使用 libsodium 加密并需要使用 crypto_box_keypair 生成 public 和私钥
Encryption using libsodium and need to generate public and private keys using crypto_box_keypair
我一直在使用 libsodium 库来实现 Shamir 秘密共享,并尝试测试 dark crystal
完成的实现
https://gitlab.com/dark-crystal-javascript/key-backup-crypto/-/blob/master/example.js
实现是这样的
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])
},
下面是揭秘-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())
})
})
现在的问题是,当我使用 encryptionKeypair
函数生成密钥对时,然后当我尝试使用此 [=] 中生成的密钥对生成 crypto_sign_ed25519_sk_to_curve25519
时15=] 我得到的函数
UnhandledPromiseRejectionWarning: Error: ENOMEM, Cannot allocate memory
我检查了我的交换 space 它是完全免费的
total used free shared buff/cache available
Mem: 3138 83 2896 0 158 2908
Swap: 5119 0 5119
我无法理解问题所在。
我不清楚为什么要将使用 encryptionKeypair()
创建的密钥对转换为 crypto_sign_ed25519_sk_to_curve25519()
or crypto_sign_ed25519_pk_to_curve25519()
。
后两种方法将秘密或 public Ed25519 密钥(在签名上下文中使用)转换为秘密或 public X25519 密钥(在密钥交换上下文中使用)。
encryptionKeypair()
应用 crypto_box_keypair()
因此 已经 创建了一个 X25519 密钥对,因此不需要(也不可能)进行转换。
转换方法的有效用途是,例如使用 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
}
此外,我无法重现发布的错误消息。当使用 encryptionKeypair()
而不是 signingKeypair()
时,我收到以下错误消息 Error: public key conversion failed.
编辑:
在第二个代码片段中,custodians
' 密钥对是使用 s.encryptionKeypair()
创建的,这会生成 X25519 密钥对。在稍后调用的 s.oneWayBox()
中,它会尝试将 public 键转换为 crypto_sign_ed25519_pk_to_curve25519()
,这一定会失败,如上所述。
推测这是一个错误!一种可能的修复方法是使用 s.keypair()
(或 signingKeypair()
)生成 custodians
' 密钥对,这会创建 Ed25519 密钥对。然后 public 密钥可以成功转换为 s.oneWayBox()
中的 X25519 密钥。通过此更改,oneWayBox()
在我的机器上运行时没有任何错误。
对 Ed25519 密钥对的这种更改也与 encryptionKeypair()
的描述一致,其中指出此方法仅在生成临时密钥时使用,例如在 oneWayBox()
。在所有其他情况下,它在内部派生自 Ed25519 密钥。
我一直在使用 libsodium 库来实现 Shamir 秘密共享,并尝试测试 dark crystal
完成的实现https://gitlab.com/dark-crystal-javascript/key-backup-crypto/-/blob/master/example.js
实现是这样的
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])
},
下面是揭秘-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())
})
})
现在的问题是,当我使用 encryptionKeypair
函数生成密钥对时,然后当我尝试使用此 [=] 中生成的密钥对生成 crypto_sign_ed25519_sk_to_curve25519
时15=] 我得到的函数
UnhandledPromiseRejectionWarning: Error: ENOMEM, Cannot allocate memory
我检查了我的交换 space 它是完全免费的
total used free shared buff/cache available
Mem: 3138 83 2896 0 158 2908
Swap: 5119 0 5119
我无法理解问题所在。
我不清楚为什么要将使用 encryptionKeypair()
创建的密钥对转换为 crypto_sign_ed25519_sk_to_curve25519()
or crypto_sign_ed25519_pk_to_curve25519()
。
后两种方法将秘密或 public Ed25519 密钥(在签名上下文中使用)转换为秘密或 public X25519 密钥(在密钥交换上下文中使用)。
encryptionKeypair()
应用 crypto_box_keypair()
因此 已经 创建了一个 X25519 密钥对,因此不需要(也不可能)进行转换。
转换方法的有效用途是,例如使用 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
}
此外,我无法重现发布的错误消息。当使用 encryptionKeypair()
而不是 signingKeypair()
时,我收到以下错误消息 Error: public key conversion failed.
编辑:
在第二个代码片段中,custodians
' 密钥对是使用 s.encryptionKeypair()
创建的,这会生成 X25519 密钥对。在稍后调用的 s.oneWayBox()
中,它会尝试将 public 键转换为 crypto_sign_ed25519_pk_to_curve25519()
,这一定会失败,如上所述。
推测这是一个错误!一种可能的修复方法是使用 s.keypair()
(或 signingKeypair()
)生成 custodians
' 密钥对,这会创建 Ed25519 密钥对。然后 public 密钥可以成功转换为 s.oneWayBox()
中的 X25519 密钥。通过此更改,oneWayBox()
在我的机器上运行时没有任何错误。
对 Ed25519 密钥对的这种更改也与 encryptionKeypair()
的描述一致,其中指出此方法仅在生成临时密钥时使用,例如在 oneWayBox()
。在所有其他情况下,它在内部派生自 Ed25519 密钥。