Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android AES 128 encryption

I'm trying to implement AES128 encryption on an Android. I've got a solution working on an iPhone with Objective C but having trouble porting it to Android. I've searched stackoverflow for a solution, but I seem to be doing something wrong. I'm fairly new to Java so I think I'm missing something to do with data, string conversion.

Here is my iPhone encrypt:

char keyPtr[kCCKeySizeAES128+1];
[keyString getCString:keyPtr
            maxLength:sizeof(keyPtr)
             encoding:NSASCIIStringEncoding];

// CString for the plain text
char plainBytes[[plainString length]+1];
[plainString getCString:plainBytes
              maxLength:sizeof(plainBytes)
               encoding:NSASCIIStringEncoding];

size_t bytesEncrypted = 0;

// Allocate the space for encrypted data
NSUInteger dataLength = [plainString length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void* buffer = malloc(bufferSize);

// Encrypt
CCCryptorStatus ret = CCCrypt(kCCEncrypt,
                              kCCAlgorithmAES128,
                              kCCOptionPKCS7Padding | kCCOptionECBMode,
                              keyPtr,
                              kCCKeySizeAES128,
                              NULL,
                              plainBytes, sizeof(plainBytes),
                              buffer, bufferSize,
                              &bytesEncrypted);
if (ret != kCCSuccess) {
    free(buffer);
}

encryptedData = [NSData dataWithBytes:buffer length:bytesEncrypted];

Here is my Java:

    SecretKeySpec skeySpec = new SecretKeySpec(key, "AES");
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));

Using the same key and plaintext in iPhone and Java give different results. My iPhone result works the way I need it so I'm trying to get java to give me the iPhone result. I'm missing something in the Java for sure, just not sure what it is.

edit

based on suggestions below I modified my Java to this

    byte[] keyBytes = plainTextKey.getBytes("US-ASCII");
    SecretKeySpec skeySpec = new SecretKeySpec(keyBytes, "AES");
    Cipher cipher = Cipher.getInstance("AES/ECB/PKCS7Padding");
    cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
    byte[] encrypted = cipher.doFinal(plainText.getBytes("US-ASCII"));

but I'm still getting different results between android and iPhone

like image 660
Pabs Avatar asked Mar 13 '13 16:03

Pabs


1 Answers

in addition to encoding difficulties with your plaintext (as vcsjones pointed out in the comments), make sure that the encoding is the same for the key string (note that using a raw string, like a password, directly as an crypto key is bad news bears, use a key derivation function like PBKDF2 on the password to get derive a key).

Also, the encoding string for Java for ASCII is US-ASCII, not just ASCII, so make sure to use that in your getBytes calls.

EDIT: found your problem: the iOS string is being encrypted with an extra null charcter (0x00) at the end, while the java was not. So encrypting "hello world\0" in java will give you the same output as "hello world" does in iOS

like image 98
Peter Elliott Avatar answered Sep 28 '22 09:09

Peter Elliott