3

我在客户端使用 CryptoJS AES 算法加密文本,我在 Java 的服务器端解密它,我得到了异常。

JS代码:

var encrypted = CryptoJS.AES.encrypt("Message", "Secret Passphrase");
console.info("encrypted " + encrypted);
var decrypted = CryptoJS.AES.decrypt(encrypted, "Secret Passphrase");
var plainText = decrypted.toString(CryptoJS.enc.Utf8)
console.info("decrypted " + plainText);

js输出:

encrypted U2FsdGVkX1/uYgVsNZmpbgKQJ8KD+8R8yyYn5+irhoI=
decrypted Message

Java 代码:

import java.nio.charset.Charset;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.regex.Pattern;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyGenerator;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;

public class AESJavaScript {
    private SecretKeySpec key;
    private Cipher cipher;
    private int size = 128;
    private static final Charset CHARSET = Charset.forName("UTF-8"); 

    public AESJavaScript() throws NoSuchAlgorithmException,
            NoSuchPaddingException, NoSuchProviderException {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        kgen.init(size); // 192 and 256 bits may not be available
        SecretKey skey = kgen.generateKey();
        byte[] raw = skey.getEncoded();
        key = new SecretKeySpec(raw, "AES/CTR/NoPadding");
        cipher = Cipher.getInstance("AES/CTR/NoPadding");
    }

    public void setKey(String keyText) {
        byte[] bText = new byte[size];
        bText = keyText.getBytes(CHARSET);
        key = new SecretKeySpec(bText, "AES/CTR/NoPadding");
    }

    public String encrypt(String message) throws InvalidKeyException,
            IllegalBlockSizeException, BadPaddingException {
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encrypted = cipher.doFinal(message.getBytes());
        return byteArrayToHexString(encrypted);
    }

    public String decrypt(String hexCiphertext)
            throws IllegalBlockSizeException, BadPaddingException,
            InvalidKeyException {
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decrypted = cipher.doFinal(hexStringToByteArray(hexCiphertext));
        return byteArrayToHexString(decrypted);
    }

    private static String byteArrayToHexString(byte[] raw) {
        String hex = "0x";
        String s = new String(raw);
        for (int x = 0; x < s.length(); x++) {
            char[] t = s.substring(x, x + 1).toCharArray();
            hex += Integer.toHexString((int) t[0]).toUpperCase();
        }
        return hex;
    }

    private static byte[] hexStringToByteArray(String hex) {
        Pattern replace = Pattern.compile("^0x");
        String s = replace.matcher(hex).replaceAll("");

        byte[] b = new byte[s.length() / 2];
        for (int i = 0; i < b.length; i++) {
            int index = i * 2;
            int v = Integer.parseInt(s.substring(index, index + 2), 16);
            b[i] = (byte) v;
        }
        return b;
    }

    public static void main(String[] args) {
        try {
            AESJavaScript ajs = new AESJavaScript();
            ajs.setKey("Secret Passphrase");
            String hexCiphertext = "U2FsdGVkX1/uYgVsNZmpbgKQJ8KD+8R8yyYn5+irhoI=";
            String decrypted = ajs.decrypt(hexCiphertext);
            System.out.println("decrypted > " + decrypted);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

例外是:

java.security.InvalidKeyException: Invalid AES key length: 17 bytes
    at com.sun.crypto.provider.AESCipher.engineGetKeySize(AESCipher.java:372)
    at javax.crypto.Cipher.passCryptoPermCheck(Cipher.java:1052)
    at javax.crypto.Cipher.checkCryptoPerm(Cipher.java:1010)
    at javax.crypto.Cipher.implInit(Cipher.java:786)
    at javax.crypto.Cipher.chooseProvider(Cipher.java:849)
    at javax.crypto.Cipher.init(Cipher.java:1213)
    at javax.crypto.Cipher.init(Cipher.java:1153)
    at com.test.jenkins.jenkinsRestart.AESJavaScript.decrypt(AESJavaScript.java:49)
    at com.test.jenkins.jenkinsRestart.AESJavaScript.main(AESJavaScript.java:82)

我在这里做错了什么还是有其他简单的方法来进行这种加密和解密?

4

1 回答 1

4

您的 Java 代码充满了错误。这里有几个:

  • 您的初始异常是由于您的"Secret Passphrase"字符串包含 17 个字节而引起的。您需要将其截断为 16 个字节(或填充它以匹配 24 或 32 个字节)。您需要匹配 CryptoJS 库的行为。

  • 您正在尝试对似乎是 base64 编码的数据进行十六进制解码。尝试使用DatatypeConverter.parseBase64Binary(hex);.

  • 您正在使用算法创建密钥"AES/CTR/NoPadding"。这无效,只需使用"AES".

  • 您必须将 IV/nonce 值传递给您的解密:

    cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(...));
    

    您使用的值将取决于 CryptoJS 正在做什么。也许它使用全零?也许它会生成一个随机的,您需要将它与密文一起存储?

这应该足以让你开始。

于 2013-07-22T07:02:58.080 回答