在节点中encryption并在java中解密

我有一个在Java中的encryption代码。 我试图将encryption部分移植到节点。 基本上,节点将使用encryption模块进行encryption,然后Java将执行解密。

以下是我如何在Java中进行encryption:

protected static String encrypt(String plaintext) { final byte[] KEY = { 0x6d, 0x79, 0x56, 0x65, 0x72, 0x79, 0x54, 0x6f, 0x70, 0x53, 0x65, 0x63, 0x72, 0x65, 0x74, 0x4b }; try { Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); final SecretKeySpec secretKey = new SecretKeySpec(KEY, "AES"); cipher.init(Cipher.ENCRYPT_MODE, secretKey); final String encryptedString = Base64.encodeToString( cipher.doFinal(plaintext.getBytes()), Base64.DEFAULT); return encryptedString; } catch (Exception e) { return null; } } 

以下是我如何在节点中进行encryption:

 var crypto = require('crypto'), key = new Buffer('6d7956657279546f705365637265744b', 'hex'), cipher = crypto.createCipher('aes-128-ecb', key), chunks = []; cipher.setAutoPadding(true); chunks.push(cipher.update( new Buffer(JSON.stringify({someKey: "someValue"}), 'utf8'), null, 'base64')); chunks.push(cipher.final('base64')); var encryptedString = chunks.join(''); 

在Java中,我得到stringT4RlJo5ENV8h1uvmOHzz1KjyXzBoBuqVLSTHsPppljA= 。 这被正确解密。 然而,在节点中,我得到了al084hEpTK7gOYGQRSGxF+WWKvNYhT4SC7MukrzHieM=这是明显不同的,因此它不会被正确解密。

我试图寻找与我有同样问题的人,而这个 github问题是我能find的最接近的问题。 正如那个问题所build议的,我尝试运行openssl像这样:

 $ echo -e '{"someKey": "someValue"}' | openssl enc -a -e -aes-128-ecb -K "6d7956657279546f705365637265744b" T4RlJo5ENV8h1uvmOHzz1MY2bhoFRHZ+ClxsV24l2BU= 

我得到的结果已经足够接近由java生成的,但仍然不同:

 T4RlJo5ENV8h1uvmOHzz1MY2bhoFRHZ+ClxsV24l2BU= // openssl T4RlJo5ENV8h1uvmOHzz1KjyXzBoBuqVLSTHsPppljA= // java al084hEpTK7gOYGQRSGxF+WWKvNYhT4SC7MukrzHieM= // node 

这使我想到了如何使节点输出与我的java代码一样的encryptionstring? 我只能在节点中更改我的代码,而不是在java中。

最后,我find了解决我的问题。 感谢这家伙。 解决scheme的关键是初始化向量。 引用的要点:

// ECB模式不需要IV,所以保持这样,它会工作。

以下是解决scheme的样子:

 var crypto = require('crypto'), iv = new Buffer(''), key = new Buffer('6d7956657279546f705365637265744b', 'hex'), cipher = cypto.createCipheriv('aes-128-ecb', key, iv), chunks = []; chunks.push(cipher.update( new Buffer(JSON.stringify({someKey: "someValue"}), 'utf8'), 'buffer', 'base64')); chunks.push(cipher.final('base64')); var encryptedString = chunks.join(''); 

在Node.Js中encryption并在Java中解密的工作示例:

encryption:

 var crypto = require('crypto') var cipher = crypto.createCipher('aes-128-ecb','somepassword') var text = "the big brown fox jumped over the fence" var crypted = cipher.update(text,'utf-8','hex') crypted += cipher.final('hex') //now crypted contains the hex representation of the ciphertext 

解密:

 private static String decrypt(String seed, String encrypted) throws Exception { byte[] keyb = seed.getBytes("UTF-8"); MessageDigest md = MessageDigest.getInstance("MD5"); byte[] thedigest = md.digest(keyb); SecretKeySpec skey = new SecretKeySpec(thedigest, "AES"); Cipher dcipher = Cipher.getInstance("AES"); dcipher.init(Cipher.DECRYPT_MODE, skey); byte[] clearbyte = dcipher.doFinal(toByte(encrypted)); return new String(clearbyte); } private static byte[] toByte(String hexString) { int len = hexString.length()/2; byte[] result = new byte[len]; for (int i = 0; i < len; i++) { result[i] = Integer.valueOf(hexString.substring(2*i, 2*i+2), 16).byteValue(); } return result; } 

