Question

I am trying to encrypt a string in Xcode and decrypt it with PHP or encrypt with PHP and decrypt with Xcode.

So first of all I am trying to get the same AES encryption result.

Here is my Xcode file (I've put everything in a single file for simplicity):

#import "t.h"
#import <CommonCrypto/CommonCryptor.h>

@interface NSData(AES)
- (NSData*)AES256EncryptWithKey:(NSString*)key;
- (NSData*)AES256DecryptWithKey:(NSString*)key;
@end

@implementation NSData (AES)

- (NSData*)AES256EncryptWithKey:(NSString*)key {
char keyPtr[kCCKeySizeAES256];

[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSASCIIStringEncoding];

NSString *iv = @"1234567812345678";
char ivPtr[kCCKeySizeAES128];

[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSASCIIStringEncoding];    

NSUInteger dataLength = [self length];

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

size_t numBytesEncrypted    = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt, kCCAlgorithmAES128, NULL,
                                      keyPtr, kCCKeySizeAES256,
                                      ivPtr /* initialization vector (optional) */,
                                      [self bytes], dataLength, /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesEncrypted);

if (cryptStatus == kCCSuccess)
{
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}

free(buffer); //free the buffer;
return nil;
}

- (NSData*)AES256DecryptWithKey:(NSString*)key {
char keyPtr[kCCKeySizeAES256];  

NSString *iv = @"1234567812345678";
char ivPtr[kCCKeySizeAES128];

[iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSASCIIStringEncoding];


// fetch key data
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSASCIIStringEncoding];

NSUInteger dataLength = [self length];

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

size_t numBytesDecrypted    = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, NULL,
                                      keyPtr, kCCKeySizeAES256,
                                      ivPtr /* initialization vector (optional) */,
                                      [self bytes], dataLength, /* input */
                                      buffer, bufferSize, /* output */
                                      &numBytesDecrypted);

if (cryptStatus == kCCSuccess)
{
    return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}

free(buffer); //free the buffer;
return nil;
}

@end



@interface t ()
@end

@implementation t

- (void)viewDidLoad
{
[super viewDidLoad];


NSString *key = @"12345678123456781234567812345678";

NSData *plaintext =  [[@"aaa0000000000000" dataUsingEncoding:NSASCIIStringEncoding] AES256EncryptWithKey: key];

label1.text = [[NSString alloc] initWithData:plaintext encoding:NSASCIIStringEncoding];


}

@end

And now the PHP code:

<?php

$key256 = "12345678123456781234567812345678";
$iv128 = "1234567812345678";
$text = "aaa";

$blocksize = 16;
$len = strlen($text);
$pad = $blocksize - ($len % $blocksize);

$text .= str_repeat("0", $pad);

$cipher = mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key256, $text, MCRYPT_MODE_CBC, $iv128);

echo $cipher;

?>

The Xcode encrypted string and the php encrypted string are different.

PHP: â5¢Ð[Iüf#hÂ(Æ

Xcode: ¡#yZPbEs¿D6ñ

What can I do to make it work? Am I doing something wrong?

I will further explain what the code does and how it is structured so you can easier understand the problem (correct me if I am wrong):

  1. Both PHP and Xcode use CBC for AES encryption so I guess there is no problem there.

  2. As you can see I am just trying to get the same result - security does not matter here - so I used no padding - the text is exactly 128 bits in length (16 characters).

  3. The key is 256 bits (32 characters).

  4. The Initialization Vector is 128 bits (16 characters).

Thank you very much.

Any help is appreciated!

Was it helpful?

Solution

Finally got it! (after asking Apple about it)

Apparently getting getCString from NSString is wrong because the routine tries to null terminate the string and a 32-byte buffer is not big enough to terminate a 32-chars string.

The correct way to get the key or IV would be:

[key cStringUsingEncoding:NSASCIIStringEncoding];

OTHER TIPS

Change:

[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSASCIIStringEncoding];

to

[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];

I believe this is an encoding issue

When using this code from the very beginning of the page, I am able to encrypt only 16 characters of text. Actually I am able to encrypt any size of text, but when I decrypt that encrypted NSData, I get only 16 characters or 128bits.

Does this has something to do with IV? Is this code made to encrypt ONLY 128bits and if I have bigger size of the text, I need to provide (for better security) new IV and encrypt second block?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top