0

I was asked to encrypt some text from client side ( web ) before sending it to server side ( java )

So i try to use CryptoJS library for client side. I encrypt it like this :

    var key = "aaaaaaaaaaaaaaaaaaaaaaaa";
    var value = "KF169841";
    var encryptedString = CryptoJS.TripleDES.encrypt(value, key);
    console.log(encryptedString.toString());

And i get something like this : U2FsdGVkX19eYFFHgYGCr3v9/skTOKVp0pLWRNK9JTg= I use this encryptedString and key in other Decrypt tool online ( Which also use CryptoJS ) and got back exact value KF169841.

After sending this value and key to server ( well key isn't sending directly to server though but for test, it is ), i need to decrypt it using Java. But i quite don't know how to decrypt it. I'm tried some code from google search but it end up wrong padding if use DESese or get wrong value if i use ECB/NoPadding. I did try to something like setting sfg for CryptoJS side like:

    mode: CryptoJS.mode.EBC,
    padding: CryptoJS.pad.NoPadding

But they got javascript exception ( a is not define )

So any have any experience with CryptoJS can help me decrypt this one using java ?

=============================================================

UPDATE : Sorry here my server side code i'm using

/**
     * Method To Decrypt An Ecrypted String
     */
    public String decrypt(String encryptedString, String myEncryptionKey) {
        String decryptedText = null;
        try {
            byte[] keyAsBytes = myEncryptionKey.getBytes("UTF8");
            KeySpec myKeySpec = new DESedeKeySpec(keyAsBytes);
            SecretKeyFactory mySecretKeyFactory = 
                    SecretKeyFactory.getInstance("DESede");
            Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
            SecretKey key = mySecretKeyFactory.generateSecret(myKeySpec);

            cipher.init(Cipher.DECRYPT_MODE, key);
//            BASE64Decoder base64decoder = new BASE64Decoder();
//            byte[] encryptedText = base64decoder.decodeBuffer(encryptedString);

            byte[] encryptedText =  org.apache.commons.codec.binary.Base64.decodeBase64(encryptedString);
            byte[] plainText = cipher.doFinal(encryptedText);
            decryptedText= bytes2String(plainText);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return decryptedText;
    }
mameo
  • 639
  • 8
  • 25
  • 1
    Welcome to StackOverflow. Are you using Java or Javascript? They are not the same thing. – Christian Ternus Oct 29 '13 at 03:22
  • I use javascript for client side ( Using CryptoJS lib ) to encrypt it For server side i need to use Java to decrypt value using the key – mameo Oct 29 '13 at 03:24
  • @ChristianTernus: Both. – SLaks Oct 29 '13 at 03:25
  • OK, cool; can we see the Java code you have so far? – Christian Ternus Oct 29 '13 at 03:25
  • 1
    `encryptedString` is a JSON object. you need to extract the cipertext from the JSON object before you can do the decryption. – happymeal Oct 29 '13 at 03:28
  • @ Christian Ternus: i just add my code in first post. I'm not sure how to generate key when using default encrypt ( not setting sfg param for encryption ) – mameo Oct 29 '13 at 03:28
  • @happymeal: i get the value from encryptedString.toString() like in console.log file, not encryptedString itself. – mameo Oct 29 '13 at 03:30
  • I'm not sure if the Base64 decode is required. maybe you could try `encryptedString.getBytes()`. – happymeal Oct 29 '13 at 03:39
  • @happymeal: i did try that but the problem is the encrypt string length isn't multi of 8 so i get this exception : javax.crypto.IllegalBlockSizeException: Input length not multiple of 8 bytes – mameo Oct 29 '13 at 03:49

1 Answers1

0

According to the documentation, your encryptedString variable contains structured data that must be split apart to be sent to Java code. You will need to send encryptedString.iv and encryptedString.ciphertext to your Java code. If you continue to use passwords (see below), you will need to send encryptedString.salt as well.

If you pass your key as a string it will be interpreted as a password and a key will be derived from it. If you actually want to pass an explicit key, follow the documentation and specify the IV and key as suggested by the code snippet below. If you stick with supplying a password, then you must figure out the derivation scheme and use the same process in your Java code.

// Code snippet from http://code.google.com/p/crypto-js/#Custom_Key_and_IV
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script>
    var key = CryptoJS.enc.Hex.parse('000102030405060708090a0b0c0d0e0f');
    var iv  = CryptoJS.enc.Hex.parse('101112131415161718191a1b1c1d1e1f');

    var encrypted = CryptoJS.AES.encrypt("Message", key, { iv: iv });
</script>

Regarding your Java code, it looks mostly OK (although there is plenty of room for error with string conversions). However, you probably want to convert your key from hex to binary rather than grabbing the bytes:

byte[] keyAsBytes = DatatypeConverter.parseHexBinary(myEncryptionKey);

This assumes you alter your JavaScript code to pass the literal key value.

You will also need to switch to DESede/CBC/PKCS5Padding and pass an IVParameterSpec object to your Cipher.init call, specifying the IV value sent from your Java Script code.

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
  • The problem is that i only permited to send the encrypted string to server, nothing else. I send key to server while testing only (as mention in my post). Also key different between user so i can't just fix its value as some byte[] on server side. That why i need to make a function as CryptoJS.TripleDES.decrypt which accept 2 string as parameter. – mameo Oct 29 '13 at 09:13
  • @mameo The point I'm making is that both sides of the conversation need to be using the same key and deriving it in the same way. So if you want to keep using a password in CryptoJS, then you will need to add derivation code to Java. The minimum you need to send across to your Java server is the ciphertext and the IV. If you are using a password, you will need to send the salt too. – Duncan Jones Oct 29 '13 at 10:07