我正在研究一些可互操作的代码,用于加密/解密Java和node.js之间的字符串,并设法让node.js解密Java加密的内容,这是成功解密的最后一部分:密钥。
要在Java中派生密钥,我们写:
private static Key deriveSecretKey(String secretKeyAlgorithm, String secretKey, String salt) throws Exception {
SecretKeyFactory factory = SecretKeyFactory.getInstance(SECRET_KEY_FACTORY_ALGORITHM);
KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), char2byte(salt), 65536, 128);
SecretKey tmp = factory.generateSecret(spec);
SecretKey secret = new SecretKeySpec(tmp.getEncoded(), secretKeyAlgorithm);
return secret;
}
请注意,传递给PBEKeySpec()的密钥长度为128。但是,在node.js中,如果我尝试使用128并且实际上必须在此处使用16,则会得到“无效密钥长度”:
crypto.pbkdf2(key_value, salt_value, 65536, 16, function(err, key) {
var decipher = crypto.createDecipheriv('aes-128-cbc', key, iv);
// decipher.setAutoPadding(false);
var decoded = decipher.update(ciphertext, 'binary', 'utf8');
decoded += decipher.final('utf8');
console.log('Result: ' + decoded);
});
控制台输出:
结果:超级秘密 - 就在这里。
很好奇为什么在指定这两个函数之间的密钥长度时存在差异。谢谢!
答案 0 :(得分:0)
通常,密钥大小以位为单位定义。但是,大多数加密库都不能处理不能被8分割的位大小 - 输出几乎总是以八位字节(8位字节)为单位。因此,如果用户必须指定位的大小,或八位字符串(字节数组)中的八位字节数,则由API的设计者决定。
真正了解为什么选择位或字节的唯一方法是询问设计库的人。在我自己的代码中,我确实尝试遵循(ad-hoc)标准 - 所以对于密钥大小的位。如果从上下文中不清楚哪个,最好使用blockSizeBits
或blockSizeBytes
之类的名称。当然,文档也可能有所帮助,但在我看来,使用特定标识符是最好的。