以为我从节点和Java方面(256而不是128)发布完整的CBC示例:如果得到java.security.InvalidKeyException,则必须安装Javaencryption扩展(JCE)无限强度pipe辖区域策略文件:

Java 6链接 Java 7链接 Java 8链接

Javaencryption和解密。

  import java.security.MessageDigest; import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.IvParameterSpec; import javax.crypto.Cipher; import java.util.Base64; import javax.xml.bind.DatatypeConverter; public class AESExample { private static byte[] iv = "0000000000000000".getBytes(); private static String decrypt(String encrypted, String seed) throws Exception { byte[] keyb = seed.getBytes("utf-8"); MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] thedigest = md.digest(keyb); SecretKeySpec skey = new SecretKeySpec(thedigest, "AES"); Cipher dcipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); dcipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(seed.getBytes("UTF-8"), "AES"), new IvParameterSpec(iv)); byte[] clearbyte = dcipher.doFinal(DatatypeConverter .parseHexBinary(encrypted)); return new String(clearbyte); } public static String encrypt(String content, String key) throws Exception { byte[] input = content.getBytes("utf-8"); MessageDigest md = MessageDigest.getInstance("SHA-256"); byte[] thedigest = md.digest(key.getBytes("utf-8")); SecretKeySpec skc = new SecretKeySpec(thedigest, "AES"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(key.getBytes("UTF-8"), "AES"), new IvParameterSpec(iv)); byte[] cipherText = new byte[cipher.getOutputSize(input.length)]; int ctLength = cipher.update(input, 0, input.length, cipherText, 0); ctLength += cipher.doFinal(cipherText, ctLength); return DatatypeConverter.printHexBinary(cipherText); } public static String encrypt128(String content, String key) throws Exception { byte[] input = content.getBytes("utf-8"); Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(DatatypeConverter.parseHexBinary(key), "AES"), new IvParameterSpec(iv)); byte[] encrypted = cipher.doFinal(content.getBytes("UTF-8")); return DatatypeConverter.printHexBinary(encrypted); } public static void main(String[] args) throws Exception { String data = "Here is my string"; String key = "1234567891123456"; String cipher = AESExample.encrypt(data, key); String decipher = AESExample.decrypt(cipher, key); System.out.println(cipher); System.out.println(decipher); System.out.println(AESExample.encrypt(data, "1234567891123456")); System.out.println(AESExample.encrypt128(data, "d7900701209d3fbac4e214dfeb5f230f")); } } 

在下面指出两个方向:

  var crypto = require('crypto'); var iv = new Buffer('0000000000000000'); // reference to converting between buffers http://nodejs.org/api/buffer.html#buffer_new_buffer_str_encoding // reference node crypto api http://nodejs.org/api/crypto.html#crypto_crypto_createcipheriv_algorithm_key_iv // reference to ECB vs CBC cipher methods http://crypto.stackexchange.com/questions/225/should-i-use-ecb-or-cbc-encryption-mode-for-my-block-cipher var encrypt = function(data, key) { var decodeKey = crypto.createHash('sha256').update(key, 'utf-8').digest(); var cipher = crypto.createCipheriv('aes-256-cbc', decodeKey, iv); return cipher.update(data, 'utf8', 'hex') + cipher.final('hex'); }; var decrypt = function(data, key) { var encodeKey = crypto.createHash('sha256').update(key, 'utf-8').digest(); var cipher = crypto.createDecipheriv('aes-256-cbc', encodeKey, iv); return cipher.update(data, 'hex', 'utf8') + cipher.final('utf8'); }; var decrypt128 = function(data, key) { var encodeKey = crypto.createHash('sha256').update(key, 'utf-8').digest(); var cipher = crypto.createDecipheriv('aes-128-cbc', new Buffer(key, 'hex'), new Buffer( iv)); return cipher.update(data, 'hex', 'utf8') + cipher.final('utf8'); }; var data = 'Here is my string' var key = '1234567891123456'; var cipher = encrypt(data, key); var decipher = decrypt(cipher, key); console.log(cipher); console.log(decipher); // the string below was generated from the "main" in the java side console.log(decrypt( "79D78BEFC06827B118A2ABC6BD9D544E83F92930144432F22A6909EF18E0FDD1", key)); console.log(decrypt128( "3EB7CF373E108ACA93E85D170C000938A6B3DCCED53A4BFC0F5A18B7DDC02499", "d7900701209d3fbac4e214dfeb5f230f"));