2

我在 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:无效的 AES 密钥长度:8 个字节

4

1 回答 1

4

您得到的原因 Invalid AES key length: 8 bytes invalid AES与您的密钥和文本的长度有关。您需要确保其长度(以位为单位)是 2 的幂。如果您想使用字符串作为加密密钥,请检查其长度(以字节为单位)并乘以 8 以找到以位为单位的长度。此外,大多数 String 实现将需要每个字符 2 个字节(Java 64 位)。此处的详细信息:如何解决 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
于 2018-07-06T11:25:38.933 回答