CryptoJS AES encryption and JAVA AES decryption value mismatch

浪尽此生 提交于 2019-12-04 14:11:36

问题


I am encrypting a text using CryptoJS AES algorithm on the client side and I am decrypting It on Server side in java, I am getting the exception.

JS code :

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 output :

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

Java Code :

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();
        }
    }

}

Exception is :

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)

Is there anything that I am doing wrong here or Is there anyother simple way to do these kind of encryption and decryption ?


回答1:


Your Java code is riddled with errors. Here are a few of them:

  • Your initial exception is caused because your "Secret Passphrase" string contains 17 bytes. You need to truncate this to 16 bytes (or pad it to match 24 or 32 bytes). You need to match the behaviour of the CryptoJS library.

  • You are trying to hex-decode data that appears to be base64 encoded. Try using DatatypeConverter.parseBase64Binary(hex);.

  • You are creating a secret key with the algorithm "AES/CTR/NoPadding". This in invalid, just use "AES".

  • You must pass an IV/nonce value into your decryption:

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

    The value you use will depend upon what CryptoJS is doing. Perhaps it uses all zeroes? Perhaps it generates a random one and you need to store it with the ciphertext?

This should be enough to get you started.



来源:https://stackoverflow.com/questions/17780734/cryptojs-aes-encryption-and-java-aes-decryption-value-mismatch

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!