NSData+AESCrypt.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. //
  2. // NSData+AESCrypt.m
  3. //
  4. // AES Encrypt/Decrypt
  5. // Created by Jim Dovey and 'Jean'
  6. // See http://iphonedevelopment.blogspot.com/2009/02/strong-encryption-for-cocoa-cocoa-touch.html
  7. //
  8. // BASE64 Encoding/Decoding
  9. // // JasonDevelop 2001 Kyle Hammond. All rights reserved.
  10. // Original development by Dave Winer.
  11. //
  12. // Put together by Michael Sedlaczek, Gone Coding on 2011-02-22
  13. //
  14. // Edited for KT by Park Insang, ktds. 2012
  15. //
  16. #import "NSData+AESCrypt.h"
  17. #import <CommonCrypto/CommonCryptor.h>
  18. static char encodingTable[64] =
  19. {
  20. 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P',
  21. 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f',
  22. 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v',
  23. 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/'
  24. };
  25. @implementation NSData (AESCrypt)
  26. - (NSData *)AES256EncryptWithKey:(NSString *)key
  27. {
  28. // 'key' should be 32 bytes for AES256, will be null-padded otherwise
  29. char keyPtr[kCCKeySizeAES256 + 1]; // room for terminator (unused)
  30. bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)
  31. // fetch key data
  32. [key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
  33. NSUInteger dataLength = [self length];
  34. //See the doc: For block ciphers, the output size will always be less than or
  35. //equal to the input size plus the size of one block.
  36. //That's why we need to add the size of one block here
  37. size_t bufferSize = dataLength + kCCBlockSizeAES128;
  38. void *buffer = malloc( bufferSize );
  39. size_t numBytesEncrypted = 0;
  40. CCCryptorStatus cryptStatus = CCCrypt( kCCEncrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
  41. keyPtr, kCCKeySizeAES256,
  42. NULL /* initialization vector (optional) */,
  43. [self bytes], dataLength, /* input */
  44. buffer, bufferSize, /* output */
  45. &numBytesEncrypted );
  46. if( cryptStatus == kCCSuccess )
  47. {
  48. //the returned NSData takes ownership of the buffer and will free it on deallocation
  49. return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
  50. }
  51. free( buffer ); //free the buffer
  52. return nil;
  53. }
  54. - (NSData *)AES256DecryptWithKey:(NSString *)key
  55. {
  56. // 'key' should be 32 bytes for AES256, will be null-padded otherwise
  57. char keyPtr[kCCKeySizeAES256+1]; // room for terminator (unused)
  58. bzero( keyPtr, sizeof( keyPtr ) ); // fill with zeroes (for padding)
  59. // fetch key data
  60. [key getCString:keyPtr maxLength:sizeof( keyPtr ) encoding:NSUTF8StringEncoding];
  61. NSUInteger dataLength = [self length];
  62. //See the doc: For block ciphers, the output size will always be less than or
  63. //equal to the input size plus the size of one block.
  64. //That's why we need to add the size of one block here
  65. size_t bufferSize = dataLength + kCCBlockSizeAES128;
  66. void *buffer = malloc( bufferSize );
  67. size_t numBytesDecrypted = 0;
  68. CCCryptorStatus cryptStatus = CCCrypt( kCCDecrypt, kCCAlgorithmAES128, kCCOptionPKCS7Padding,
  69. keyPtr, kCCKeySizeAES256,
  70. NULL /* initialization vector (optional) */,
  71. [self bytes], dataLength, /* input */
  72. buffer, bufferSize, /* output */
  73. &numBytesDecrypted );
  74. if( cryptStatus == kCCSuccess )
  75. {
  76. //the returned NSData takes ownership of the buffer and will free it on deallocation
  77. return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
  78. }
  79. free( buffer ); //free the buffer
  80. return nil;
  81. }
  82. - (NSData *)AES128EncryptWithKey:(NSString *)key
  83. {
  84. // 'key' should be 32 bytes for AES256, will be null-padded otherwise
  85. char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused) // oorspronkelijk 256
  86. bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
  87. // fetch key data
  88. [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
  89. NSUInteger dataLength = [self length];
  90. //See the doc: For block ciphers, the output size will always be less than or
  91. //equal to the input size plus the size of one block.
  92. //That's why we need to add the size of one block here
  93. size_t bufferSize = dataLength + kCCBlockSizeAES128;
  94. void *buffer = malloc(bufferSize);
  95. size_t numBytesEncrypted = 0;
  96. CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
  97. kCCAlgorithmAES128,
  98. kCCOptionECBMode +kCCOptionPKCS7Padding,
  99. keyPtr,
  100. kCCKeySizeAES128, // oorspronkelijk 256
  101. nil, /* initialization vector (optional) */
  102. [self bytes],
  103. dataLength, /* input */
  104. buffer,
  105. bufferSize, /* output */
  106. &numBytesEncrypted);
  107. if (cryptStatus == kCCSuccess) {
  108. //the returned NSData takes ownership of the buffer and will free it on deallocation
  109. return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
  110. }
  111. free(buffer); //free the buffer;
  112. return nil;
  113. }
  114. - (NSData *)AES128DecryptWithKey:(NSString *)key
  115. {
  116. // 'key' should be 32 bytes for AES256, will be null-padded otherwise
  117. char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused) // oorspronkelijk 256
  118. bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding)
  119. // fetch key data
  120. [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
  121. NSUInteger dataLength = [self length];
  122. //See the doc: For block ciphers, the output size will always be less than or
  123. //equal to the input size plus the size of one block.
  124. //That's why we need to add the size of one block here
  125. size_t bufferSize = dataLength + kCCBlockSizeAES128;
  126. void *buffer = malloc(bufferSize);
  127. size_t numBytesDecrypted = 0;
  128. CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
  129. kCCAlgorithmAES128,
  130. kCCOptionECBMode +kCCOptionPKCS7Padding,
  131. keyPtr, kCCKeySizeAES128, // oorspronkelijk 256
  132. NULL /* initialization vector (optional) */,
  133. [self bytes], dataLength, /* input */
  134. buffer, bufferSize, /* output */
  135. &numBytesDecrypted);
  136. if (cryptStatus == kCCSuccess) {
  137. //the returned NSData takes ownership of the buffer and will free it on deallocation
  138. return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
  139. }
  140. free(buffer); //free the buffer;
  141. return nil;
  142. }
  143. #pragma mark -
  144. + (NSData *)dataWithBase64EncodedString:(NSString *)string
  145. {
  146. return [[NSData allocWithZone:nil] initWithBase64EncodedString:string];
  147. }
  148. - (id)initWithBase64EncodedString:(NSString *)string
  149. {
  150. NSMutableData *mutableData = nil;
  151. if( string )
  152. {
  153. unsigned long ixtext = 0;
  154. unsigned long lentext = 0;
  155. unsigned char ch = 0;
  156. unsigned char inbuf[4], outbuf[3];
  157. short i = 0, ixinbuf = 0;
  158. BOOL flignore = NO;
  159. BOOL flendtext = NO;
  160. NSData *base64Data = nil;
  161. const unsigned char *base64Bytes = nil;
  162. // Convert the string to ASCII data.
  163. base64Data = [string dataUsingEncoding:NSASCIIStringEncoding];
  164. base64Bytes = [base64Data bytes];
  165. mutableData = [NSMutableData dataWithCapacity:base64Data.length];
  166. lentext = base64Data.length;
  167. while( YES )
  168. {
  169. if( ixtext >= lentext ) break;
  170. ch = base64Bytes[ixtext++];
  171. flignore = NO;
  172. if( ( ch >= 'A' ) && ( ch <= 'Z' ) ) ch = ch - 'A';
  173. else if( ( ch >= 'a' ) && ( ch <= 'z' ) ) ch = ch - 'a' + 26;
  174. else if( ( ch >= '0' ) && ( ch <= '9' ) ) ch = ch - '0' + 52;
  175. else if( ch == '+' ) ch = 62;
  176. else if( ch == '=' ) flendtext = YES;
  177. else if( ch == '/' ) ch = 63;
  178. else flignore = YES;
  179. if( ! flignore )
  180. {
  181. short ctcharsinbuf = 3;
  182. BOOL flbreak = NO;
  183. if( flendtext )
  184. {
  185. if( ! ixinbuf ) break;
  186. if( ( ixinbuf == 1 ) || ( ixinbuf == 2 ) ) ctcharsinbuf = 1;
  187. else ctcharsinbuf = 2;
  188. ixinbuf = 3;
  189. flbreak = YES;
  190. }
  191. inbuf [ixinbuf++] = ch;
  192. if( ixinbuf == 4 )
  193. {
  194. ixinbuf = 0;
  195. outbuf [0] = ( inbuf[0] << 2 ) | ( ( inbuf[1] & 0x30) >> 4 );
  196. outbuf [1] = ( ( inbuf[1] & 0x0F ) << 4 ) | ( ( inbuf[2] & 0x3C ) >> 2 );
  197. outbuf [2] = ( ( inbuf[2] & 0x03 ) << 6 ) | ( inbuf[3] & 0x3F );
  198. for( i = 0; i < ctcharsinbuf; i++ )
  199. [mutableData appendBytes:&outbuf[i] length:1];
  200. }
  201. if( flbreak ) break;
  202. }
  203. }
  204. }
  205. self = [self initWithData:mutableData];
  206. return self;
  207. }
  208. #pragma mark -
  209. - (NSString *)base64Encoding
  210. {
  211. return [self base64EncodingWithLineLength:0];
  212. }
  213. - (NSString *)base64EncodingWithLineLength:(NSUInteger)lineLength
  214. {
  215. const unsigned char *bytes = [self bytes];
  216. NSMutableString *result = [NSMutableString stringWithCapacity:self.length];
  217. unsigned long ixtext = 0;
  218. unsigned long lentext = self.length;
  219. long ctremaining = 0;
  220. unsigned char inbuf[3], outbuf[4];
  221. unsigned short i = 0;
  222. unsigned short charsonline = 0, ctcopy = 0;
  223. unsigned long ix = 0;
  224. while( YES )
  225. {
  226. ctremaining = lentext - ixtext;
  227. if( ctremaining <= 0 ) break;
  228. for( i = 0; i < 3; i++ )
  229. {
  230. ix = ixtext + i;
  231. if( ix < lentext ) inbuf[i] = bytes[ix];
  232. else inbuf [i] = 0;
  233. }
  234. outbuf [0] = (inbuf [0] & 0xFC) >> 2;
  235. outbuf [1] = ((inbuf [0] & 0x03) << 4) | ((inbuf [1] & 0xF0) >> 4);
  236. outbuf [2] = ((inbuf [1] & 0x0F) << 2) | ((inbuf [2] & 0xC0) >> 6);
  237. outbuf [3] = inbuf [2] & 0x3F;
  238. ctcopy = 4;
  239. switch( ctremaining )
  240. {
  241. case 1:
  242. ctcopy = 2;
  243. break;
  244. case 2:
  245. ctcopy = 3;
  246. break;
  247. }
  248. for( i = 0; i < ctcopy; i++ )
  249. [result appendFormat:@"%c", encodingTable[outbuf[i]]];
  250. for( i = ctcopy; i < 4; i++ )
  251. [result appendString:@"="];
  252. ixtext += 3;
  253. charsonline += 4;
  254. if( lineLength > 0 )
  255. {
  256. if( charsonline >= lineLength )
  257. {
  258. charsonline = 0;
  259. [result appendString:@"\n"];
  260. }
  261. }
  262. }
  263. return [NSString stringWithString:result];
  264. }
  265. - (NSString *)hexEncode{
  266. NSMutableString *hex = [NSMutableString string];
  267. unsigned char *bytes = (unsigned char *)[self bytes];
  268. char temp[3];
  269. NSUInteger i=0;
  270. for(i=0; i<[self length]; i++){
  271. temp[0] = temp[1] = temp[2] =0;
  272. (void)sprintf(temp, "%02x",bytes[i]);
  273. [hex appendString:[NSString stringWithUTF8String:temp]];
  274. }
  275. return hex;
  276. }
  277. + (NSData *)decodeHexString:(NSString *)hexString
  278. {
  279. int tlen = (int)[hexString length]/2;
  280. char tbuf[tlen];
  281. int i,k,h,l;
  282. bzero(tbuf, sizeof(tbuf));
  283. for(i=0,k=0;i<tlen;i++)
  284. {
  285. h=[hexString characterAtIndex:k++];
  286. l=[hexString characterAtIndex:k++];
  287. h=(h >= 'A') ? h-'A'+10 : h-'0';
  288. l=(l >= 'A') ? l-'A'+10 : l-'0';
  289. tbuf[i]= ((h<<4)&0xf0)| (l&0x0f);
  290. }
  291. return [NSData dataWithBytes:tbuf length:tlen];
  292. }
  293. #pragma mark -
  294. - (BOOL)hasPrefixBytes:(const void *)prefix length:(NSUInteger)length
  295. {
  296. if( ! prefix || ! length || self.length < length ) return NO;
  297. return ( memcmp( [self bytes], prefix, length ) == 0 );
  298. }
  299. - (BOOL)hasSuffixBytes:(const void *)suffix length:(NSUInteger)length
  300. {
  301. if( ! suffix || ! length || self.length < length ) return NO;
  302. return ( memcmp( ((const char *)[self bytes] + (self.length - length)), suffix, length ) == 0 );
  303. }
  304. @end