java - Nodejs 加密字符串与 java : AES-256-CBC 不匹配

标签 java node.js encryption

嗨,我已经编写了nodejs加密和java加密,双方使用相同的算法。但 Java 和 NodeJS 返回不同的加密字符串。请在这里帮助我。

//这是我的Java代码

import java.io.UnsupportedEncodingException;
import java.security.Key;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.spec.AlgorithmParameterSpec;

    import javax.crypto.Cipher;
    import javax.crypto.spec.IvParameterSpec;
    import javax.crypto.spec.SecretKeySpec;
    import java.util.Base64;

    public enum AESUtil {
        ;
        private static final String ENCRYPTION_KEY = "RwcmlVpg";
        private static final String ENCRYPTION_IV = "4e5Wa71fYoT7MFEX";

        public static String encrypt(String src) {
            try {
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(Cipher.ENCRYPT_MODE, makeKey(), makeIv());
                Base64.Encoder encoder = Base64.getEncoder();
                return encoder.encodeToString(cipher.doFinal(src.getBytes()));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }

        public static String decrypt(String src) {
            String decrypted = "";
            try {
                Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
                cipher.init(Cipher.DECRYPT_MODE, makeKey(), makeIv());
                Base64.Decoder decoder = Base64.getDecoder();
                decrypted = new String(cipher.doFinal(decoder.decode(src)));
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            return decrypted;
        }

        static AlgorithmParameterSpec makeIv() {
            try {
                return new IvParameterSpec(ENCRYPTION_IV.getBytes("UTF-8"));
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
            return null;
        }

        static Key makeKey() {
            try {
                MessageDigest md = MessageDigest.getInstance("SHA-256");
                byte[] key = md.digest(ENCRYPTION_KEY.getBytes("UTF-8"));
                return new SecretKeySpec(key, "AES");
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }

            return null;
        }
    }

//下面是测试上面代码的代码

    public class AESMain {

        /**
         * @param args
         */
        public static void main(String[] args) {
            String src = "Hello,CryptWorld";
            String encrypted = AESUtil.encrypt(src);
            String decrypted = AESUtil.decrypt(encrypted);
            System.out.println("src: " + src);
            System.out.println("encrypted: " + encrypted);
            System.out.println("decrypted: " + decrypted);
        }

    }

上述代码的响应是

src: Hello,CryptWorld
encrypted: rh7ro9NH1XZeLX95paLETDgYxRbnDoOIrxarO0Sy73s=
decrypted: Hello,CryptWorld

//Node JS代码

var Encrypt, crypto;

crypto = require("crypto");


Encrypt = module.exports = (function() {
  var b64dec, b64enc, cipher, decrypt, encrypt, iv, key;
  key = crypto.createHash("sha256").update("RwcmlVpg").digest();
  iv = '4e5Wa71fYoT7MFEX';
  cipher = function(mode, data) {
    var encipher, encoded;
    encipher = crypto[mode]("aes-256-cbc", key, iv);
    encoded = encipher.update(data);
    encoded += encipher.final();
    return encoded;
  };
  encrypt = function(data) {
    return b64enc(cipher("createCipheriv", data));
  };
  decrypt = function(data) {
    return cipher("createDecipheriv", b64dec(data));
  };
  b64enc = function(data) {
    var b;
    b = new Buffer(data, "binary");
    return b.toString("base64");
  };
  b64dec = function(data) {
    var b;
    b = new Buffer(data, "base64");
    return b.toString("binary");
  };
  return {
    encrypt: encrypt,
    decrypt: decrypt
  };
})();
var expected = Encrypt.encrypt("Hello,CryptWorld");
console.log("expected " + expected);

Node JS 的响应是

expected /R79/f1H/XZeLX95/f39TDgY/Rb9Dv39/Rb9O0T9/Xs=

Node js 版本为 v6.10.1,JDK 版本为 1.8.0_77。

我真的不知道我错过了什么。

最佳答案

我不是 javascript 或 node.js 专家,但我认为问题在于 cipher.update()cipher.final() 返回的是 Buffer 实例,而不是字符串。因此,您必须使用 Buffer.concat(...) 来连接它们,即

cipher = function (mode, data) {
    var encipher, encoded;
    encipher = crypto[mode]("aes-256-cbc", key, iv);
    cipher1 = encipher.update(data);
    cipher2 = encipher.final();
    return  Buffer.concat([cipher1, cipher2]);
};

此外,您永远不应该使用此 String.getBytes()方法也不是这个String(byte[])任何致力于实现可移植性或互操作性的代码中的构造函数。相反,请始终显式指定字符集。我专门推荐 UTF_8,例如所以使用String.getBytes(StandardCharsets.UTF_8)new String(byte[], StandardCharsets.UTF_8) .

关于java - Nodejs 加密字符串与 java : AES-256-CBC 不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46211416/

相关文章:

java - 什么是 List 与 ArrayList?

node.js - 使用 Bower 安装软件包

java - java 中的法语字符解密适用于 Windows,但不适用于 Linux 机器

c++ - Crypto++ 异常调用 messageEnd

java - 使用 m2eclipse 开发 Web 应用程序的首选方式

Java Applet 使用 Paint 方法时遇到的问题

java - Stream 中 "filter then map"和 "map then filter"的性能是否不同?

node.js - Nodejs : Path must be a string. 收到空

javascript - 终端:% Node example.js -bash:fg:没有这样的工作

encryption - 从文件中查找加密算法