繁体   English   中英

CryptoJS AES加密和JAVA AES解密值不匹配

[英]CryptoJS AES encryption and JAVA AES decryption value mismatch

我在客户端使用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)

有什么我在这里做错了或有没有其他简单的方法来做这些加密和解密?

您的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正在做什么。 也许它使用全零? 也许它生成一个随机的,你需要用密文存储它?

这应该足以让你入门。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM