mah*_*454 5 javascript java typescript angular java-11
我想使用加密的 AES-GCM 数据(用于密码的 PBKDF2 哈希)在 java 和 typescript 之间进行通信。
我为 pbkdf2 使用了随机字节:
randomBytes(Base64): wqzowTahVBaxuxcN8vKAEUBEo0wOfcg4e6u4M9tPDFk=
Run Code Online (Sandbox Code Playgroud)
这是我的 java PBKDF2 代码:
private String salt = "1234";
private static final String KEY_ALGORITHM = "AES";
private Key generateKey(byte[] randomBytes) throws Exception {
var randomPassword = new String(randomBytes);
KeySpec keySpec = new PBEKeySpec(randomPassword.toCharArray(), salt.getBytes(), 10000, 256);
SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256");
var kdf2SecurePassword = secretKeyFactory.generateSecret(keySpec).getEncoded();
return new SecretKeySpec(kdf2SecurePassword, KEY_ALGORITHM);
}
Run Code Online (Sandbox Code Playgroud)
这是打字稿代码:
private static importKey(randomBytes: ArrayBuffer) {
return crypto.subtle.importKey(
'raw',
randomBytes,
{name: 'PBKDF2', length: 256},
true,
['deriveKey']
);
}
private generateAESKey(baseKey, salt) {
const encSalt = new TextEncoder().encode(salt);
const algorithm = {
name: 'PBKDF2',
hash: 'SHA-256',
iterations: 10000,
salt: encSalt
};
return crypto.subtle.deriveKey(
algorithm,
baseKey,
{name: 'AES-GCM', length: 256},
true,
['encrypt', 'decrypt']
);
}
Run Code Online (Sandbox Code Playgroud)
结果在 java 和 typescript :
Java Key : hrG2Hw/bec9JoI+EcemfUxR/5lGw718kYOcCWRRbulk=
typescript Key : EGPcTUQUmYpNHoCDuD7rkIVaHkPSqEZYan4HnWfhFSc=
Run Code Online (Sandbox Code Playgroud)
为什么我有不同的结果?
代码的哪一部分有问题?
更新
有趣,我尝试使用 linuxnettle-pbkdf2命令生成 pbkdf2 密钥,结果与 javascript 输出完全匹配:
USERNAME@HOSTNAME:~$ echo -n "wqzowTahVBaxuxcN8vKAEUBEo0wOfcg4e6u4M9tPDFk=" | base64 -d | nettle-pbkdf2 -i 10000 -l 32 --raw "1234" | base64
EGPcTUQUmYpNHoCDuD7rkIVaHkPSqEZYan4HnWfhFSc=
Run Code Online (Sandbox Code Playgroud)
经过在互联网上的大量研究并比较了 3 种编程语言(Java、Javascript、Python)和 linu nettle-pbkdf2 命令。
我注意到 Java JCE 和 Bouncycastle 在 PBKDF2 算法实现中存在错误。
这是Python示例代码:
#!/usr/bin/python3
import base64
import hashlib
b64 = "wqzowTahVBaxuxcN8vKAEUBEo0wOfcg4e6u4M9tPDFk="
bytePass = base64.b64decode(b64)
key = hashlib.pbkdf2_hmac('sha256', bytePass, '1234'.encode(), 10000, 32)
keyB64 = base64.b64encode(key)
print(keyB64)
Run Code Online (Sandbox Code Playgroud)
javascript 和 linux nettle-pbkdf2 命令的结果相同:
EGPcTUQUmYpNHoCDuD7rkIVaHkPSqEZYan4HnWfhFSc=
Run Code Online (Sandbox Code Playgroud)
在java中,当我将randomBytes更改为简单的字符串时Password123456,结果是java,javascript,python是类似的。
Java : nCpOvPbsb62/jfYIlPClEEGNzpD7Wt/qwkIC00Rkx24=
JavaScript : nCpOvPbsb62/jfYIlPClEEGNzpD7Wt/qwkIC00Rkx24=
Python : nCpOvPbsb62/jfYIlPClEEGNzpD7Wt/qwkIC00Rkx24=
Run Code Online (Sandbox Code Playgroud)
注意:实际上我的示例代码中的 randomBits 是 ECDH 共享秘密。我认为Java无法计算PBKDF2上的某些位或实现有问题。
无论如何,我从PBKDF2迁移到Argon2。
更新
此 PBKDF2 源代码在 java 中工作没有任何问题:PBKDF2 源代码