I have to emulate and JavaScript code in Android to do an AES encrytion and decrytion, but my Android code isn't working as JavaScrip code.
I have to do the same as this code in JavaScript:
<html>
<head>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/rollups/aes.js"></script>
<script src="http://crypto-js.googlecode.com/svn/tags/3.1.2/build/components/pad-zeropadding-min.js"></script>
<!-- jquery -->
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<div id="0"></div>
<div id="1"></div>
<div id="2"></div>
<div id="3"></div>
<div id="4"></div>
<script>
var key = CryptoJS.enc.Utf8.parse('a5240ba5b7cbde89e8075db30138ce64');
var iv = CryptoJS.enc.Utf8.parse('1ec9b4a4767e582b8a1e3dcad1782f80');
var message = "message";
$('#0').text("Message: "+message);
var encrypted = CryptoJS.AES.encrypt(message, key, { iv: iv, padding: CryptoJS.pad.ZeroPadding, mode: CryptoJS.mode.CBC});
$('#1').text("Encrypted BASE64: "+encrypted);
$('#2').text("Encrypted HEX: "+encrypted.ciphertext);
var decrypted = CryptoJS.AES.decrypt(encrypted,key, { iv: iv, padding: CryptoJS.pad.ZeroPadding, mode: CryptoJS.mode.CBC});
$('#3').text("Decrypted HEX: "+decrypted);
$('#4').text("Decrypted TEXT: "+decrypted.toString(CryptoJS.enc.Utf8));
</script>
</body>
</html>
I have to do it with bouncycastle lib because the IV has 32 bytes length as you can see, I do it but my code doesn't return the same as this JavaScript code. Anyone know what I am doing wrong, in the android code?
This is the android code:
private static final String ZERO_PADDING_KEY = "a5240ba5b7cbde89e8075db30138ce64";
private static final String IV = "1ec9b4a4767e582b8a1e3dcad1782f80";
public String encryptURL(String url) {
try {
Hex hex = new Hex();
byte[] key = ZERO_PADDING_KEY.getBytes("UTF-8");
byte[] iv = IV.getBytes("UTF-8");
PaddedBufferedBlockCipher c = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), new ZeroBytePadding());
c.init(true, new ParametersWithIV(new KeyParameter(key), iv));
byte[] res = cipherData(c, url.getBytes("UTF-8"));
String resul = bytesToHex(res);
return resul;
} catch (Exception e) {
Log.e("ENCRYPT ERROR", e.getMessage());
e.printStackTrace();
}
return "";
}
public String decryptUrl(String encrypted) {
try {
Hex hex = new Hex();
byte[] key = ZERO_PADDING_KEY.getBytes("UTF-8");
byte[] iv = IV.getBytes("UTF-8");
PaddedBufferedBlockCipher c = new PaddedBufferedBlockCipher(new CBCBlockCipher(new RijndaelEngine(256)), new ZeroBytePadding());
c.init(false, new ParametersWithIV(new KeyParameter(key), iv));
byte[] decryptedText = cipherData(c, (byte[]) hex.decode(encrypted));
String decrypted = new String(decryptedText, "UTF-8");
Log.d("DECRYPTED", decrypted);
return decrypted;
} catch (Exception e) {
try {
throw new CryptoException("Unable to decrypt", e);
} catch (CryptoException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
}
return "";
}
private static byte[] cipherData(PaddedBufferedBlockCipher cipher, byte[] data) throws Exception {
int minSize = cipher.getOutputSize(data.length);
byte[] outBuf = new byte[minSize];
int length1 = cipher.processBytes(data, 0, data.length, outBuf, 0);
int length2 = cipher.doFinal(outBuf, length1);
int actualLength = length1 + length2;
byte[] result = new byte[actualLength];
System.arraycopy(outBuf, 0, result, 0, result.length);
return result;
}
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
You have new RijndaelEngine(256)
in your Android code. It is Rijndael with a block size of 256. CryptoJS only supports AES which is Rijndael with a block size of 128.
Since CryptoJS only supports AES with a block size of 128, the IV size also must be 128. You should parse the IV as Hex. CryptoJS doesn't seem to mind that a bigger IV is passed. In CryptoJS:
var iv = CryptoJS.enc.Hex.parse('1ec9b4a4767e582b8a1e3dcad1782f80');
And in Android you can use the Hex class that you already have in your code.
If you don't want to change the JavaScript code, you can use only the first 128-bit of the IV in Android (I suspect this is what CryptoJS does, but couldn't verify it):
byte[] iv = Arrays.copyOf(IV.getBytes("UTF-8"), 16);