Java crypto.pbkdf2(node.js)和PBEKeySpec之间密钥长度的差异

Java crypto.pbkdf2(node.js)和PBEKeySpec之间密钥长度的差异,java,node.js,encryption,interop,Java,Node.js,Encryption,Interop,我正在编写一些可互操作的代码,用于加密/解密Java和node.js之间的字符串,并设法让node.js解密Java加密的内容,这是成功解密的最后一部分:密钥 要在Java中派生密钥,我们编写: private static Key deriveSecretKey(String secretKeyAlgorithm, String secretKey, String salt) throws Exception { SecretKeyFactory factory = SecretKeyF

我正在编写一些可互操作的代码,用于加密/解密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);
});
控制台输出:

结果:超级秘密的东西-就在这里


奇怪的是,为什么在指定这两个函数之间的键长度时会有差异。谢谢

通常,密钥大小以位为单位定义。然而,大多数加密库不能很好地处理不能除以8的位大小-输出几乎总是以8位字节的八位字节为单位。因此,如果用户必须以位或八位字节字符串字节数组中的八位字节数指定大小,则由API的设计者决定


要真正了解为什么要选择位或字节,唯一的方法是询问库的设计者。在我自己的代码中,我确实尝试遵守特别的标准——因此密钥大小的位数。如果上下文中不清楚哪个是哪个,那么最好使用blockSizeBytes或blockSizeBytes等名称。当然,文档可能也有帮助,但在我看来,使用特定标识符是最好的

对我来说足够好了。假设我自己早晚会明白,但这绝对是有道理的。我注意到的另一个行为是node.js不像Java那样填充字节数组,因此int16在node.js中是2字节,而在Java中是4字节;我必须执行额外的步骤,将\u0000\u0000写入前两个字节,以便正确填充它。我猜这就是你的互操作。谢谢我真的不明白你最后关于填充的评论;我知道,如果你想在Java中为字节数组编写不同的基本类型,你可以使用ByteBuffer对其进行包装,或者如果你需要流式处理,有DataOutputStream。好的,我想我现在明白了。Java使用定义长度的基元类型,而在JavaScript/NodeJ中,整数的大小取决于值。这与问题无关。