CocoaSecurity.m 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508
  1. //
  2. // CocoaSecurity.m
  3. //
  4. // Created by Kelp on 12/5/12.
  5. // Copyright (c) 2012 Kelp http://kelp.phate.org/
  6. // MIT License
  7. //
  8. #import "CocoaSecurity.h"
  9. #import <CommonCrypto/CommonHMAC.h>
  10. #import <CommonCrypto/CommonCryptor.h>
  11. #import "Base64.h"
  12. #pragma mark - CocoaSecurity
  13. @implementation CocoaSecurity
  14. #pragma mark - AES Encrypt
  15. // default AES Encrypt, key -> SHA384(key).sub(0, 32), iv -> SHA384(key).sub(32, 16)
  16. + (CocoaSecurityResult *)aesEncrypt:(NSString *)data key:(NSString *)key
  17. {
  18. CocoaSecurityResult * sha = [self sha384:key];
  19. NSData *aesKey = [sha.data subdataWithRange:NSMakeRange(0, 32)];
  20. NSData *aesIv = [sha.data subdataWithRange:NSMakeRange(32, 16)];
  21. return [self aesEncrypt:data key:aesKey iv:aesIv];
  22. }
  23. #pragma mark AES Encrypt 128, 192, 256
  24. + (CocoaSecurityResult *)aesEncrypt:(NSString *)data hexKey:(NSString *)key hexIv:(NSString *)iv
  25. {
  26. CocoaSecurityDecoder *decoder = [CocoaSecurityDecoder new];
  27. NSData *aesKey = [decoder hex:key];
  28. NSData *aesIv = [decoder hex:iv];
  29. return [self aesEncrypt:data key:aesKey iv:aesIv];
  30. }
  31. + (CocoaSecurityResult *)aesEncrypt:(NSString *)data key:(NSData *)key iv:(NSData *)iv
  32. {
  33. return [self aesEncryptWithData:[data dataUsingEncoding:NSUTF8StringEncoding] key:key iv:iv];
  34. }
  35. + (CocoaSecurityResult *)aesEncryptWithData:(NSData *)data key:(NSData *)key iv:(NSData *)iv
  36. {
  37. // check length of key and iv
  38. if ([iv length] != 16) {
  39. @throw [NSException exceptionWithName:@"Cocoa Security"
  40. reason:@"Length of iv is wrong. Length of iv should be 16(128bits)"
  41. userInfo:nil];
  42. }
  43. if ([key length] != 16 && [key length] != 24 && [key length] != 32 ) {
  44. @throw [NSException exceptionWithName:@"Cocoa Security"
  45. reason:@"Length of key is wrong. Length of iv should be 16, 24 or 32(128, 192 or 256bits)"
  46. userInfo:nil];
  47. }
  48. // setup output buffer
  49. size_t bufferSize = [data length] + kCCBlockSizeAES128;
  50. void *buffer = malloc(bufferSize);
  51. // do encrypt
  52. size_t encryptedSize = 0;
  53. CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
  54. kCCAlgorithmAES128,
  55. kCCOptionPKCS7Padding,
  56. [key bytes], // Key
  57. [key length], // kCCKeySizeAES
  58. [iv bytes], // IV
  59. [data bytes],
  60. [data length],
  61. buffer,
  62. bufferSize,
  63. &encryptedSize);
  64. if (cryptStatus == kCCSuccess) {
  65. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:buffer length:encryptedSize];
  66. free(buffer);
  67. return result;
  68. }
  69. else {
  70. free(buffer);
  71. @throw [NSException exceptionWithName:@"Cocoa Security"
  72. reason:@"Encrypt Error!"
  73. userInfo:nil];
  74. return nil;
  75. }
  76. }
  77. #pragma mark - AES Decrypt
  78. // default AES Decrypt, key -> SHA384(key).sub(0, 32), iv -> SHA384(key).sub(32, 16)
  79. + (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data key:(NSString *)key
  80. {
  81. CocoaSecurityResult * sha = [self sha384:key];
  82. NSData *aesKey = [sha.data subdataWithRange:NSMakeRange(0, 32)];
  83. NSData *aesIv = [sha.data subdataWithRange:NSMakeRange(32, 16)];
  84. return [self aesDecryptWithBase64:data key:aesKey iv:aesIv];
  85. }
  86. #pragma mark AES Decrypt 128, 192, 256
  87. + (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data hexKey:(NSString *)key hexIv:(NSString *)iv
  88. {
  89. CocoaSecurityDecoder *decoder = [CocoaSecurityDecoder new];
  90. NSData *aesKey = [decoder hex:key];
  91. NSData *aesIv = [decoder hex:iv];
  92. return [self aesDecryptWithBase64:data key:aesKey iv:aesIv];
  93. }
  94. + (CocoaSecurityResult *)aesDecryptWithBase64:(NSString *)data key:(NSData *)key iv:(NSData *)iv
  95. {
  96. CocoaSecurityDecoder *decoder = [CocoaSecurityDecoder new];
  97. return [self aesDecryptWithData:[decoder base64:data] key:key iv:iv];
  98. }
  99. + (CocoaSecurityResult *)aesDecryptWithData:(NSData *)data key:(NSData *)key iv:(NSData *)iv
  100. {
  101. // check length of key and iv
  102. if ([iv length] != 16) {
  103. @throw [NSException exceptionWithName:@"Cocoa Security"
  104. reason:@"Length of iv is wrong. Length of iv should be 16(128bits)"
  105. userInfo:nil];
  106. }
  107. if ([key length] != 16 && [key length] != 24 && [key length] != 32 ) {
  108. @throw [NSException exceptionWithName:@"Cocoa Security"
  109. reason:@"Length of key is wrong. Length of iv should be 16, 24 or 32(128, 192 or 256bits)"
  110. userInfo:nil];
  111. }
  112. // setup output buffer
  113. size_t bufferSize = [data length] + kCCBlockSizeAES128;
  114. void *buffer = malloc(bufferSize);
  115. // do encrypt
  116. size_t encryptedSize = 0;
  117. CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
  118. kCCAlgorithmAES128,
  119. kCCOptionPKCS7Padding,
  120. [key bytes], // Key
  121. [key length], // kCCKeySizeAES
  122. [iv bytes], // IV
  123. [data bytes],
  124. [data length],
  125. buffer,
  126. bufferSize,
  127. &encryptedSize);
  128. if (cryptStatus == kCCSuccess) {
  129. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:buffer length:encryptedSize];
  130. free(buffer);
  131. return result;
  132. }
  133. else {
  134. free(buffer);
  135. @throw [NSException exceptionWithName:@"Cocoa Security"
  136. reason:@"Decrypt Error!"
  137. userInfo:nil];
  138. return nil;
  139. }
  140. }
  141. #pragma mark - MD5
  142. + (CocoaSecurityResult *)md5:(NSString *)hashString
  143. {
  144. return [self md5WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
  145. }
  146. + (CocoaSecurityResult *)md5WithData:(NSData *)hashData
  147. {
  148. unsigned char *digest;
  149. digest = malloc(CC_MD5_DIGEST_LENGTH);
  150. CC_MD5([hashData bytes], (CC_LONG)[hashData length], digest);
  151. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_MD5_DIGEST_LENGTH];
  152. free(digest);
  153. return result;
  154. }
  155. #pragma mark - HMAC-MD5
  156. + (CocoaSecurityResult *)hmacMd5:(NSString *)hashString hmacKey:(NSString *)key
  157. {
  158. return [self hmacMd5WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
  159. }
  160. + (CocoaSecurityResult *)hmacMd5WithData:(NSData *)hashData hmacKey:(NSString *)key
  161. {
  162. unsigned char *digest;
  163. digest = malloc(CC_MD5_DIGEST_LENGTH);
  164. const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
  165. CCHmac(kCCHmacAlgMD5, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
  166. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_MD5_DIGEST_LENGTH];
  167. free(digest);
  168. cKey = nil;
  169. return result;
  170. }
  171. #pragma mark - SHA1
  172. + (CocoaSecurityResult *)sha1:(NSString *)hashString
  173. {
  174. return [self sha1WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
  175. }
  176. + (CocoaSecurityResult *)sha1WithData:(NSData *)hashData
  177. {
  178. unsigned char *digest;
  179. digest = malloc(CC_SHA1_DIGEST_LENGTH);
  180. CC_SHA1([hashData bytes], (CC_LONG)[hashData length], digest);
  181. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
  182. free(digest);
  183. return result;
  184. }
  185. #pragma mark SHA224
  186. + (CocoaSecurityResult *)sha224:(NSString *)hashString
  187. {
  188. return [self sha224WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
  189. }
  190. + (CocoaSecurityResult *)sha224WithData:(NSData *)hashData
  191. {
  192. unsigned char *digest;
  193. digest = malloc(CC_SHA224_DIGEST_LENGTH);
  194. CC_SHA224([hashData bytes], (CC_LONG)[hashData length], digest);
  195. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA224_DIGEST_LENGTH];
  196. free(digest);
  197. return result;
  198. }
  199. #pragma mark SHA256
  200. + (CocoaSecurityResult *)sha256:(NSString *)hashString
  201. {
  202. return [self sha256WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
  203. }
  204. + (CocoaSecurityResult *)sha256WithData:(NSData *)hashData
  205. {
  206. unsigned char *digest;
  207. digest = malloc(CC_SHA256_DIGEST_LENGTH);
  208. CC_SHA256([hashData bytes], (CC_LONG)[hashData length], digest);
  209. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
  210. free(digest);
  211. return result;
  212. }
  213. #pragma mark SHA384
  214. + (CocoaSecurityResult *)sha384:(NSString *)hashString
  215. {
  216. return [self sha384WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
  217. }
  218. + (CocoaSecurityResult *)sha384WithData:(NSData *)hashData
  219. {
  220. unsigned char *digest;
  221. digest = malloc(CC_SHA384_DIGEST_LENGTH);
  222. CC_SHA384([hashData bytes], (CC_LONG)[hashData length], digest);
  223. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA384_DIGEST_LENGTH];
  224. free(digest);
  225. return result;
  226. }
  227. #pragma mark SHA512
  228. + (CocoaSecurityResult *)sha512:(NSString *)hashString
  229. {
  230. return [self sha512WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding]];
  231. }
  232. + (CocoaSecurityResult *)sha512WithData:(NSData *)hashData
  233. {
  234. unsigned char *digest;
  235. digest = malloc(CC_SHA512_DIGEST_LENGTH);
  236. CC_SHA512([hashData bytes], (CC_LONG)[hashData length], digest);
  237. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA512_DIGEST_LENGTH];
  238. free(digest);
  239. return result;
  240. }
  241. #pragma mark - HMAC-SHA1
  242. + (CocoaSecurityResult *)hmacSha1:(NSString *)hashString hmacKey:(NSString *)key
  243. {
  244. return [self hmacSha1WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
  245. }
  246. + (CocoaSecurityResult *)hmacSha1WithData:(NSData *)hashData hmacKey:(NSString *)key
  247. {
  248. unsigned char *digest;
  249. digest = malloc(CC_SHA1_DIGEST_LENGTH);
  250. const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
  251. CCHmac(kCCHmacAlgSHA1, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
  252. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA1_DIGEST_LENGTH];
  253. free(digest);
  254. cKey = nil;
  255. return result;
  256. }
  257. #pragma mark HMAC-SHA224
  258. + (CocoaSecurityResult *)hmacSha224:(NSString *)hashString hmacKey:(NSString *)key
  259. {
  260. return [self hmacSha224WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
  261. }
  262. + (CocoaSecurityResult *)hmacSha224WithData:(NSData *)hashData hmacKey:(NSString *)key
  263. {
  264. unsigned char *digest;
  265. digest = malloc(CC_SHA224_DIGEST_LENGTH);
  266. const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
  267. CCHmac(kCCHmacAlgSHA224, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
  268. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA224_DIGEST_LENGTH];
  269. free(digest);
  270. cKey = nil;
  271. return result;
  272. }
  273. #pragma mark HMAC-SHA256
  274. + (CocoaSecurityResult *)hmacSha256:(NSString *)hashString hmacKey:(NSString *)key
  275. {
  276. return [self hmacSha256WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
  277. }
  278. + (CocoaSecurityResult *)hmacSha256WithData:(NSData *)hashData hmacKey:(NSString *)key
  279. {
  280. unsigned char *digest;
  281. digest = malloc(CC_SHA256_DIGEST_LENGTH);
  282. const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
  283. CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
  284. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA256_DIGEST_LENGTH];
  285. free(digest);
  286. cKey = nil;
  287. return result;
  288. }
  289. #pragma mark HMAC-SHA384
  290. + (CocoaSecurityResult *)hmacSha384:(NSString *)hashString hmacKey:(NSString *)key
  291. {
  292. return [self hmacSha384WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
  293. }
  294. + (CocoaSecurityResult *)hmacSha384WithData:(NSData *)hashData hmacKey:(NSString *)key
  295. {
  296. unsigned char *digest;
  297. digest = malloc(CC_SHA384_DIGEST_LENGTH);
  298. const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
  299. CCHmac(kCCHmacAlgSHA384, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
  300. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA384_DIGEST_LENGTH];
  301. free(digest);
  302. cKey = nil;
  303. return result;
  304. }
  305. #pragma mark HMAC-SHA512
  306. + (CocoaSecurityResult *)hmacSha512:(NSString *)hashString hmacKey:(NSString *)key
  307. {
  308. return [self hmacSha512WithData:[hashString dataUsingEncoding:NSUTF8StringEncoding] hmacKey:key];
  309. }
  310. + (CocoaSecurityResult *)hmacSha512WithData:(NSData *)hashData hmacKey:(NSString *)key
  311. {
  312. unsigned char *digest;
  313. digest = malloc(CC_SHA512_DIGEST_LENGTH);
  314. const char *cKey = [key cStringUsingEncoding:NSUTF8StringEncoding];
  315. CCHmac(kCCHmacAlgSHA512, cKey, strlen(cKey), [hashData bytes], [hashData length], digest);
  316. CocoaSecurityResult *result = [[CocoaSecurityResult alloc] initWithBytes:digest length:CC_SHA512_DIGEST_LENGTH];
  317. free(digest);
  318. cKey = nil;
  319. return result;
  320. }
  321. @end
  322. #pragma mark - CocoaSecurityResult
  323. @implementation CocoaSecurityResult
  324. @synthesize data = _data;
  325. #pragma mark - Init
  326. - (id)initWithBytes:(unsigned char[])initData length:(NSUInteger)length
  327. {
  328. self = [super init];
  329. if (self) {
  330. _data = [NSData dataWithBytes:initData length:length];
  331. }
  332. return self;
  333. }
  334. #pragma mark UTF8 String
  335. // convert CocoaSecurityResult to UTF8 string
  336. - (NSString *)utf8String
  337. {
  338. NSString *result = [[NSString alloc] initWithData:_data encoding:NSUTF8StringEncoding];
  339. return result;
  340. }
  341. #pragma mark HEX
  342. // convert CocoaSecurityResult to HEX string
  343. - (NSString *)hex
  344. {
  345. CocoaSecurityEncoder *encoder = [CocoaSecurityEncoder new];
  346. return [encoder hex:_data useLower:false];
  347. }
  348. - (NSString *)hexLower
  349. {
  350. CocoaSecurityEncoder *encoder = [CocoaSecurityEncoder new];
  351. return [encoder hex:_data useLower:true];
  352. }
  353. #pragma mark Base64
  354. // convert CocoaSecurityResult to Base64 string
  355. - (NSString *)base64
  356. {
  357. CocoaSecurityEncoder *encoder = [CocoaSecurityEncoder new];
  358. return [encoder base64:_data];
  359. }
  360. @end
  361. #pragma mark - CocoaSecurityEncoder
  362. @implementation CocoaSecurityEncoder
  363. // convert NSData to Base64
  364. - (NSString *)base64:(NSData *)data
  365. {
  366. return [data base64EncodedString];
  367. }
  368. // convert NSData to hex string
  369. - (NSString *)hex:(NSData *)data useLower:(BOOL)isOutputLower
  370. {
  371. if (data.length == 0) { return nil; }
  372. static const char HexEncodeCharsLower[] = "0123456789abcdef";
  373. static const char HexEncodeChars[] = "0123456789ABCDEF";
  374. char *resultData;
  375. // malloc result data
  376. resultData = malloc([data length] * 2 +1);
  377. // convert imgData(NSData) to char[]
  378. unsigned char *sourceData = ((unsigned char *)[data bytes]);
  379. NSUInteger length = [data length];
  380. if (isOutputLower) {
  381. for (NSUInteger index = 0; index < length; index++) {
  382. // set result data
  383. resultData[index * 2] = HexEncodeCharsLower[(sourceData[index] >> 4)];
  384. resultData[index * 2 + 1] = HexEncodeCharsLower[(sourceData[index] % 0x10)];
  385. }
  386. }
  387. else {
  388. for (NSUInteger index = 0; index < length; index++) {
  389. // set result data
  390. resultData[index * 2] = HexEncodeChars[(sourceData[index] >> 4)];
  391. resultData[index * 2 + 1] = HexEncodeChars[(sourceData[index] % 0x10)];
  392. }
  393. }
  394. resultData[[data length] * 2] = 0;
  395. // convert result(char[]) to NSString
  396. NSString *result = [NSString stringWithCString:resultData encoding:NSASCIIStringEncoding];
  397. sourceData = nil;
  398. free(resultData);
  399. return result;
  400. }
  401. @end
  402. #pragma mark - CocoaSecurityDecoder
  403. @implementation CocoaSecurityDecoder
  404. - (NSData *)base64:(NSString *)string
  405. {
  406. return [NSData dataWithBase64EncodedString:string];
  407. }
  408. - (NSData *)hex:(NSString *)data
  409. {
  410. if (data.length == 0) { return nil; }
  411. static const unsigned char HexDecodeChars[] =
  412. {
  413. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  414. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  415. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  416. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  417. 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, //49
  418. 2, 3, 4, 5, 6, 7, 8, 9, 0, 0, //59
  419. 0, 0, 0, 0, 0, 10, 11, 12, 13, 14,
  420. 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, //79
  421. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  422. 0, 0, 0, 0, 0, 0, 0, 10, 11, 12, //99
  423. 13, 14, 15
  424. };
  425. // convert data(NSString) to CString
  426. const char *source = [data cStringUsingEncoding:NSUTF8StringEncoding];
  427. // malloc buffer
  428. unsigned char *buffer;
  429. NSUInteger length = strlen(source) / 2;
  430. buffer = malloc(length);
  431. for (NSUInteger index = 0; index < length; index++) {
  432. buffer[index] = (HexDecodeChars[source[index * 2]] << 4) + (HexDecodeChars[source[index * 2 + 1]]);
  433. }
  434. // init result NSData
  435. NSData *result = [NSData dataWithBytes:buffer length:length];
  436. free(buffer);
  437. source = nil;
  438. return result;
  439. }
  440. @end