RSATool.m 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. /*
  2. @author: ideawu
  3. @link: https://github.com/ideawu/Objective-C-RSA
  4. */
  5. #import "RSATool.h"
  6. // RSA加密需要头文件
  7. #import <Security/Security.h>
  8. // AES加密需要头文件
  9. #import "CommonCrypto/CommonDigest.h"
  10. #import <CommonCrypto/CommonCrypto.h>
  11. // Base64加密需要的key
  12. static const char encodingTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
  13. @implementation RSATool
  14. /*
  15. static NSString *base64_encode(NSString *str){
  16. NSData* data = [str dataUsingEncoding:NSUTF8StringEncoding];
  17. if(!data){
  18. return nil;
  19. }
  20. return base64_encode_data(data);
  21. }
  22. */
  23. #pragma mark RSATool 自带方法
  24. static NSString *base64_encode_data(NSData *data){
  25. data = [data base64EncodedDataWithOptions:0];
  26. NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  27. return ret;
  28. }
  29. static NSData *base64_decode(NSString *str){
  30. NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
  31. return data;
  32. }
  33. + (NSData *)stripPublicKeyHeader:(NSData *)d_key{
  34. // Skip ASN.1 public key header
  35. if (d_key == nil) return(nil);
  36. unsigned long len = [d_key length];
  37. if (!len) return(nil);
  38. unsigned char *c_key = (unsigned char *)[d_key bytes];
  39. unsigned int idx = 0;
  40. if (c_key[idx++] != 0x30) return(nil);
  41. if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
  42. else idx++;
  43. // PKCS #1 RSAToolEncryption szOID_RSATool_RSATool
  44. static unsigned char seqiod[] =
  45. { 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
  46. 0x01, 0x05, 0x00 };
  47. if (memcmp(&c_key[idx], seqiod, 15)) return(nil);
  48. idx += 15;
  49. if (c_key[idx++] != 0x03) return(nil);
  50. if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
  51. else idx++;
  52. if (c_key[idx++] != '\0') return(nil);
  53. // Now make a new NSData from this buffer
  54. return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
  55. }
  56. //credit: http://hg.mozilla.org/services/fx-home/file/tip/Sources/NetworkAndStorage/CryptoUtils.m#l1036
  57. #pragma mark RAS加密(公钥签名 私钥解密)
  58. + (NSData *)stripPrivateKeyHeader:(NSData *)d_key{
  59. // Skip ASN.1 private key header
  60. if (d_key == nil) return(nil);
  61. unsigned long len = [d_key length];
  62. if (!len) return(nil);
  63. unsigned char *c_key = (unsigned char *)[d_key bytes];
  64. unsigned int idx = 22; //magic byte at offset 22
  65. if (0x04 != c_key[idx++]) return nil;
  66. //calculate length of the key
  67. unsigned int c_len = c_key[idx++];
  68. int det = c_len & 0x80;
  69. if (!det) {
  70. c_len = c_len & 0x7f;
  71. } else {
  72. int byteCount = c_len & 0x7f;
  73. if (byteCount + idx > len) {
  74. //RSATool length field longer than buffer
  75. return nil;
  76. }
  77. unsigned int accum = 0;
  78. unsigned char *ptr = &c_key[idx];
  79. idx += byteCount;
  80. while (byteCount) {
  81. accum = (accum << 8) + *ptr;
  82. ptr++;
  83. byteCount--;
  84. }
  85. c_len = accum;
  86. }
  87. // Now make a new NSData from this buffer
  88. return [d_key subdataWithRange:NSMakeRange(idx, c_len)];
  89. }
  90. + (SecKeyRef)addPublicKey:(NSString *)key{
  91. NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
  92. NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];
  93. if(spos.location != NSNotFound && epos.location != NSNotFound){
  94. NSUInteger s = spos.location + spos.length;
  95. NSUInteger e = epos.location;
  96. NSRange range = NSMakeRange(s, e-s);
  97. key = [key substringWithRange:range];
  98. }
  99. key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
  100. key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
  101. key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
  102. key = [key stringByReplacingOccurrencesOfString:@" " withString:@""];
  103. // This will be base64 encoded, decode it.
  104. NSData *data = base64_decode(key);
  105. data = [RSATool stripPublicKeyHeader:data];
  106. if(!data){
  107. return nil;
  108. }
  109. //a tag to read/write keychain storage
  110. NSString *tag = @"RSAToolUtil_PubKey";
  111. NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
  112. // Delete any old lingering key with the same tag
  113. NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
  114. [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
  115. [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  116. [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
  117. SecItemDelete((__bridge CFDictionaryRef)publicKey);
  118. // Add persistent version of the key to system keychain
  119. [publicKey setObject:data forKey:(__bridge id)kSecValueData];
  120. [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)
  121. kSecAttrKeyClass];
  122. [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
  123. kSecReturnPersistentRef];
  124. CFTypeRef persistKey = nil;
  125. OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
  126. if (persistKey != nil){
  127. CFRelease(persistKey);
  128. }
  129. if ((status != noErr) && (status != errSecDuplicateItem)) {
  130. return nil;
  131. }
  132. [publicKey removeObjectForKey:(__bridge id)kSecValueData];
  133. [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
  134. [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
  135. [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  136. // Now fetch the SecKeyRef version of the key
  137. SecKeyRef keyRef = nil;
  138. status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
  139. if(status != noErr){
  140. return nil;
  141. }
  142. return keyRef;
  143. }
  144. + (SecKeyRef)addPrivateKey:(NSString *)key{
  145. NSRange spos;
  146. NSRange epos;
  147. spos = [key rangeOfString:@"-----BEGIN RSATool PRIVATE KEY-----"];
  148. if(spos.length > 0){
  149. epos = [key rangeOfString:@"-----END RSATool PRIVATE KEY-----"];
  150. }else{
  151. spos = [key rangeOfString:@"-----BEGIN PRIVATE KEY-----"];
  152. epos = [key rangeOfString:@"-----END PRIVATE KEY-----"];
  153. }
  154. if(spos.location != NSNotFound && epos.location != NSNotFound){
  155. NSUInteger s = spos.location + spos.length;
  156. NSUInteger e = epos.location;
  157. NSRange range = NSMakeRange(s, e-s);
  158. key = [key substringWithRange:range];
  159. }
  160. key = [key stringByReplacingOccurrencesOfString:@"\r" withString:@""];
  161. key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
  162. key = [key stringByReplacingOccurrencesOfString:@"\t" withString:@""];
  163. key = [key stringByReplacingOccurrencesOfString:@" " withString:@""];
  164. // This will be base64 encoded, decode it.
  165. NSData *data = base64_decode(key);
  166. data = [RSATool stripPrivateKeyHeader:data];
  167. if(!data){
  168. return nil;
  169. }
  170. //a tag to read/write keychain storage
  171. NSString *tag = @"RSAToolUtil_PrivKey";
  172. NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
  173. // Delete any old lingering key with the same tag
  174. NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];
  175. [privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
  176. [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  177. [privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
  178. SecItemDelete((__bridge CFDictionaryRef)privateKey);
  179. // Add persistent version of the key to system keychain
  180. [privateKey setObject:data forKey:(__bridge id)kSecValueData];
  181. [privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)
  182. kSecAttrKeyClass];
  183. [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
  184. kSecReturnPersistentRef];
  185. CFTypeRef persistKey = nil;
  186. OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);
  187. if (persistKey != nil){
  188. CFRelease(persistKey);
  189. }
  190. if ((status != noErr) && (status != errSecDuplicateItem)) {
  191. return nil;
  192. }
  193. [privateKey removeObjectForKey:(__bridge id)kSecValueData];
  194. [privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
  195. [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
  196. [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  197. // Now fetch the SecKeyRef version of the key
  198. SecKeyRef keyRef = nil;
  199. status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
  200. if(status != noErr){
  201. return nil;
  202. }
  203. return keyRef;
  204. }
  205. /* START: Encryption & Decryption with RSATool private key */
  206. + (NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef isSign:(BOOL)isSign {
  207. const uint8_t *srcbuf = (const uint8_t *)[data bytes];
  208. size_t srclen = (size_t)data.length;
  209. size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
  210. void *outbuf = malloc(block_size);
  211. size_t src_block_size = block_size - 11;
  212. NSMutableData *ret = [[NSMutableData alloc] init];
  213. for(int idx=0; idx<srclen; idx+=src_block_size){
  214. //KyoLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
  215. size_t data_len = srclen - idx;
  216. if(data_len > src_block_size){
  217. data_len = src_block_size;
  218. }
  219. size_t outlen = block_size;
  220. OSStatus status = noErr;
  221. if (isSign) {
  222. status = SecKeyRawSign(keyRef,
  223. kSecPaddingPKCS1,
  224. srcbuf + idx,
  225. data_len,
  226. outbuf,
  227. &outlen
  228. );
  229. } else {
  230. status = SecKeyEncrypt(keyRef,
  231. kSecPaddingPKCS1,
  232. srcbuf + idx,
  233. data_len,
  234. outbuf,
  235. &outlen
  236. );
  237. }
  238. if (status != 0) {
  239. KyoLog(@"SecKeyEncrypt fail. Error Code: %d", status);
  240. ret = nil;
  241. break;
  242. }else{
  243. [ret appendBytes:outbuf length:outlen];
  244. }
  245. }
  246. free(outbuf);
  247. // CFRelease(keyRef);
  248. return ret;
  249. }
  250. + (NSString *)encryptString:(NSString *)str privateKey:(NSString *)privKey{
  251. NSData *data = [RSATool encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] privateKey:privKey];
  252. NSString *ret = base64_encode_data(data);
  253. return ret;
  254. }
  255. + (NSData *)encryptData:(NSData *)data privateKey:(NSString *)privKey{
  256. if(!data || !privKey){
  257. return nil;
  258. }
  259. SecKeyRef keyRef = [RSATool addPrivateKey:privKey];
  260. if(!keyRef){
  261. return nil;
  262. }
  263. return [RSATool encryptData:data withKeyRef:keyRef isSign:YES];
  264. }
  265. + (NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
  266. const uint8_t *srcbuf = (const uint8_t *)[data bytes];
  267. size_t srclen = (size_t)data.length;
  268. size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
  269. UInt8 *outbuf = malloc(block_size);
  270. size_t src_block_size = block_size;
  271. NSMutableData *ret = [[NSMutableData alloc] init];
  272. for(int idx=0; idx<srclen; idx+=src_block_size){
  273. //KyoLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
  274. size_t data_len = srclen - idx;
  275. if(data_len > src_block_size){
  276. data_len = src_block_size;
  277. }
  278. size_t outlen = block_size;
  279. OSStatus status = noErr;
  280. status = SecKeyDecrypt(keyRef,
  281. kSecPaddingNone,
  282. srcbuf + idx,
  283. data_len,
  284. outbuf,
  285. &outlen
  286. );
  287. if (status != 0) {
  288. KyoLog(@"SecKeyEncrypt fail. Error Code: %d", status);
  289. ret = nil;
  290. break;
  291. }else{
  292. //the actual decrypted data is in the middle, locate it!
  293. int idxFirstZero = -1;
  294. int idxNextZero = (int)outlen;
  295. for ( int i = 0; i < outlen; i++ ) {
  296. if ( outbuf[i] == 0 ) {
  297. if ( idxFirstZero < 0 ) {
  298. idxFirstZero = i;
  299. } else {
  300. idxNextZero = i;
  301. break;
  302. }
  303. }
  304. }
  305. [ret appendBytes:&outbuf[idxFirstZero+1] length:idxNextZero-idxFirstZero-1];
  306. }
  307. }
  308. free(outbuf);
  309. // CFRelease(keyRef);
  310. return ret;
  311. }
  312. + (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey{
  313. NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
  314. data = [RSATool decryptData:data privateKey:privKey];
  315. NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  316. return ret;
  317. }
  318. + (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey{
  319. if(!data || !privKey){
  320. return nil;
  321. }
  322. SecKeyRef keyRef = [RSATool addPrivateKey:privKey];
  323. if(!keyRef){
  324. return nil;
  325. }
  326. return [RSATool decryptData:data withKeyRef:keyRef];
  327. }
  328. /* END: Encryption & Decryption with RSATool private key */
  329. /* START: Encryption & Decryption with RSATool public key */
  330. + (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey{
  331. NSData *data = [RSATool encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];
  332. NSString *ret = base64_encode_data(data);
  333. return ret;
  334. }
  335. + (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{
  336. if(!data || !pubKey){
  337. return nil;
  338. }
  339. SecKeyRef keyRef = [RSATool addPublicKey:pubKey];
  340. if(!keyRef){
  341. return nil;
  342. }
  343. return [RSATool encryptData:data withKeyRef:keyRef isSign:NO];
  344. }
  345. + (NSString *)decryptString:(NSString *)str publicKey:(NSString *)pubKey{
  346. NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
  347. data = [RSATool decryptData:data publicKey:pubKey];
  348. NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  349. return ret;
  350. }
  351. + (NSData *)decryptData:(NSData *)data publicKey:(NSString *)pubKey{
  352. if(!data || !pubKey){
  353. return nil;
  354. }
  355. SecKeyRef keyRef = [RSATool addPublicKey:pubKey];
  356. if(!keyRef){
  357. return nil;
  358. }
  359. return [RSATool decryptData:data withKeyRef:keyRef];
  360. }
  361. /* END: Encryption & Decryption with RSATool public key */
  362. #pragma mark RSA签名 (私钥签名 公钥验签)
  363. //// 1. PKCS1格式的RSA私钥的字符串转SecKeyRef
  364. //+ (SecKeyRef)addRSAPrivateKey:(NSString *)key {
  365. //
  366. // // This is a base64 encoded key. so, decode it.
  367. // NSData *data = [[NSData alloc] initWithBase64EncodedString:key options:NSDataBase64DecodingIgnoreUnknownCharacters];
  368. //
  369. // if(!data){ return nil; }
  370. // //a tag to read/write keychain storage
  371. // NSString *tag = @"RSA_PRIVATE_KEY";
  372. // NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
  373. //
  374. // // Delete any old lingering key with the same tag
  375. // NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];
  376. // [privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
  377. // [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  378. // [privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
  379. // SecItemDelete((__bridge CFDictionaryRef)privateKey);
  380. //
  381. // // Add persistent version of the key to system keychain
  382. // [privateKey setObject:data forKey:(__bridge id)kSecValueData];
  383. // [privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)kSecAttrKeyClass];
  384. // [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef];
  385. //
  386. // CFTypeRef persistKey = nil;
  387. // OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);
  388. // if (persistKey != nil){ CFRelease(persistKey); }
  389. // if ((status != noErr) && (status != errSecDuplicateItem)) { return nil; }
  390. //
  391. // [privateKey removeObjectForKey:(__bridge id)kSecValueData];
  392. // [privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
  393. // [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
  394. // [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  395. //
  396. // // Now fetch the SecKeyRef version of the key
  397. // SecKeyRef keyRef = nil;
  398. // status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
  399. // if(status != noErr){
  400. // return nil;
  401. // }
  402. // return keyRef;
  403. //}
  404. //
  405. //// 2. 公钥字符串转SeckeyRef
  406. //+ (SecKeyRef)addRSAPublicKey:(NSString *)pubKey
  407. //{
  408. // NSData *data = [[NSData alloc] initWithBase64EncodedString:pubKey options:NSDataBase64DecodingIgnoreUnknownCharacters];
  409. //
  410. // //a tag to read/write keychain storage
  411. // NSString *tag = @"RSA_PUBLIC_KEY";
  412. // NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
  413. //
  414. // // Delete any old lingering key with the same tag
  415. // NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
  416. // [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
  417. // [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  418. // [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
  419. // SecItemDelete((__bridge CFDictionaryRef)publicKey);
  420. //
  421. // // Add persistent version of the key to system keychain
  422. // [publicKey setObject:data forKey:(__bridge id)kSecValueData];
  423. // [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)kSecAttrKeyClass];
  424. // [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef];
  425. //
  426. // CFTypeRef persistKey = nil;
  427. // OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
  428. // if (persistKey != nil){
  429. // CFRelease(persistKey);
  430. // }
  431. //
  432. // if ((status != noErr) && (status != errSecDuplicateItem)) { return nil; }
  433. //
  434. // [publicKey removeObjectForKey:(__bridge id)kSecValueData];
  435. // [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
  436. // [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
  437. // [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  438. //
  439. // // Now fetch the SecKeyRef version of the key
  440. // SecKeyRef keyRef = nil;
  441. // status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
  442. // if(status != noErr){
  443. // return nil;
  444. // }
  445. // return keyRef;
  446. //}
  447. // 3.1 SHA1算法的实现
  448. + (NSData *)sha1:(NSString *)str
  449. {
  450. const void *data = [str cStringUsingEncoding:NSUTF8StringEncoding];
  451. CC_LONG len = (CC_LONG)strlen(data);
  452. uint8_t * md = malloc( CC_SHA1_DIGEST_LENGTH * sizeof(uint8_t) );;
  453. CC_SHA1(data, len, md);
  454. return [NSData dataWithBytes:md length:CC_SHA1_DIGEST_LENGTH];
  455. }
  456. // 3.2 SHA256算法的实现
  457. + (NSData *)sha256:(NSString *)str
  458. {
  459. // const char *cstr = [self cStringUsingEncoding:NSUTF8StringEncoding];
  460. // NSData*data=[NSData dataWithBytes:cstr length:self.length];
  461. // uint8_t digest[CC_SHA256_DIGEST_LENGTH];
  462. // CC_SHA256(data.bytes, data.length,digest);
  463. // NSMutableString *output=[NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2];
  464. // for(inti=0; i < CC_SHA256_DIGEST_LENGTH; i++)
  465. // [output appendFormat:@"%02x", digest[i]];
  466. // return output;CC_SHA256_BLOCK_BYTES
  467. const void *data = [str cStringUsingEncoding:NSUTF8StringEncoding];
  468. CC_LONG len = (CC_LONG)strlen(data);
  469. uint8_t * md = malloc( CC_SHA256_DIGEST_LENGTH * sizeof(uint8_t) );;
  470. CC_SHA256(data, len, md);
  471. return [NSData dataWithBytes:md length:CC_SHA256_DIGEST_LENGTH];
  472. }
  473. + (NSMutableString *)sha256_64:(NSString *)str
  474. {
  475. const char *cstr = [str cStringUsingEncoding:NSUTF8StringEncoding];
  476. NSData*data=[NSData dataWithBytes:cstr length:str.length];
  477. uint8_t digest[CC_SHA256_DIGEST_LENGTH];
  478. CC_SHA256(data.bytes, data.length,digest);
  479. NSMutableString *output=[NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH*2];
  480. for(int i=0; i < CC_SHA256_DIGEST_LENGTH; i++)
  481. [output appendFormat:@"%02x", digest[i]];
  482. return output;
  483. }
  484. + (NSString *)sha256_8:(NSString *)str
  485. {
  486. NSMutableString * str64 = [self sha256_64:str];
  487. NSString *str8 = [str64 substringToIndex:8];
  488. str8 = [str8 uppercaseString];
  489. return str8;
  490. }
  491. // 4. 使用RSA私钥签名的实现
  492. + (NSString *)sign:(NSString *)content withPriKey:(NSString *)priKey
  493. {
  494. SecKeyRef privateKeyRef = [self addPrivateKey:priKey];
  495. if (!privateKeyRef) { KyoLog(@"添加私钥失败"); return nil; }
  496. NSData *sha256Data = [self sha256:content];
  497. unsigned char *sig = (unsigned char *)malloc(256);
  498. size_t sig_len;
  499. OSStatus status = SecKeyRawSign(privateKeyRef, kSecPaddingPKCS1SHA256, [sha256Data bytes], CC_SHA256_DIGEST_LENGTH, sig, &sig_len);
  500. if (status != noErr) { KyoLog(@"加签失败:%d",status); return nil; }
  501. NSData *outData = [NSData dataWithBytes:sig length:sig_len];
  502. return [outData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
  503. }
  504. // 5. 使用RSA公钥验签的实现
  505. + (BOOL)verify:(NSString *)content signature:(NSString *)signature withPublivKey:(NSString *)publicKey {
  506. SecKeyRef publicKeyRef = [self addPublicKey:publicKey];
  507. if (!publicKeyRef) { KyoLog(@"添加公钥失败"); return NO; }
  508. NSData *originData = [self sha256:content];
  509. NSData *signatureData = [[NSData alloc] initWithBase64EncodedString:signature options:NSDataBase64DecodingIgnoreUnknownCharacters];
  510. if (!originData || !signatureData) { return NO; }
  511. OSStatus status = SecKeyRawVerify(publicKeyRef, kSecPaddingPKCS1SHA256, [originData bytes], originData.length, [signatureData bytes], signatureData.length);
  512. if (status ==noErr) { return YES; }
  513. else{ KyoLog(@"验签失败:%d",status); return NO; }
  514. }
  515. #pragma mark 加密/解密(AES RSA base64 md5)
  516. // AES加密
  517. + (NSString *)AES128Encrypt:(NSString *)plainText key:(NSString *)key
  518. {
  519. char keyPtr[kCCKeySizeAES128+1];
  520. memset(keyPtr, 0, sizeof(keyPtr));
  521. [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
  522. NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
  523. NSUInteger dataLength = [data length];
  524. size_t bufferSize = dataLength + kCCBlockSizeAES128;
  525. void *buffer = malloc(bufferSize);
  526. size_t numBytesEncrypted = 0;
  527. CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
  528. kCCAlgorithmAES128,
  529. kCCOptionPKCS7Padding|kCCOptionECBMode,
  530. keyPtr,
  531. kCCBlockSizeAES128,
  532. NULL,
  533. [data bytes],
  534. dataLength,
  535. buffer,
  536. bufferSize,
  537. &numBytesEncrypted);
  538. if (cryptStatus == kCCSuccess) {
  539. NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted];
  540. return [resultData base64EncodedStringWithOptions:(NSDataBase64Encoding64CharacterLineLength)];
  541. }
  542. free(buffer);
  543. return nil;
  544. }
  545. //AES解密
  546. + (NSString *)AES128Decrypt:(NSString *)encryptText key:(NSString *)key
  547. {
  548. char keyPtr[kCCKeySizeAES128 + 1];
  549. memset(keyPtr, 0, sizeof(keyPtr));
  550. [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
  551. NSData *data = [[NSData alloc] initWithBase64EncodedString:encryptText options:NSDataBase64DecodingIgnoreUnknownCharacters];//base64解码
  552. NSUInteger dataLength = [data length];
  553. size_t bufferSize = dataLength + kCCBlockSizeAES128;
  554. void *buffer = malloc(bufferSize);
  555. size_t numBytesCrypted = 0;
  556. CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
  557. kCCAlgorithmAES128,
  558. kCCOptionPKCS7Padding|kCCOptionECBMode,
  559. keyPtr,
  560. kCCBlockSizeAES128,
  561. NULL,
  562. [data bytes],
  563. dataLength,
  564. buffer,
  565. bufferSize,
  566. &numBytesCrypted);
  567. if (cryptStatus == kCCSuccess) {
  568. NSData *resultData = [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
  569. return [[NSString alloc] initWithData:resultData encoding:NSUTF8StringEncoding];
  570. }
  571. free(buffer);
  572. return nil;
  573. }
  574. /**RSA加密-publicKey-公钥*/
  575. + (NSString *)RSAEncrypt:(NSString *)plainText key:(NSString *)publicKey {
  576. NSString *encrypted = [RSATool encryptString:plainText publicKey:publicKey];
  577. return encrypted;
  578. }
  579. /**RSA解密-privateKey-私钥*/
  580. + (NSString *)RSADecrypt:(NSString *)encryptText key:(NSString *)privateKey {
  581. NSString *decrypted = [RSATool decryptString:encryptText privateKey:privateKey];
  582. return decrypted;
  583. }
  584. /**RSA私钥签名-privateKey-私钥*/
  585. + (NSString *)RSASignEncrypt:(NSString *)plainText key:(NSString *)privateKey {
  586. NSString *encrypted = [RSATool sign:plainText withPriKey:privateKey];
  587. return encrypted;
  588. }
  589. /**RSA公钥验签-publicKey-公钥 encryptText-密文 plainText-明文*/
  590. + (BOOL)RSASignDecrypt:(NSString *)encryptText Encrypt:(NSString *)plainText key:(NSString *)publicKey {
  591. BOOL decrypted = [RSATool verify:plainText signature:encryptText withPublivKey:publicKey];
  592. return decrypted;
  593. }
  594. /**Base64加密*/
  595. + (NSString *)Base64Encrypt:(NSString *)plainText {
  596. NSData *data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
  597. return [data base64EncodedStringWithOptions:0];
  598. }
  599. /**base64解密*/
  600. + (NSString *)Base64Decrypt:(NSString *)encryptText {
  601. NSData *data = [self dataWithBase64EncodedString:encryptText];
  602. return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
  603. }
  604. /**base64格式字符串转换为文本数据*/
  605. + (NSData *)dataWithBase64EncodedString:(NSString *)string
  606. {
  607. if (string == nil)
  608. [NSException raise:NSInvalidArgumentException format:@""];
  609. if ([string length] == 0)
  610. return [NSData data];
  611. static char *decodingTable = NULL;
  612. if (decodingTable == NULL)
  613. {
  614. decodingTable = (char *)malloc(256);
  615. if (decodingTable == NULL)
  616. return nil;
  617. memset(decodingTable, CHAR_MAX, 256);
  618. NSUInteger i;
  619. for (i = 0; i < 64; i++)
  620. decodingTable[(short)encodingTable[i]] = i;
  621. }
  622. const char *characters = [string cStringUsingEncoding:NSASCIIStringEncoding];
  623. if (characters == NULL) // Not an ASCII string!
  624. return nil;
  625. char *bytes = (char *)malloc((([string length] + 3) / 4) * 3);
  626. if (bytes == NULL)
  627. return nil;
  628. NSUInteger length = 0;
  629. NSUInteger i = 0;
  630. while (YES)
  631. {
  632. char buffer[4];
  633. short bufferLength;
  634. for (bufferLength = 0; bufferLength < 4; i++)
  635. {
  636. if (characters[i] == '\0')
  637. break;
  638. if (isspace(characters[i]) || characters[i] == '=')
  639. continue;
  640. buffer[bufferLength] = decodingTable[(short)characters[i]];
  641. if (buffer[bufferLength++] == CHAR_MAX) // Illegal character!
  642. {
  643. free(bytes);
  644. return nil;
  645. }
  646. }
  647. if (bufferLength == 0)
  648. break;
  649. if (bufferLength == 1) // At least two characters are needed to produce one byte!
  650. {
  651. free(bytes);
  652. return nil;
  653. }
  654. // Decode the characters in the buffer to bytes.
  655. bytes[length++] = (buffer[0] << 2) | (buffer[1] >> 4);
  656. if (bufferLength > 2)
  657. bytes[length++] = (buffer[1] << 4) | (buffer[2] >> 2);
  658. if (bufferLength > 3)
  659. bytes[length++] = (buffer[2] << 6) | buffer[3];
  660. }
  661. bytes = (char *)realloc(bytes, length);
  662. return [NSData dataWithBytesNoCopy:bytes length:length];
  663. }
  664. /**md5加密*/
  665. + (NSString *)md5Encrypt:(NSString *)encryptText{
  666. const char *cStr = [encryptText UTF8String];
  667. unsigned char result[CC_MD5_DIGEST_LENGTH];
  668. CC_MD5(cStr, strlen(cStr), result);
  669. return [[NSString stringWithFormat:@"%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
  670. result[0], result[1], result[2], result[3],
  671. result[4], result[5], result[6], result[7],
  672. result[8], result[9], result[10], result[11],
  673. result[12], result[13], result[14], result[15]
  674. ] lowercaseString];
  675. }
  676. #pragma mark - RSA加密demo
  677. - (void)RSA {
  678. NSString *pubkey = @"-----BEGIN PUBLIC KEY-----\nMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDDI2bvVLVYrb4B0raZgFP60VXY\ncvRmk9q56QiTmEm9HXlSPq1zyhyPQHGti5FokYJMzNcKm0bwL1q6ioJuD4EFI56D\na+70XdRz1CjQPQE3yXrXXVvOsmq9LsdxTFWsVBTehdCmrapKZVVx6PKl7myh0cfX\nQmyveT/eqyZK1gYjvQIDAQAB\n-----END PUBLIC KEY-----";
  679. NSString *privkey = @"-----BEGIN PRIVATE KEY-----\nMIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMMjZu9UtVitvgHS\ntpmAU/rRVdhy9GaT2rnpCJOYSb0deVI+rXPKHI9Aca2LkWiRgkzM1wqbRvAvWrqK\ngm4PgQUjnoNr7vRd1HPUKNA9ATfJetddW86yar0ux3FMVaxUFN6F0KatqkplVXHo\n8qXubKHRx9dCbK95P96rJkrWBiO9AgMBAAECgYBO1UKEdYg9pxMX0XSLVtiWf3Na\n2jX6Ksk2Sfp5BhDkIcAdhcy09nXLOZGzNqsrv30QYcCOPGTQK5FPwx0mMYVBRAdo\nOLYp7NzxW/File//169O3ZFpkZ7MF0I2oQcNGTpMCUpaY6xMmxqN22INgi8SHp3w\nVU+2bRMLDXEc/MOmAQJBAP+Sv6JdkrY+7WGuQN5O5PjsB15lOGcr4vcfz4vAQ/uy\nEGYZh6IO2Eu0lW6sw2x6uRg0c6hMiFEJcO89qlH/B10CQQDDdtGrzXWVG457vA27\nkpduDpM6BQWTX6wYV9zRlcYYMFHwAQkE0BTvIYde2il6DKGyzokgI6zQyhgtRJ1x\nL6fhAkB9NvvW4/uWeLw7CHHVuVersZBmqjb5LWJU62v3L2rfbT1lmIqAVr+YT9CK\n2fAhPPtkpYYo5d4/vd1sCY1iAQ4tAkEAm2yPrJzjMn2G/ry57rzRzKGqUChOFrGs\nlm7HF6CQtAs4HC+2jC0peDyg97th37rLmPLB9txnPl50ewpkZuwOAQJBAM/eJnFw\nF5QAcL4CYDbfBKocx82VX/pFXng50T7FODiWbbL4UnxICE0UBFInNNiWJxNEb6jL\n5xd0pcy9O2DOeso=\n-----END PRIVATE KEY-----";
  680. NSString *encrypted = [RSATool encryptString:@"hello world!" publicKey:pubkey];
  681. HLog(@"encrypted: %@", encrypted);
  682. NSString *decrypted = [RSATool decryptString:encrypted privateKey:privkey];
  683. HLog(@"decrypted: %@", decrypted);
  684. }
  685. #pragma mark 其他
  686. // 传入一个原始字典,依据ascii码从小到大排序,回传一个排好序的待签名字符串
  687. + (NSString *)sortArrWithDictionary:(NSDictionary *)dictionary {
  688. // 取出所有的key值
  689. NSArray *keys = [dictionary allKeys];
  690. //按字母顺序排序
  691. NSArray *sortedArray = [keys sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
  692. return [obj1 compare:obj2 options:NSNumericSearch];
  693. }];
  694. // 将排好的序的key值重新赋值
  695. NSMutableArray *jsonArr = [NSMutableArray array];
  696. [sortedArray enumerateObjectsUsingBlock:^(NSString * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
  697. // 取出每一个keyValue值
  698. id value = dictionary[obj];
  699. NSString *str = @"";
  700. if ([value isKindOfClass:[NSString class]]) {
  701. str = [NSString stringWithFormat:@"\"%@\":\"%@\"", obj, dictionary[obj]];
  702. }else {
  703. str = [NSString stringWithFormat:@"\"%@\":%@", obj, dictionary[obj]];
  704. }
  705. [jsonArr addObject:str];
  706. }];
  707. // 将做好排序的数组转出字符串
  708. NSString *result = [jsonArr componentsJoinedByString:@","];
  709. result = [NSString stringWithFormat:@"{%@}", result];
  710. return result;
  711. }
  712. /**删除字符串里的换行符 \r 和 \n */
  713. + (NSString *)deleteNewlineCharactersWithString:(NSString *)text {
  714. // //去除掉首尾的空白字符和换行字符
  715. text = [text stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
  716. text = [text stringByReplacingOccurrencesOfString:@"\r" withString:@""];
  717. text = [text stringByReplacingOccurrencesOfString:@"\n" withString:@""];
  718. return text;
  719. }
  720. //#pragma mark 登录密码加密算法:MD5➕RSA
  721. //+ (NSString *)getRSAStringFrom:(NSString *)pwd {
  722. // /**密码加密算法:MD5➕RSA*/
  723. // NSString *publicKey = [HWDataManager getStringWithKey:Const_HWRSAPublicKey];
  724. // NSString *pwdMD5 = [RSATool md5Encrypt:pwd];
  725. // NSString *pwdRSA = [RSATool RSAEncrypt:pwdMD5 key:publicKey];
  726. // return pwdRSA;
  727. //}
  728. @end