Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AES ECB iOS Encrypt

I try to encrypt some string using AES algorithm with ECB option.

size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);

size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode,
                                      encryptionKey, kCCKeySizeAES128,
                                      NULL /* initialization vector (optional) */,
                                      [self bytes], dataLength, /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}

But func returns kCCAlignmentError (-4303)

Then I try to align data:

unsigned long diff = kCCKeySizeAES128 - (dataLength % kCCKeySizeAES128);
unsigned long newSize = 0;

if (diff > 0) {
    newSize = dataLength + diff;
}

char dataPtr[newSize];
memcpy(dataPtr, [self bytes], [self length]);
for(int i = 0; i < diff; i++) {
    dataPtr[i + dataLength] = 0x20;
}

size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode,
                                      encryptionKey, kCCKeySizeAES128,
                                      NULL /* initialization vector (optional) */,
                                      dataPtr, sizeof(dataPtr), /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesEncrypted);

input string

"test_string,test2"

result is

jxtFOhYpgBVieM90zx9oDanqBkcsVAvRRJsM4GL3cio=

On Android result is

jxtFOhYpgBVieM90zx9oDUfV7v43WFv7F5bzErfxrL8=

What did I wrong?

like image 410
Bogdan Korda Avatar asked Mar 13 '23 23:03

Bogdan Korda


1 Answers

Simply AES is a block cypher which means it requires it's input data to be a multiple of the block size (16-bytes for AES). Your input data is 17 bytes thus th alignment error. (It is not talking about the alignment in memory).

The way to handle this is to specify PKCS#7 padding in the options:

kCCOptionPKCS7Padding | kCCOptionECBMode

The input data will be padded to a block multiple and on decryption the padding will be removed. To allow this on encryption it is necessary to increase the output buffer by one block size.

Consider not using [ECB mode](https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_Codebook_.28ECB.29 (Scroll down to the Penguin), it is not secure.

If you are using mcrypt on Android: don't, it is abandonware and does not support standard padding, only null padding. Instead consider defuse or RNCryptor which is a full secure implementation is is available for iOS and Java.

If you do use mcrypt you will need to add your own PKCS#7 padding.

Here is example code:

+ (NSData *)doCipher:(NSData *)dataIn
                 key:(NSData *)symmetricKey
             context:(CCOperation)encryptOrDecrypt // kCCEncrypt or kCCDecrypt
{
    CCCryptorStatus ccStatus   = kCCSuccess;
    size_t          cryptBytes = 0;    // Number of bytes moved to buffer.
    NSMutableData  *dataOut    = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];

    ccStatus = CCCrypt( encryptOrDecrypt,
                       kCCAlgorithmAES128,
                       kCCOptionPKCS7Padding | kCCOptionECBMode,
                       symmetricKey.bytes, 
                       kCCKeySizeAES128,
                       0,
                       dataIn.bytes, dataIn.length,
                       dataOut.mutableBytes, dataOut.length,
                       &cryptBytes);

    if (ccStatus != kCCSuccess) {
        NSLog(@"CCCrypt status: %d", ccStatus);
    }

    dataOut.length = cryptBytes;

    return dataOut;
}

Example PHP PKCS#7 padding:
Add PKCS#7 padding

$padLength = $blockSize - (strlen($clearText) % $blockSize);
$clearText = $clearText . str_repeat(chr($padLength), $padLength);

Strip PKCS#7 padding

$padLength = ord($cryptText[strlen($cryptText)-1]);
$cryptText = substr($cryptText, 0, strlen($cryptText) - $padLength);
like image 154
zaph Avatar answered Mar 25 '23 09:03

zaph