使用 NodeJs Crypto 将 Java 加密转换为 Java 脚本
Converting Java Encryption to Javascript with NodeJs Crypto
我有一个 Java 加密密码的代码,如下所示。我尝试将其转换为 Javascript 但出现错误:
Error [ERR_CRYPTO_HASH_FINALIZED]: Digest already called
我发现了一些类似的问题和答案说;将 hash.update() 放入您的 for 但结果将不同于 Java.
我该如何解决这个问题?我怎样才能在 Java 脚本中获得与 Java 相同的结果? :/
Java
public String encryptNew(String password, String salt) throws IOException, NoSuchAlgorithmException {
byte[] saltBytes = base64ToByte(salt);
byte[] encryptedBytes = getHash(password, saltBytes);
String result = byteToBase64(encryptedBytes);
return result;
}
private byte[] getHash(String password, byte[] salt) throws NoSuchAlgorithmException,
UnsupportedEncodingException {
MessageDigest digest = MessageDigest.getInstance("SHA-512");
digest.reset();
digest.update(salt);
byte[] input = digest.digest(password.getBytes("UTF-8"));
for (int i = 0; i < 1000; i++) {
digest.reset();
input = digest.digest(input);
}
return input;
}
我的Java脚本
const pass = '12344321';
const salt = 'X9geKit5sd0=';
// 1. ToByte
const saltBytes = Buffer.from(salt, 'base64');
console.log('Salt:', saltBytes);
// 2. Hash
let hash = crypto.createHash('sha512');
hash.update(saltBytes);
var input = new TextEncoder();
input.encode(pass);
for (let i = 0; i < 1000; i++) {
input = hash.digest(input);
}
// 3. ToBase64
const result = Buffer.from(input).toString('base64');
console.log('Result:', result);
node.js 中 Hash
对象的方法签名与 Java 中的 MessageDigest
完全不同。您只能通过 update
将数据输入其中。由于没有 reset
,您每次都需要使用新的 Hash
实例。
这是产生预期结果的完整代码:
let crypto = require('crypto');
const pass = '12344321';
const salt = 'X9geKit5sd0=';
// 1. ToByte
const saltBytes = Buffer.from(salt, 'base64');
// 2. Hash
let hash = crypto.createHash('sha512');
hash.update(saltBytes);
hash.update(Buffer.from(pass, 'utf8'));
let input = hash.digest();
for (let i = 0; i < 1000; i++) {
hash = crypto.createHash('sha512');
hash.update(input);
input = hash.digest();
}
// 3. ToBase64
const result = Buffer.from(input).toString('base64');
console.log('Result:', result);
请记住,这会快速散列您的密码,其中盐仅用于第一次迭代。最好使用已建立的密码散列方法,例如 Argon2、scrypt、bcrypt 或 PBKDF2,工作因数高。
我有一个 Java 加密密码的代码,如下所示。我尝试将其转换为 Javascript 但出现错误:
Error [ERR_CRYPTO_HASH_FINALIZED]: Digest already called
我发现了一些类似的问题和答案说;将 hash.update() 放入您的 for 但结果将不同于 Java.
我该如何解决这个问题?我怎样才能在 Java 脚本中获得与 Java 相同的结果? :/
Java
public String encryptNew(String password, String salt) throws IOException, NoSuchAlgorithmException {
byte[] saltBytes = base64ToByte(salt);
byte[] encryptedBytes = getHash(password, saltBytes);
String result = byteToBase64(encryptedBytes);
return result;
}
private byte[] getHash(String password, byte[] salt) throws NoSuchAlgorithmException,
UnsupportedEncodingException {
MessageDigest digest = MessageDigest.getInstance("SHA-512");
digest.reset();
digest.update(salt);
byte[] input = digest.digest(password.getBytes("UTF-8"));
for (int i = 0; i < 1000; i++) {
digest.reset();
input = digest.digest(input);
}
return input;
}
我的Java脚本
const pass = '12344321';
const salt = 'X9geKit5sd0=';
// 1. ToByte
const saltBytes = Buffer.from(salt, 'base64');
console.log('Salt:', saltBytes);
// 2. Hash
let hash = crypto.createHash('sha512');
hash.update(saltBytes);
var input = new TextEncoder();
input.encode(pass);
for (let i = 0; i < 1000; i++) {
input = hash.digest(input);
}
// 3. ToBase64
const result = Buffer.from(input).toString('base64');
console.log('Result:', result);
node.js 中 Hash
对象的方法签名与 Java 中的 MessageDigest
完全不同。您只能通过 update
将数据输入其中。由于没有 reset
,您每次都需要使用新的 Hash
实例。
这是产生预期结果的完整代码:
let crypto = require('crypto');
const pass = '12344321';
const salt = 'X9geKit5sd0=';
// 1. ToByte
const saltBytes = Buffer.from(salt, 'base64');
// 2. Hash
let hash = crypto.createHash('sha512');
hash.update(saltBytes);
hash.update(Buffer.from(pass, 'utf8'));
let input = hash.digest();
for (let i = 0; i < 1000; i++) {
hash = crypto.createHash('sha512');
hash.update(input);
input = hash.digest();
}
// 3. ToBase64
const result = Buffer.from(input).toString('base64');
console.log('Result:', result);
请记住,这会快速散列您的密码,其中盐仅用于第一次迭代。最好使用已建立的密码散列方法,例如 Argon2、scrypt、bcrypt 或 PBKDF2,工作因数高。