简体   繁体   English

使用 libsodium 加密,需要使用 crypto_box_keypair 生成公钥和私钥

[英]Encryption using libsodium and need to generate public and private keys using crypto_box_keypair

I have been working with the libsodium library to implement Shamir secret sharing and trying to test the implementation done by dark crystal我一直在使用 libsodium 库来实现 Shamir 秘密共享并尝试测试由暗水晶完成的实现

https://gitlab.com/dark-crystal-javascript/key-backup-crypto/-/blob/master/example.js https://gitlab.com/dark-crystal-javascript/key-backup-crypto/-/blob/master/example.js

Implementation is something like this实现是这样的

function encryptionKeypair () {
    const keypair = {
      publicKey: sodium.sodium_malloc(sodium.crypto_box_PUBLICKEYBYTES),
      secretKey: sodium.sodium_malloc(sodium.crypto_box_SECRETKEYBYTES)
    }
    sodium.crypto_box_keypair(keypair.publicKey, keypair.secretKey)
    return keypair
  },

 function oneWayBox (message, publicKey) {
    console.log('in one way box');
    const curvePublicKey = sodium.sodium_malloc(sodium.crypto_box_PUBLICKEYBYTES)
    // console.log('curvePublicKey', curvePublicKey.toString('hex'));
    console.log('curvePublicKey', curvePublicKey.length);
    console.log('publicKey', publicKey.length);
    
    sodium.crypto_sign_ed25519_pk_to_curve25519(curvePublicKey, publicKey)

    // console.log('curvePublicKey', curvePublicKey.toString('hex'));


    console.log('in one way box');
    console.log('\n');

    const ephemeral = this.encryptionKeypair()
    const nonce = this.randomBytes(sodium.crypto_box_NONCEBYTES)
    const cipherText = sodium.sodium_malloc(message.length + sodium.crypto_box_MACBYTES)
  
    sodium.crypto_box_easy(cipherText, message, nonce, curvePublicKey, ephemeral.secretKey)
    zero(ephemeral.secretKey)
    zero(message)
    return Buffer.concat([nonce, ephemeral.publicKey, cipherText])
  },

below is Secret-sharing-generation.js下面是 Secret-sharing-generation.js

const secrets = require('secret-sharing')
const s = require('.')

const secret = 'My secret key'
const label = ''

console.log('Secret to share:', secret.toString('hex'))

console.log(`Packing with label: '${label}'`)
const packedSecret = s.packLabel(secret, label)
console.log(`Packed secret: ${packedSecret.toString('hex')}`)
console.log(`Length of packed secret is ${packedSecret.length} bytes.`)
const signingKeypair = s.keypair()
const encryptionKeypair = s.signingKeypairToEncryptionKeypair(signingKeypair)

const custodians = []
for (let i = 0; i < 5; i++) {
  custodians.push(s.encryptionKeypair())
}


console.log('custodians', custodians);

console.log('Creating 5 shares, 3 needed to recover')
secrets.share(packedSecret, 5, 3).then((shards) => {
  console.log('Shards:')
  console.log(shards.map(s => s.toString('hex')))
  console.log('Signed shards:')
  const signedShards = s.signShards(shards, signingKeypair)
  console.log(signedShards.map(s => s.toString('hex')))

  const boxedShards = signedShards.map((shard, i) => {
    return s.oneWayBox(shard, custodians[i].publicKey)
  })

  console.log('Boxed shards:')
  console.log(boxedShards.map(s => s.toString('hex')))
  console.log(`Length of boxed shards are ${boxedShards[0].length} bytes.`)
  secrets.combine(shards.slice(2)).then((result) => {
    console.log('Result of recombining 3 shares:', result.toString())
  })
})

Now the problem is when I am using encryptionKeypair function to generate key pair for and then after that when I am trying to generate to do crypto_sign_ed25519_sk_to_curve25519 using the key pair generated in this encryptionKeypair function I am getting现在的问题是,当我使用encryptionKeypair function 生成密钥对时,然后当我尝试使用此encryptionKeypair function 中生成的密钥对生成执行crypto_sign_ed25519_sk_to_curve25519

UnhandledPromiseRejectionWarning: Error: ENOMEM, Cannot allocate memory

I have checked my swap space it is completely free我检查了我的交换空间它是完全免费的

           total        used        free      shared  buff/cache   available
Mem:           3138          83        2896           0         158        2908
Swap:          5119           0        5119

