在 nodejs 中加密字符串并在 java 中解密
Encrypt a string in nodejs and decrypt in java
我在 NODEJS 中加密文本并尝试在 Java 中解密但出现错误。
我的 nodejs 代码:
var crypto = require('crypto')
, key = 'mykey@91'
, plaintext = 'SS18617710213463'
, cipher = crypto.createCipher('aes-128-ecb', key)
, decipher = crypto.createDecipher('aes-128-ecb', key);
var encryptedPassword = cipher.update(plaintext, 'utf8', 'base64');
encryptedPassword += cipher.final('base64')
var decryptedPassword = decipher.update(encryptedPassword, 'base64', 'utf8');
decryptedPassword += decipher.final('utf8');
console.log('original :', plaintext);
console.log('encrypted :', encryptedPassword);
console.log('decrypted :', decryptedPassword);
但是当我试图解密它时,它总是抛出错误。
public static String decrypt(String encryptedText) {
try {
final String key = "mykey@91";
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] cipherText = Base64.getDecoder().decode(encryptedText.getBytes("UTF8"));
String decryptedString = new String(cipher.doFinal(cipherText),"UTF8");
return decryptedString;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
我得到的错误如下:
java.security.InvalidKeyException: Invalid AES key length: 8 bytes
您获得 Invalid AES key length: 8 bytes invalid AES
的原因与您的密钥和文本的长度有关。您需要确保其长度(以位为单位)是 2 的幂。如果您想使用字符串作为加密密钥,请检查其字节长度,然后乘以 8 得到位长度。此外,大多数 String 实现将需要每个字符 2 个字节(Java 64 位)。详细信息在这里:How to solve InvalidKeyException
在这种情况下,只需使用填充或更长的密钥,上述错误就会消失,例如:
static String PLAIN_TEXT = "SS18617710213463";
static String ENCRYPTION_KEY = "mykey@91mykey@91";
然而,还有另一件重要的事情需要考虑。 Java 实现必须与 node.js 提供的算法完全匹配。这并不像听起来那么容易(至少根据我的经验)。在你的情况下,我建议你在 node.js 侧使用 node-forge ,这更容易匹配 Java 实现:
var forge = require('node-forge');
var plaintext = 'SS18617710213463';
var key = 'mykey@91mykey@91';
var iv = 'AODVNUASDNVVAOVF';
console.log('Plain Text: ' + plaintext);
var cipher = forge.cipher.createCipher('AES-CBC', key);
cipher.start({iv: iv});
cipher.update(forge.util.createBuffer(plaintext));
cipher.finish();
var encrypted = cipher.output;
var encodedB64 = forge.util.encode64(encrypted.data);
console.log("Encoded: " + encodedB64);
var decodedB64 = forge.util.decode64(encodedB64);
encrypted.data = decodedB64;
var decipher = forge.cipher.createDecipher('AES-CBC', key);
decipher.start({iv: iv});
decipher.update(encrypted);
var result = decipher.finish();
console.log("Decoded: " + decipher.output.data);
运行上面的代码,输出应该是:
Plain Text: SS18617710213463
Encoded: HCzZD7uc13fqfM6odWcXf/mdR4aNJfkMDhEbnU+asjE=
Decoded: SS18617710213463
并且以相同方式工作的兼容 Java 代码如下所示:
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Main {
static String PLAIN_TEXT = "SS18617710213463";
static String ENCRYPTION_KEY = "mykey@91mykey@91";
static String INITIALIZATIO_VECTOR = "AODVNUASDNVVAOVF";
public static void main(String [] args) {
try {
System.out.println("Plain text: " + PLAIN_TEXT);
byte[] encryptedMsg = encrypt(PLAIN_TEXT, ENCRYPTION_KEY);
String base64Encrypted = Base64.getEncoder().encodeToString(encryptedMsg);
System.out.println("Encrypted: "+ base64Encrypted);
byte[] base64Decrypted = Base64.getDecoder().decode(base64Encrypted);
String decryptedMsg = decrypt(base64Decrypted, ENCRYPTION_KEY);
System.out.println("Decrypted: " + decryptedMsg);
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/pkcs5padding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));
return cipher.doFinal(plainText.getBytes("UTF-8"));
}
public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/pkcs5padding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));
return new String(cipher.doFinal(cipherText),"UTF-8");
}
}
产生:
Plain text: SS18617710213463
Encrypted: HCzZD7uc13fqfM6odWcXf/mdR4aNJfkMDhEbnU+asjE=
Decrypted: SS18617710213463
我在 NODEJS 中加密文本并尝试在 Java 中解密但出现错误。 我的 nodejs 代码:
var crypto = require('crypto')
, key = 'mykey@91'
, plaintext = 'SS18617710213463'
, cipher = crypto.createCipher('aes-128-ecb', key)
, decipher = crypto.createDecipher('aes-128-ecb', key);
var encryptedPassword = cipher.update(plaintext, 'utf8', 'base64');
encryptedPassword += cipher.final('base64')
var decryptedPassword = decipher.update(encryptedPassword, 'base64', 'utf8');
decryptedPassword += decipher.final('utf8');
console.log('original :', plaintext);
console.log('encrypted :', encryptedPassword);
console.log('decrypted :', decryptedPassword);
但是当我试图解密它时,它总是抛出错误。
public static String decrypt(String encryptedText) {
try {
final String key = "mykey@91";
Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
SecretKeySpec secretKey = new SecretKeySpec(key.getBytes(), "AES");
cipher.init(Cipher.DECRYPT_MODE, secretKey);
byte[] cipherText = Base64.getDecoder().decode(encryptedText.getBytes("UTF8"));
String decryptedString = new String(cipher.doFinal(cipherText),"UTF8");
return decryptedString;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
我得到的错误如下:
java.security.InvalidKeyException: Invalid AES key length: 8 bytes
您获得 Invalid AES key length: 8 bytes invalid AES
的原因与您的密钥和文本的长度有关。您需要确保其长度(以位为单位)是 2 的幂。如果您想使用字符串作为加密密钥,请检查其字节长度,然后乘以 8 得到位长度。此外,大多数 String 实现将需要每个字符 2 个字节(Java 64 位)。详细信息在这里:How to solve InvalidKeyException
在这种情况下,只需使用填充或更长的密钥,上述错误就会消失,例如:
static String PLAIN_TEXT = "SS18617710213463";
static String ENCRYPTION_KEY = "mykey@91mykey@91";
然而,还有另一件重要的事情需要考虑。 Java 实现必须与 node.js 提供的算法完全匹配。这并不像听起来那么容易(至少根据我的经验)。在你的情况下,我建议你在 node.js 侧使用 node-forge ,这更容易匹配 Java 实现:
var forge = require('node-forge');
var plaintext = 'SS18617710213463';
var key = 'mykey@91mykey@91';
var iv = 'AODVNUASDNVVAOVF';
console.log('Plain Text: ' + plaintext);
var cipher = forge.cipher.createCipher('AES-CBC', key);
cipher.start({iv: iv});
cipher.update(forge.util.createBuffer(plaintext));
cipher.finish();
var encrypted = cipher.output;
var encodedB64 = forge.util.encode64(encrypted.data);
console.log("Encoded: " + encodedB64);
var decodedB64 = forge.util.decode64(encodedB64);
encrypted.data = decodedB64;
var decipher = forge.cipher.createDecipher('AES-CBC', key);
decipher.start({iv: iv});
decipher.update(encrypted);
var result = decipher.finish();
console.log("Decoded: " + decipher.output.data);
运行上面的代码,输出应该是:
Plain Text: SS18617710213463
Encoded: HCzZD7uc13fqfM6odWcXf/mdR4aNJfkMDhEbnU+asjE=
Decoded: SS18617710213463
并且以相同方式工作的兼容 Java 代码如下所示:
import java.util.Base64;
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
public class Main {
static String PLAIN_TEXT = "SS18617710213463";
static String ENCRYPTION_KEY = "mykey@91mykey@91";
static String INITIALIZATIO_VECTOR = "AODVNUASDNVVAOVF";
public static void main(String [] args) {
try {
System.out.println("Plain text: " + PLAIN_TEXT);
byte[] encryptedMsg = encrypt(PLAIN_TEXT, ENCRYPTION_KEY);
String base64Encrypted = Base64.getEncoder().encodeToString(encryptedMsg);
System.out.println("Encrypted: "+ base64Encrypted);
byte[] base64Decrypted = Base64.getDecoder().decode(base64Encrypted);
String decryptedMsg = decrypt(base64Decrypted, ENCRYPTION_KEY);
System.out.println("Decrypted: " + decryptedMsg);
} catch (Exception e) {
e.printStackTrace();
}
}
public static byte[] encrypt(String plainText, String encryptionKey) throws Exception {
Cipher cipher = Cipher.getInstance("AES/CBC/pkcs5padding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.ENCRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));
return cipher.doFinal(plainText.getBytes("UTF-8"));
}
public static String decrypt(byte[] cipherText, String encryptionKey) throws Exception{
Cipher cipher = Cipher.getInstance("AES/CBC/pkcs5padding", "SunJCE");
SecretKeySpec key = new SecretKeySpec(encryptionKey.getBytes("UTF-8"), "AES");
cipher.init(Cipher.DECRYPT_MODE, key,new IvParameterSpec(INITIALIZATIO_VECTOR.getBytes("UTF-8")));
return new String(cipher.doFinal(cipherText),"UTF-8");
}
}
产生:
Plain text: SS18617710213463
Encrypted: HCzZD7uc13fqfM6odWcXf/mdR4aNJfkMDhEbnU+asjE=
Decrypted: SS18617710213463