添加链接
link之家
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams

I encrypted message with cryptojs aes 256 on the client side. But couldn't decrypt it on the java side. First, I pass the key directly to the server side as hex, then convert it from hex to java bytearray. It didn't work. Then I pass the phrase, salt, iv to the server as hex. Then generate the key. It still didn't work. It always to complain the key length is not right.

Client side:

var salt = CryptoJS.lib.WordArray.random(16);
var salt_hex = CryptoJS.enc.Hex.stringify(salt);
var iv = CryptoJS.lib.WordArray.random(256/32);
var iv_hex = CryptoJS.enc.Hex.stringify(iv);
var key = CryptoJS.PBKDF2(secret, salt, { keySize: 256/32, iterations: 10 });
var key_hex=CryptoJS.enc.Hex.stringify(key);
var encrypted = CryptoJS.AES.encrypt(plaintext, key, { iv: iv });    
var encryptedtxt = secret+":"+salt_hex+":"+iv_hex+":"+encrypted.ciphertext.toString(CryptoJS.enc.Base64)+":"+key_hex;

Server side:

    if (encrypted != null)
        //Get the passphras, salt, IV and msg
        String data[] = encrypted.split(":");
        String passphrase = data[0];
        String salt_hex = data[1];
        String iv_hex = data[2];
        String msg64 = data[3];
        String jskey_hex = data[4];
        byte[] jskey = hexStringToByteArray(jskey_hex);
        byte[] iv = hexStringToByteArray(iv_hex);
        byte[] salt = hexStringToByteArray(salt_hex);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] msg = decoder.decodeBuffer(msg64);
        try {
             //theClear = AES.decrypt(encrypted);
            /* Decrypt the message, given derived key and initialization vector. */
            SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            KeySpec spec = new PBEKeySpec(passphrase.toCharArray(), salt, 10, 256/32);
            SecretKey key = new SecretKeySpec(factory.generateSecret(spec).getEncoded(), "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            String plaintext = new String(cipher.doFinal(msg), "UTF-8");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
                If "the key length is not right", then your problem might be leading zeros.  Does the stringify() method convert [0x01, 0x02, 0x03] to "123"?  Your decryption code probably assumes "010203".  "123" will probably give a two byte array, [0x12, 0x03], which does not match the input and is the wrong length.  That is fatal for a crypto key.
– rossum
                Jun 25, 2014 at 17:02
                256/32 == 8, while supported key sizes for AES are 16, 24 or 32 bytes. You will have to modify both JS and Java code to use key of at least 16 bytes.
– Oleg Estekhin
                Jun 25, 2014 at 17:15
                rossum - the hex stringified key is like 010203. But I do hex decode on the java side to byte array. I wonder how the word array on JS to match with byte array on java?
– rickcoup
                Jun 25, 2014 at 17:40
                Your IV is also sized incorrectly in the CryptoJS. AES uses 128 bit blocks, and the IV should therefore be 128 bits as well.
– Maarten Bodewes - on strike
                Jun 25, 2014 at 23:05

Finally figured it out. By default JRE 7 doesn't support 256-bit key. I had to download the new jars from http://www.oracle.com/technetwork/java/javase/downloads/jce-7-download-432124.html and overwrite them in the jre/lib/security folder. You will have to do the similar thing for the Websphere 6 or 7. If you don't do it, it prompts "illegal key size". I've also seen "illegal key size x", where x is a number. That means the key size is not right. Below are the code.

Server side:

//@Override
public String getClearText() throws IOException {
    // Get the body
    String encrypted = super.getParameter("aes"); //base64
    if (encrypted != null)
        //Get the passphras, salt, IV and msg
        String data[] = encrypted.split(":");
        String passphrase = data[0];
        String salt_hex = data[1];
        String iv_hex = data[2];
        String msg64 = data[3];
        String jskey_hex = data[4];
        byte[] jskey = hexStringToByteArray(jskey_hex);
        byte[] iv = hexStringToByteArray(iv_hex);
        byte[] salt = hexStringToByteArray(salt_hex);
        BASE64Decoder decoder = new BASE64Decoder();
        byte[] msg = decoder.decodeBuffer(msg64);
        String plaintext = "";
        try {
            SecretKey key = new SecretKeySpec(jskey, "AES");
            Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
            cipher.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
            plaintext = new String(cipher.doFinal(msg), "UTF-8");
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        System.out.println("in filter, decrypted: " +plaintext);
    return plaintext;

Client:

$(function() {
$('#test').on('submit', function() {
var plaintext = $('#text').val();
var secret = '0123456789abcdef';
var salt = CryptoJS.lib.WordArray.random(16);
var salt_hex = CryptoJS.enc.Hex.stringify(salt);
var iv = CryptoJS.lib.WordArray.random(16);
var iv_hex = CryptoJS.enc.Hex.stringify(iv);
var key = CryptoJS.PBKDF2(secret, salt, { keySize: 256/32, iterations: 1 });
//var key_hex=CryptoJS.enc.Hex.stringify(key);
var key_hex= key;
var encrypted = CryptoJS.AES.encrypt(plaintext, key, { iv: iv });    
//decrypt
var decrypted = CryptoJS.AES.decrypt(
      encrypted,
      CryptoJS.enc.Hex.parse(key_hex),
      { iv: CryptoJS.enc.Hex.parse(iv_hex) });
var text = decrypted.toString( CryptoJS.enc.Utf8 );
//console.log(encrypted);
// ----- base64 encoding ----------
var encryptedtxt =     secret+":"+salt_hex+":"+iv_hex+":"+encrypted.ciphertext.toString(CryptoJS.enc.Base64)+":"+key_hex;
console.log('html - ciphere txt : ' +encryptedtxt);
// ---- testing ----
//var decrypted = CryptoJS.AES.decrypt(encrypted, key,{iv: CryptoJS.enc.Utf8.parse(iv)});
//console.log(decrypted.toString(CryptoJS.enc.Utf8));
post ('/E2Efilter/TheServlet', encryptedtxt);
return false;
                It looks like you're storing your key with all of the other parameters (iv/salt/encrypted data), so why did you encrypt in the first place? An attacker could decrypt the data just as easily.
– Elad Nava
                Nov 15, 2014 at 17:45
        

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.