#import "NSData+AES.h" #import @implementation NSData (AES) - (NSData *)AES128EncryptedDataWithKey:(NSString *)key { return [self AES128EncryptedDataWithKey:key iv:nil]; } - (NSData *)AES128DecryptedDataWithKey:(NSString *)key { return [self AES128DecryptedDataWithKey:key iv:nil]; } - (NSData *)AES128EncryptedDataWithKey:(NSString *)key iv:(NSString *)iv { return [self AES128Operation:kCCEncrypt key:key iv:iv]; } - (NSData *)AES128DecryptedDataWithKey:(NSString *)key iv:(NSString *)iv { return [self AES128Operation:kCCDecrypt key:key iv:iv]; } - (NSData *)AES128Operation:(CCOperation)operation key:(NSString *)key iv:(NSString *)iv { char keyPtr[kCCKeySizeAES128 + 1]; bzero(keyPtr, sizeof(keyPtr)); [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; char ivPtr[kCCBlockSizeAES128 + 1]; bzero(ivPtr, sizeof(ivPtr)); if (iv) { [iv getCString:ivPtr maxLength:sizeof(ivPtr) encoding:NSUTF8StringEncoding]; } NSUInteger dataLength = [self length]; size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; CCCryptorStatus cryptStatus = CCCrypt(operation, kCCAlgorithmAES128, kCCOptionPKCS7Padding | kCCOptionECBMode, keyPtr, kCCBlockSizeAES128, ivPtr, [self bytes], dataLength, buffer, bufferSize, &numBytesEncrypted); if (cryptStatus == kCCSuccess) { return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); return nil; } - (NSString*)hexUppercaseString { return [self hexStringWithFormat:"%02X"]; } - (NSString*)hexStringWithFormat:(const char*)format { if (self.length == 0) return @""; NSUInteger length = self.length; NSMutableData* data = [NSMutableData dataWithLength:length * 2]; char *dest = data.mutableBytes; unsigned const char *src = self.bytes; for (int i = 0; i < length; ++i) { sprintf(dest + i*2, format, (unsigned int)(src[i])); } return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; } - (id)initWithHexString:(NSString*)hexString { return [self initWithHexCString:[hexString cStringUsingEncoding:NSUTF8StringEncoding]]; } - (id) initWithHexCString:(const char *)hexCString { if (!hexCString) return [self init]; const unsigned char *psz = (const unsigned char*)hexCString; while (isspace(*psz)) psz++; // Skip optional 0x prefix if (psz[0] == '0' && tolower(psz[1]) == 'x') psz += 2; while (isspace(*psz)) psz++; size_t len = strlen((const char*)psz); // If the string is not full number of bytes (each byte 2 hex characters), return nil. if (len % 2 != 0) return nil; unsigned char* buf = (unsigned char*)malloc(len/2); static const signed char digits[256] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, -1,0xa,0xb,0xc,0xd,0xe,0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,0xa,0xb,0xc,0xd,0xe,0xf, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; unsigned char* bufpointer = buf; while (1) { unsigned char c1 = (unsigned char)*psz++; signed char n1 = digits[c1]; if (n1 == (signed char)-1) break; // break when null-terminator is hit unsigned char c2 = (unsigned char)*psz++; signed char n2 = digits[c2]; if (n2 == (signed char)-1) break; // break when null-terminator is hit *bufpointer = (unsigned char)((n1 << 4) | n2); bufpointer++; } return [self initWithBytesNoCopy:buf length:len/2]; } @end