javascript - CryptoJS AES and Java AES encrypted value mismatch -
i trying encrypt in client , decrypt in sever using aes, using cryptojs encrypt in client side cbc mode , nopadding in server side using cipher
class same mode , nopadding
function call() { var key = cryptojs.enc.hex.parse('roshanmathew1989'); var iv = cryptojs.enc.hex.parse('roshanmathew1989'); var encrypted = cryptojs.aes.encrypt("roshanmathew1989",key,{ iv: iv}, {padding:cryptojs.pad.nopadding}); alert(encrypted.ciphertext.tostring(cryptojs.enc.base64)); alert(encrypted.iv.tostring()); }
server side code
public class crypto { private static byte[] key = null; public void setkey(string key){this.key=key.getbytes();} public string encrypt(string strtoencrypt) { string encryptedstring =null; try { cipher cipher = cipher.getinstance("aes/cbc/nopadding"); final secretkeyspec secretkey = new secretkeyspec(key,"aes"); system.out.println("sdfsdf = "+key.tostring()); ivparameterspec ips = new ivparameterspec(key); cipher.init(cipher.encrypt_mode, secretkey,ips); encryptedstring = base64.encodebase64string(cipher.dofinal(strtoencrypt.getbytes())); } catch(exception e) { system.out.println(" error : "+e.getmessage()); } return encryptedstring; } other method omitted ....
implementation
crypto cry=new crypto(); cry.setkey("roshanmathew1989"); string s=cry.encrypt("roshanmathew1989");
results
browser side value = o64x/bknbu7r2tuq2lubxeflq7wd2ynfasyyhsvuryw= server side value of s = rrncvier/75fzdjhr884sw==
can point out mistake?
there few things wrong code:
- you using hexadecimal decoding of key in javascript, ,
string.getbytes()
- character encoding without specifying character set - in java - your key 16 characters (it should 16, 24 or 32 randomized bytes), not in hexadecimals
- you encrypting instead of decrypting on "server side", although 1 on purpose
take on how perform encoding , character-encoding, essential crypto , performed incorrectly (it's common issue on stackoverflow regarding encryption)
Given it a long try and finally got it.
ReplyDelete1). CryptoJS uses hex values while java uses bytes for the same String.
2.) The two other factors which need to be same (apart from the key) are initVector and padding.
Considering both above we first have to validate that both Java are CryptoJS and encrypting to the same value given the above parameters are same.
Here is the code for Java
import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.math.BigInteger;
import java.util.Base64;
public class JavaEncryptor {
private static final String key = "aesEncryptionKey";
private static final String initVector = "encryptionIntVec";
public static String toHex(String arg) throws UnsupportedEncodingException {
return String.format("%020x", new BigInteger(1, arg.getBytes("UTF-8")));
}
/**
* Use these hex value in CryptoJS
* @throws Exception
*/
public static void printHexForJS() throws Exception {
System.out.println("HexKeyForJS : "+ toHex(key));
System.out.println("HexInitVectorForJS : "+ toHex(initVector));
}
public static String encrypt(String value) {
try {
IvParameterSpec iv = new IvParameterSpec(initVector.getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);
byte[] encrypted = cipher.doFinal(value.getBytes());
return Base64.getEncoder().encodeToString(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}
return null;
}
public static void main(String[] args) throws Exception {
printHexForJS();
System.out.println(encrypt("MyPlainTextToBeEncrypted"));
}
}
Output of the above program is
> HexKeyForJS : 616573456e6372797074696f6e4b6579
> HexInitVectorForJS : 656e6372797074696f6e496e74566563
> MURKOx14eSOo2vs8ZQyCpXpsoKg8Uzlvyj3byQreVBk=
And then for JS encryption use the HexKeyForJS and HexInitVectorForJS as in below code
var text = "ManishMudgal";
var key = CryptoJS.enc.Hex.parse(HexKeyForJS);
var iv = CryptoJS.enc.Hex.parse(HexInitVectorForJS);
var encrypted = CryptoJS.AES.encrypt(text, key, {iv: iv, padding: CryptoJS.pad.Pkcs7});
console.log(encrypted.toString());
> Output of the above JS code should be kBgYcrSxz+kbXRnyKIFmSw==
Which is the same encrypted key generated through Java code
MURKOx14eSOo2vs8ZQyCpXpsoKg8Uzlvyj3byQreVBk=
Now Decryption at Crypto End
CryptoJS.AES.decrypt('MURKOx14eSOo2vs8ZQyCpXpsoKg8Uzlvyj3byQreVBk=', CryptoJS.enc.Hex.parse(HexKeyForJS), {iv: CryptoJS.enc.Hex.parse(HexInitVectorForJS), padding: CryptoJS.pad.Pkcs7}).toString(CryptoJS.enc.Utf8);
Cheers :)