为什么我总是在nodejs本机密码中弄错des-ecb结果?



这是我的代码:

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');
}

但我得到的结果是:

=================

>>>>输入 STR : 16CE7F2DEB9BB56D

我在这个网络上测试的正确结果:http://tool.chacuo.net/cryptdes

去模式:欧洲央行

填充模式:PKCS7填充

密码:测试密钥

输出:十六进制

正确的结果(与我的 java 代码相同(是

832e52EBD3FB9059

我的节点版本是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 以及没有密钥派生是不安全的(,您正在使用已弃用的crypto.createCipher()函数,该函数从提供的密码派密钥。

crypto.createCipher()的实现使用 OpenSSL 函数派密钥,EVP_BytesToKey摘要算法设置为MD5,一次迭代,无盐。缺少盐允许字典攻击,因为相同的密码总是创建相同的密钥。低迭代次数和非加密安全哈希算法允许非常快速地测试密码。

请改用crypto.createCipheriv(),它按原样使用提供的密钥:

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);

createCipherivAPI 将拒绝您的 9 字节长密钥,因为 DES 需要 8 字节密钥。我做了一个解决方法,从提供的密码中获取前 8 个字节作为密钥,现在它正在打印您想要的结果。

输出:

===============>>>> ENTER STR : 832E52EBD3FB9059

最新更新