I am not able to understand what is the issue.我无法理解问题所在。

It's not clear to me why you want to convert a key pair created with encryptionKeypair() with crypto_sign_ed25519_sk_to_curve25519() or crypto_sign_ed25519_pk_to_curve25519() .我不清楚为什么要将使用encryptionKeypair()创建的密钥对转换为crypto_sign_ed25519_sk_to_curve25519()crypto_sign_ed25519_pk_to_curve25519()

The latter two methods convert a secret or public Ed25519 key (used in the context of signing) to a secret or public X25519 key (used in the context of key exchange).后两种方法将秘密或公共 Ed25519 密钥(在签名上下文中使用)转换为秘密或公共 X25519 密钥(在密钥交换上下文中使用)。

encryptionKeypair() applies crypto_box_keypair() and thus already creates an X25519 key pair, so conversion is not necessary (and not possible). encryptionKeypair()应用crypto_box_keypair()并因此已经创建了一个 X25519 密钥对,因此不需要(也不可能)进行转换。

A working use of the conversion methods would be, eg using crypto_sign_keypair() , which generates an Ed25519 key pair:转换方法的一个工作用途是,例如使用crypto_sign_keypair() ,它生成一个 Ed25519 密钥对:

var sodium = require('sodium-native');
...
var ed25519KeyPair = signingKeypair() // Create an Ed25519 keypair
var x25519KeyPair = {
    publicKey: sodium.sodium_malloc(sodium.crypto_box_PUBLICKEYBYTES),
    secretKey: sodium.sodium_malloc(sodium.crypto_box_SECRETKEYBYTES)
}
sodium.crypto_sign_ed25519_pk_to_curve25519(x25519KeyPair.publicKey, ed25519KeyPair.publicKey) // Convert the public Ed25519 into a public X25519 key
sodium.crypto_sign_ed25519_sk_to_curve25519(x25519KeyPair.secretKey, ed25519KeyPair.secretKey) // Convert the secret Ed25519 into a secret X25519 key
console.log(x25519KeyPair.publicKey)
console.log(x25519KeyPair.secretKey)

function signingKeypair () {
    const keypair = {
        publicKey: sodium.sodium_malloc(sodium.crypto_sign_PUBLICKEYBYTES),
        secretKey: sodium.sodium_malloc(sodium.crypto_sign_SECRETKEYBYTES)
    }
    sodium.crypto_sign_keypair(keypair.publicKey, keypair.secretKey)
    return keypair
}

Also, I can't reproduce the posted error message.此外,我无法重现发布的错误消息。 When using encryptionKeypair() instead of signingKeypair() , I get the following error message Error: public key conversion failed .当使用encryptionKeypair()而不是signingKeypair()时,我收到以下错误消息Error: public key conversion failed

Edit:编辑:

In the 2nd code snippet, the custodians ' key pairs are created with s.encryptionKeypair() , which produces X25519 key pairs.在第二个代码片段中, custodians的密钥对是使用s.encryptionKeypair()创建的,它会生成 X25519 密钥对。 In the later called s.oneWayBox() it is then tried to convert the public keys with crypto_sign_ed25519_pk_to_curve25519() , which must fail as described above.在后面调用的s.oneWayBox()中,然后尝试使用crypto_sign_ed25519_pk_to_curve25519()转换公钥,如上所述,这必须失败。

Presumably this is a bug!估计这是一个错误! A possible fix is to generate the custodians ' key pairs with s.keypair() (or signingKeypair() ), which creates Ed25519 key pairs.一种可能的解决方法是使用s.keypair() (或signingKeypair() )生成custodians的密钥对,这会创建 Ed25519 密钥对。 The public keys can then be successfully converted to X25519 keys in s.oneWayBox() .然后可以在s.oneWayBox()中成功地将公钥转换为 X25519 密钥。 With this change, oneWayBox() runs without any errors on my machine.通过此更改, oneWayBox()在我的机器上运行时不会出现任何错误。

This change to Ed25519 key pairs is also consistent with the description of encryptionKeypair() , which states that this method is only used when generating ephemeral keys, eg in oneWayBox() .对 Ed25519 密钥对的这种更改也与encryptionKeypair()的描述一致,该描述表明该方法仅在生成临时密钥时使用,例如在oneWayBox()中。 In all other cases it is internally derived from Ed25519 keys.在所有其他情况下,它是从 Ed25519 密钥内部派生的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM