javascript - 为什么我在nodejs native 密码中总是得到错误的des-ecb结果?

标签 javascript node.js encryption des

这是我的代码:

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 function EVP_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/

相关文章:

angular - 加密和解密本地存储值

javascript - 使用 json 解析谷歌日历数据

javascript - 如何部署从命令行运行的 Javascript 应用程序?

node.js - express js - 一个 http 请求与其他请求有何不同?

javascript - Nodejs 将值从一个模块传递到另一个模块

encryption - .pem、.cer 和 .der 之间有什么区别?

javascript - PropTypes 位置的 Redux 最佳实践

javascript - 用JS设置日期值

javascript - JSONP 在 Chrome 中工作,但在 Firefox/IE 中不起作用?

javax.crypto.BadPaddingException : unknown block type