Javascript 节点JS中的AES加密/解密类似于Java

Javascript 节点JS中的AES加密/解密类似于Java,javascript,java,node.js,cryptography,cryptojs,Javascript,Java,Node.js,Cryptography,Cryptojs,我试图在节点JS中复制AES加密和解密的Java代码 Java代码 SecretKeySpec skeySpec; String key = "a4e1112f45e84f785358bb86ba750f48"; public void encryptString(String key) throws Exception { try { skeySpec = new SecretKeySpec(key.getBytes(), "A

我试图在节点JS中复制AES加密和解密的Java代码

Java代码

    SecretKeySpec skeySpec;
    String key = "a4e1112f45e84f785358bb86ba750f48";

    public void encryptString(String key) throws Exception {
        try {
            skeySpec = new SecretKeySpec(key.getBytes(), "AES");
            cipher = Cipher.getInstance("AES");
            cipher.init(1, skeySpec);
            byte encstr[] = cipher.doFinal(message.getBytes());
            String encData = new String(encstr, "UTF-8");
            System.out.println(encData);
        } catch (NoSuchAlgorithmException nsae) {
            throw new Exception("Invalid Java Version");
        } catch (NoSuchPaddingException nse) {
            throw new Exception("Invalid Key");
        }
    }
节点JS

    var encryptKey = function (text) {
        var cipher = crypto.createCipher('aes256', 'a4e1112f45e84f785358bb86ba750f48');
        var crypted = cipher.update(text,'utf8', 'hex')
        crypted += cipher.final('hex');
        console.log(crypted);
        return crypted;
    }

我无法在节点JS中获得确切的密码文本,我在Java中获得了该密码文本。在这两种情况下,您的代码实际上使用了不同的加密参数。AES是一种分组密码,它采用:要加密的纯文本、初始化向量(也称为IV)(与纯文本一起使用)和加密密钥

在Java中,IV显然是在init()上自动生成的——来自Cipher.init的Java SE平台文档:

可以使用getParameters或getIV检索生成的参数 (如果参数为IV)

在Node.js中,如果使用弃用的createCipher函数,IV将根据提供的密钥自动生成,可能与Java中的方式不同,因此您将获得不同的密码文本。但是,您应该使用未弃用的crypto.createCipheriv变体

为了准确复制密码文本,您应该:

  • 在两侧使用相同的加密算法-最好精确地指定这一点,例如aes-256-cbc,或者像aes-256-gcm这样的经过身份验证的加密方案,后者更难使用,但提供消息身份验证
  • 在Java的初始化参数中提供相同的IV,并在节点中使用createCipheriv在两侧使用相同的IV;尽管要小心,但在生产过程中,您应该始终随机化它!看

作为结束语,当使用块加密时,通常会生成安全的随机IVs,这意味着密文将始终彼此不同,即使是相同的明文。这是一件好事!它可以保护您的有效负载不受攻击者的攻击,攻击者会观察加密数据并根据消息重复得出结论。

最后,在查看Java文档和Node JS Crypto Docs后,成功获得了结果。 我们必须使用
crypto.createCipheriv()
而不是带有iv的
crypto.createCipheriv
。 这里iv将是
null

代码:

    let crypto = require('crypto');

    var iv = new Buffer.from('');   //(null) iv 
    var algorithm = 'aes-256-ecb';
    var password = 'a4e1112f45e84f785358bb86ba750f48';      //key password for cryptography

    function encrypt(buffer){
        var cipher = crypto.createCipheriv(algorithm,new Buffer(password),iv)
        var crypted = Buffer.concat([cipher.update(buffer),cipher.final()]);
        return crypted;
    }

    console.log(encrypt(new Buffer('TextToEncrypt')).toString())

嘿,这是另一个加密的例子,所有的东西都出了问题。ECB模式,密钥为字符串(十六进制,但未解码),糟糕的异常处理,甚至未记录原因,使用错误消息和使用异常等,明文编码错误,为什么不使用ECB进行传输模式安全。每行至少有一个错误,不要使用上面的代码。答案很好,尽管Nodejs文档中说可以安全地公开IV,但在数据库中存储加密文本时,使用加密文本公开IV是否仍然安全?看看这个例子:另外,你真的希望每次加密都生成一个新的IV吗?啊哈,我在进一步搜索后找到了我的答案。