jwk 保存到文件中,例如:
let jwk = keyObject.export({format:'jwk'})
fs.writeFileSync(JWK_PATH, JSON.stringify(jwk));
但是如何将 jwk 字符串解析回
KeyObject
?
KeyObject.from(jwkString)
抛出TypeError [ERR_INVALID_ARG_TYPE]: The "key" argument must be an instance of CryptoKey.
。
let
key = createSecretKey(jwkString,'base64url');
使用无效的密钥长度创建错误结果。
如果我只传递 JWK 的“k”属性,但
createCipheriv
接受 createCipheriv
,那么我将成功地将密钥传递给 KeyObjects
方法,并且将密钥保存在(秘密)KeyObject
中似乎是最佳实践
而不是字符串?除了 WebCrypto/Subtle 模块之外,我找不到导入?
对称密钥最终只是一个字节序列(原始或使用二进制到文本编码进行编码)。对于 JWK 格式的对称密钥(例如此处),原始密钥以 Base64url 编码存储在
k
(密钥值)中。
因此可以使用(
here)轻松导入到
KeyObject
(更准确地说是SecretKeyObject
):
crypto.createSecretKey(aesKeyJwk.k, 'base64url')
示例:
var crypto = require('crypto')
// Generate symmetric 32 bytes AES key for AES-256, wrapped in SecretKeyObject
var aesKey = crypto.generateKeySync('aes', {length: 256})
// Export as JWK
var aesKeyJwk = aesKey.export({format: 'jwk'})
// Import JWK into a SecretKeyObject
var aesKeyReloaded = crypto.createSecretKey(aesKeyJwk.k, 'base64url')
// Test
var plaintext = Buffer.from('The quick brown fox jumps over the lazy dog', 'utf8')
var iv = crypto.randomBytes(16)
var cipher = crypto.createCipheriv('aes-256-cbc', aesKey, iv) // encrypt with aeskey
var ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()])
var decipher = crypto.createDecipheriv('aes-256-cbc', aesKeyReloaded, iv) // decrypt with aesKeyReloaded, proving that the same raw key is wrapped
var decryptedText = Buffer.concat([decipher.update(ciphertext), decipher.final()])
// Output
console.log(aesKey) // SecretKeyObject { [Symbol(kKeyType)]: 'secret' }
console.log(aesKeyJwk) // e.g. { kty: 'oct', k: 'Y4mR6UP1NmI0TS3uVu9F6SWCb-lvQhlykFqPFATQ3vo' } // k (key value) contains the Base64 url encoded raw key, kty contains the key type, oct (octet secuence) denotes a symmetric key
console.log(aesKeyReloaded) // SecretKeyObject { [Symbol(kKeyType)]: 'secret' }
console.log(decryptedText.toString('utf8')) // The quick brown fox jumps over the lazy dog