Joe Joe - 1 year ago 174
Android Question

Android and Crypto++ AES 128bit encrypted results not matching

I am trying to use the same key and VI to encrypt and decryp the same message, say
. The key length is 128 bit as I know that in Java/Android, 256 is not easy to implement.

Here is my function to do the AES encryption using Crypto++

string encryptString(string toBeEncrypted) {
// Create Cipher Text
CryptoPP::AES::Encryption aesEncryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Encryption cbcEncryption(aesEncryption, iv);

std::string ciphertext;

std::cout << "To be encrypted (" << toBeEncrypted.size() << " bytes)" << std::endl;
std::cout << toBeEncrypted;
std::cout << std::endl << std::endl;

CryptoPP::StreamTransformationFilter stfEncryptor(cbcEncryption, new CryptoPP::StringSink(ciphertext), CryptoPP::StreamTransformationFilter::PKCS_PADDING);
stfEncryptor.Put(reinterpret_cast<const unsigned char*> (toBeEncrypted.c_str()), toBeEncrypted.length() + 1);


key is "4ff539a893fed04840749287bb3e4152" and IV is "79f564e83be16711759ac7c730072bd0".

They are stored in binary in a ubuntu running in VMWare on a x86 Windows.

The function to convert
from byte to hex array is:

std::string hexToStr(unsigned char *data, int len)
std::stringstream ss;
for(int i(0);i<len;++i){

return ss.str();

I checked the hex string vs the memory of byte array
, and they are matching.

The results for encrypting
from C++.

I obtained this by passing the returned string
into the function
cout<<TFFHelper::hexStr((unsigned char *)ciphertext.c_str(), ciphertext.length())<<endl;

I can also decrpt it with the following function, and I passed the raw string rather than the hex string into this function.

string TFFEncryption::decryptString(string toBeDecrypted) {

string decryptedtext;
CryptoPP::AES::Decryption aesDecryption(key, CryptoPP::AES::DEFAULT_KEYLENGTH);
CryptoPP::CBC_Mode_ExternalCipher::Decryption cbcDecryption(aesDecryption, iv);

CryptoPP::StreamTransformationFilter stfDecryptor(cbcDecryption, new CryptoPP::StringSink(decryptedtext), CryptoPP::StreamTransformationFilter::PKCS_PADDING);
stfDecryptor.Put(reinterpret_cast<const unsigned char*> (toBeDecrypted.c_str()), toBeDecrypted.size());

return decryptedtext;

I put the same VI and KEY in my Android code, and try to encrypt. It ends up in a half matching results after encrypting.

Android code is as follow:

public class myAES {
private static final String key = "4ff539a893fed04840749287bb3e4152";
private static final String initVector = "79f564e83be16711759ac7c730072bd0";
private final static char[] hexArray = "0123456789ABCDEF".toCharArray();

public static byte[] hexStringToByteArray(String s) {
int len = s.length();
byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
+ Character.digit(s.charAt(i+1), 16));
return data;

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

public static byte[] encrypt(String value) {
try {
IvParameterSpec iv = new IvParameterSpec(hexStringToByteArray(initVector));
SecretKeySpec skeySpec = new SecretKeySpec(hexStringToByteArray(key), "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

byte[] encrypted = cipher.doFinal(value.getBytes());
Log.v("Encryption successful", bytesToHex(encrypted));
return encrypted;
} catch (Exception ex) {
return null;

public static String decrypt(byte[] encrypted) {
try {
IvParameterSpec iv = new IvParameterSpec(hexStringToByteArray(initVector));
SecretKeySpec skeySpec = new SecretKeySpec(hexStringToByteArray(key), "AES");

Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

byte[] original = cipher.doFinal(encrypted);
Log.v("Decryption successful", new String(original, "UTF-8"));
return new String(original);
} catch (Exception ex) {
return null;

I got the result of

I used the same piece of code in Netbeans on Java8, running on the same Ubuntu of the C++ code, and got exactly the same results as what I mentioned on the previous line (Android results). I don't think this is OS dependent, but probably I did something wrong with either Java or C++ in my code.

So the first half of the hex strings are matching, and the later half is not. I tried to reduced the phrase
, which results in complete different results from C++ vs Java (Ubuntu vs Android).

However, if I decrpt that binary array in Java, I got the original phrase

I have the following questions.

  1. What did I do wrong?

  2. Is it the proper way to case
    const char *
    unsigned char *
    ? I think it should be OK as I am getting the hex string of the binary

  3. Is the half matching results caused by padding?

Answer Source

The email in the Crypto++ message is '0' terminated, but the message in Java is not.

As AES is a block cipher with a block length of 128 bits (16 bytes), and your email is exactly 16 bytes long, the first block gets encrypted the same way in both implementations. The '0' in the first position of the second block gives the difference in the second block of the encryption.

Notice the extra '00' in below screenshot using this online tool. All the '0f' following the '00' is the PKCS5 Padding that this tool did not remove here ..

enter image description here

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download