这是我的代码:
const crypto = require('crypto')
let enterJS = 'h';
let enterStr = null;
enterStr = encrypt(enterJS, 'des-ecb').toUpperCase();
console.log("===============>>>> ENTER STR : " + enterStr);
function encrypt(plaintext, algorithm) {
var keyStr = "imtestKey";
var key = new Buffer(keyStr);
var cipher = crypto.createCipher(algorithm, key);
cipher.setAutoPadding(true);
var ciph = cipher.update(plaintext, 'ascii');
var ciphf = cipher.final();
return ciph.toString('hex') + ciphf.toString('hex');
}
但是我得到的结果是:
===============>>>> ENTER STR : 16CE7F2DEB9BB56D
我在这个网站上测试的正确结果是:http://tool.chacuo.net/cryptdes
des-mode:ecb
fill-mode:pkcs7padding
password:imtestKey
output:hex
正确的结果(与我的java代码相同)是
832e52ebd3fb9059
我的 Node 版本是v8.9.0,如何才能得到正确的结果?
这是我的java代码:
import java.lang.StringBuilder;
import javax.crypto.Cipher;
import java.security.SecureRandom;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.SecretKeyFactory;
import javax.crypto.SecretKey;
public class Test {
public static void main(String[] args) {
String js = "h";
try {
byte[] bs = encrypt(js.getBytes(), "imtestKey".getBytes());
System.out.println(byte2hex(bs));
} catch(Exception ex) {
}
}
public static byte[] encrypt(byte[] src, byte[] key) throws Exception {
SecureRandom sr = new SecureRandom();
DESKeySpec dks = new DESKeySpec(key);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
SecretKey securekey = keyFactory.generateSecret(dks);
Cipher cipher = Cipher.getInstance("DES");
cipher.init(Cipher.ENCRYPT_MODE, securekey, sr);
return cipher.doFinal(src);
}
public static String byte2hex(byte[] b) {
StringBuilder sb = new StringBuilder();
String stmp = "";
for(int n = 0; b != null && n < b.length; ++n) {
stmp = Integer.toHexString(b[n] & 255);
if (stmp.length() == 1) {
sb.append("0").append(stmp);
} else {
sb.append(stmp);
}
}
return sb.toString().toUpperCase();
}
}
最佳答案
除了安全方面(正如已经指出的,DES 和 ECB,以及没有 key 派生是不安全的),您正在使用已弃用的 crypto.createCipher()
函数从提供的密码派生 key 。
The implementation of
crypto.createCipher()
derives keys using the OpenSSL functionEVP_BytesToKey
with the digest algorithm set to MD5, one iteration, and no salt. The lack of salt allows dictionary attacks as the same password always creates the same key. The low iteration count and non-cryptographically secure hash algorithm allow passwords to be tested very rapidly.
使用crypto.createCipheriv()
相反,它按原样使用提供的 key :
const crypto = require('crypto')
let enterJS = 'h';
let enterStr = null;
function encrypt(plaintext, algorithm) {
var keyStr = "imtestKey";
var key = Buffer.alloc(8, keyStr);
var cipher = crypto.createCipheriv(algorithm, key, Buffer.alloc(0));
cipher.setAutoPadding(true);
var ciph = cipher.update(Buffer.from(plaintext));
var ciphf = cipher.final();
return Buffer.concat([ciph, ciphf]).toString('hex');
}
enterStr = encrypt(enterJS, 'des-ecb').toUpperCase();
console.log("===============>>>> ENTER STR : " + enterStr);
createCipheriv
API 将拒绝您的 9 字节长 key ,因为 DES 需要 8 字节 key 。我采取了一种解决方法,将提供的密码中的前 8 个字节作为 key ,现在它正在打印您想要的结果。
输出:
===============>>>> ENTER STR : 832E52EBD3FB9059
关于javascript - 为什么我在nodejs native 密码中总是得到错误的des-ecb结果?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52516095/