3

I am trying to encrypt a string using AES 128 bit encryption, but the encrypted data converted, when converted to a string, always returns null.

NSString *iv = @"fedcba9876543210";
NSString *key = @"0123456789abcdef";
- (NSData *)AES128EncryptWithKey
{
char keyPtr[kCCKeySizeAES128 + 1];
bzero( keyPtr, sizeof( keyPtr ) );

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

NSUInteger dataLength = [self length];

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

size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode | kCCOptionPKCS7Padding,
                                      keyPtr, kCCKeySizeAES128,
                                      NULL ,
                                      [self bytes], dataLength,
                                      buffer, bufferSize,
                                      &numBytesEncrypted );
if( cryptStatus == kCCSuccess )
{
    return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
}
}

This is my encryption function.

NSData *data = [@"String to encrypt" dataUsingEncoding:NSUTF8StringEncoding];

NSData *encryptedData = [[NSData alloc] init];

encryptedData = [data AES128EncryptWithKey];

NSLog(@"Encrypted Data Length %d", [encryptedData length]);

if (encryptedData != nil)
{
    NSString* myString;
    myString = [[NSString alloc] initWithData:encryptedData encoding:NSUTF8StringEncoding];
    NSString* newStr = [NSString stringWithUTF8String:[encryptedData bytes]];
}

After encryption, encryption data length is reported as 16 but after converting it to an NSString it returns null. If I use stringWithUTF16String to convert it, it returns like "軽ﶁែ뼐끨驂퐇". What is the issue here?

Carl Veazey
  • 18,392
  • 8
  • 66
  • 81
itdeeps
  • 277
  • 10
  • 25
  • 1
    Not going into the code very far, you can't encode an NSData as NSString in this way without data loss (UTF-8 does not allow for certain byte combinations and just won't decode the same). The result is binary, not alphanumeric, so your UTF16 result looks quite reasonable. You may want to loop through the NSData, appending the hex version of each byte to the string for every iteration if you need it in a readable format. – Joachim Isaksson Aug 24 '13 at 08:52
  • Thanks for ur reply. u mean like this unichar* hexChars = (unichar*)malloc(sizeof(unichar) * (data.length*2)); unsigned char* bytes = (unsigned char*)data.bytes; for (NSUInteger i = 0; i < data.length; i++) { unichar c = bytes[i] / 16; if (c < 10) c += '0'; else c += 'a' - 10; hexChars[i*2] = c; c = bytes[i] % 16; if (c < 10) c += '0'; else c += 'a' - 10; hexChars[i*2+1] = c; } NSString* retVal = [[NSString alloc] initWithCharactersNoCopy:hexChars length:data.length*2 freeWhenDone:YES]; – itdeeps Aug 24 '13 at 08:55

2 Answers2

2
try this code

#define kCryptingKey @"1234567890abcdef"    

@implementation Tool

+ (NSString*) crypt:(NSString*)recource
{
    NSData *data = [recource dataUsingEncoding:NSUTF8StringEncoding];
    NSData *encrypt = [self AES128EncryptWithKey:kCryptingKey withData:data];
    return [self stringWithHexBytes:encrypt];
}

+ (NSString*) decryptData:(NSData*)recource
{
    NSData *decrypt = [self AES128DecryptWithKey:kCryptingKey withData:recource];
    return [[NSString alloc] initWithData:decrypt encoding:NSUTF8StringEncoding];
}

+ (NSString*) decrypt:(NSString*)recource
{
    NSData* data=[self decodeFromHexidecimal:recource];
    NSData *decrypt = [self AES128DecryptWithKey:kCryptingKey withData:data];
    return [[NSString alloc] initWithData:decrypt encoding:NSUTF8StringEncoding];
}

+ (NSData *) decodeFromHexidecimal:(NSString*)str
{
    NSString *command = [NSString stringWithString:str];
    command = [command stringByReplacingOccurrencesOfString:@" " withString:@""];
    NSMutableData *commandToSend = [[NSMutableData data] init];
    unsigned char whole_byte;
    char byte_chars[3] = {'\0','\0','\0'};
    int i;
    for (i=0; i < [command length]/2; i++) {
        byte_chars[0] = [command characterAtIndex:i*2];
        byte_chars[1] = [command characterAtIndex:i*2+1];
        whole_byte = strtol(byte_chars, NULL, 16);
        [commandToSend appendBytes:&whole_byte length:1];
    }
    return commandToSend;
}

+ (NSData *)AES128EncryptWithKey:(NSString *)key withData:(NSData*)_data
{
    // ‘key’ should be 16 bytes for AES128
    char keyPtr[kCCKeySizeAES128 + 1]; // room for terminator (unused)
    bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)

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

    NSUInteger dataLength = [_data length];

    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That’s why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc( bufferSize );

    size_t numBytesEncrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionECBMode | kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES128,
                                          NULL /* initialization vector (optional) */,
                                          [_data bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesEncrypted );
    if( cryptStatus == kCCSuccess )
    {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
    }

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

+ (NSData *)AES128DecryptWithKey:(NSString *)key withData:(NSData*)data
{
    // 'key' should be 32 bytes for AES256, will be null-padded otherwise
    char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused)
    bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)

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

    NSUInteger dataLength = [data length];


    //See the doc: For block ciphers, the output size will always be less than or
    //equal to the input size plus the size of one block.
    //That's why we need to add the size of one block here
    size_t bufferSize = dataLength + kCCBlockSizeAES128;
    void *buffer = malloc(bufferSize);

    size_t numBytesDecrypted = 0;
    CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode | kCCOptionPKCS7Padding,
                                          keyPtr, kCCKeySizeAES128,
                                          NULL /* initialization vector (optional) */,
                                          [data bytes], dataLength, /* input */
                                          buffer, bufferSize, /* output */
                                          &numBytesDecrypted);
    if (cryptStatus == kCCSuccess) {
        //the returned NSData takes ownership of the buffer and will free it on deallocation
        return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
    }

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

+ (NSString*) stringWithHexBytes:(NSData*)_data {
    NSMutableString *stringBuffer = [NSMutableString stringWithCapacity:([_data length] * 2)];
    const unsigned char *dataBuffer = [_data bytes];
    int i;
    for (i = 0; i < [_data length]; ++i) {
        [stringBuffer appendFormat:@"%02lX", (unsigned long)dataBuffer[i]];
    }
    return [[stringBuffer copy] autorelease];
}

@end
Liolik
  • 791
  • 6
  • 12
0

Finally I got it.. As Joachim suggested I used the following method and it worked..

unichar* hexChars = (unichar*)malloc(sizeof(unichar) * (data.length*2));
unsigned char* bytes = (unsigned char*)data.bytes;
for (NSUInteger i = 0; i < data.length; i++) {
    unichar c = bytes[i] / 16;
    if (c < 10) c += '0';
    else c += 'a' - 10;
    hexChars[i*2] = c;
    c = bytes[i] % 16;
    if (c < 10) c += '0';
    else c += 'a' - 10;
    hexChars[i*2+1] = c;
}
NSString* retVal = [[NSString alloc] initWithCharactersNoCopy:hexChars
                                                       length:data.length*2
                                                 freeWhenDone:YES];
itdeeps
  • 277
  • 10
  • 25