在节点中加密并在java中解密
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19698721/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Encrypt in node and decrypt in java
提问by avendael
I have an encrypt-code in Java. I'm trying to port the encrypt part to node. Basically, node will do the encryption using the crypto module, and then Java will do the decryption.
我有一个 Java 加密代码。我正在尝试将加密部分移植到节点。基本上,node 将使用 crypto 模块进行加密,然后 Java 将进行解密。
Here's how I do encryption in Java:
以下是我在 Java 中进行加密的方法:
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;
}
}
Here's how I do encryption in node:
这是我在节点中进行加密的方法:
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('');
In Java, I get the string T4RlJo5ENV8h1uvmOHzz1KjyXzBoBuqVLSTHsPppljA=
. This gets decrypted correctly. However, in node, I get al084hEpTK7gOYGQRSGxF+WWKvNYhT4SC7MukrzHieM=
which is obviously different and thus it won't get decrypted correctly.
在 Java 中,我得到了 string T4RlJo5ENV8h1uvmOHzz1KjyXzBoBuqVLSTHsPppljA=
。这被正确解密。但是,在节点中,我得到了al084hEpTK7gOYGQRSGxF+WWKvNYhT4SC7MukrzHieM=
明显不同的结果,因此无法正确解密。
I tried to look for people who has the same problem as me, and thisgithub issue is the closest I can find. As suggested in that issue, I tried running openssl like so:
我试图寻找和我有同样问题的人,这个github issue 是我能找到的最接近的问题。正如该问题中所建议的,我尝试像这样运行 openssl:
$ echo -e '{"someKey": "someValue"}' | openssl enc -a -e -aes-128-ecb -K "6d7956657279546f705365637265744b"
T4RlJo5ENV8h1uvmOHzz1MY2bhoFRHZ+ClxsV24l2BU=
The result I got was close enough to the one produced by java, but still different:
我得到的结果与java产生的结果足够接近,但仍然不同:
T4RlJo5ENV8h1uvmOHzz1MY2bhoFRHZ+ClxsV24l2BU= // openssl
T4RlJo5ENV8h1uvmOHzz1KjyXzBoBuqVLSTHsPppljA= // java
al084hEpTK7gOYGQRSGxF+WWKvNYhT4SC7MukrzHieM= // node
Which brings me to the question, how do I make node output the same encrypted string as my java code? I can only change my code in node, but not in java.
这让我想到了一个问题,如何让节点输出与我的 java 代码相同的加密字符串?我只能在 node 中更改我的代码,而不能在 java 中更改。
采纳答案by avendael
Finally, I found the solution to my problem. Thanks to thisguy. The key to the solution is the initialization vector. Quoting the gist:
最后,我找到了解决我的问题的方法。多亏了这个人。解决方案的关键是初始化向量。引用要点:
// ECB mode won't need IV, so keep it like this and it will work well.
// ECB 模式不需要 IV,所以保持这样,它会工作得很好。
Here's how the solution looks like:
解决方案如下所示:
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('');
回答by Dima Gutzeit
Working example of encrypting in Node.Js and decrypting in Java:
在 Node.Js 中加密和在 Java 中解密的工作示例:
to encrypt:
加密:
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
to decrypt:
解密:
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;
}
回答by Matthew Payne
Thought I post the a full CBC example from both the node and java sides(256 instead of 128): If you get the java.security.InvalidKeyException you have to install the Java Cryptography Extension (JCE) unlimited strength jurisdiction policy files:
我想我从节点和 java 端发布了一个完整的 CBC 示例(256 而不是 128):如果你得到 java.security.InvalidKeyException 你必须安装 Java Cryptography Extension (JCE) 无限强度管辖权策略文件:
Java 6 linkJava 7 linkJava 8 link
Java encrypt and Decrypt.
Java 加密和解密。
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"));
}
}
Node both directions below:
节点两个方向如下:
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"));
回答by wizmea
Important: Matthew Payne answer just work for "Encrypt in node and decrypt in java" not in both so don't just copy and paste if you want both
重要提示:Matthew Payne 的回答仅适用于“在节点中加密并在 Java 中解密”,而不适用于两者,因此如果您同时需要,请不要只复制和粘贴