JXSecurityUtil.m 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  1. //
  2. // JXSecurityUtil.m
  3. // shiku_im
  4. //
  5. // Created by p on 2019/7/10.
  6. // Copyright © 2019 Reese. All rights reserved.
  7. //
  8. #import "JXSecurityUtil.h"
  9. #import <CommonCrypto/CommonDigest.h>
  10. #import <CommonCrypto/CommonHMAC.h>
  11. #import "AESUtil.h"
  12. #import "DESUtil.h"
  13. #import "MD5Util.h"
  14. #if DEBUG
  15. #define LOGGING_FACILITY(X, Y) \
  16. NSAssert(X, Y);
  17. #define LOGGING_FACILITY1(X, Y, Z) \
  18. NSAssert1(X, Y, Z);
  19. #else
  20. #define LOGGING_FACILITY(X, Y) \
  21. if (!(X)) { \
  22. NSLog(Y); \
  23. }
  24. #define LOGGING_FACILITY1(X, Y, Z) \
  25. if (!(X)) { \
  26. NSLog(Y, Z); \
  27. }
  28. #endif
  29. @interface JXSecurityUtil ()
  30. @property (strong, nonatomic) NSString * publicIdentifier;
  31. @property (strong, nonatomic) NSString * privateIdentifier;
  32. @end
  33. @implementation JXSecurityUtil{
  34. size_t kSecAttrKeySizeInBitsLength;
  35. }
  36. +(instancetype)sharedManager {
  37. static dispatch_once_t onceToken;
  38. static JXSecurityUtil *instance;
  39. dispatch_once(&onceToken, ^{
  40. instance = [[JXSecurityUtil alloc] init];
  41. });
  42. return instance;
  43. }
  44. - (instancetype)init {
  45. if ([super init]) {
  46. _publicIdentifier = [NSString stringWithFormat:@"com.RSA.publicIdentifier.mykey.%@",g_myself.userId];
  47. _privateIdentifier = [NSString stringWithFormat:@"com.RSA.privateIdentifier.mykey.%@",g_myself.userId];
  48. // 获取本地aes加密后的私钥
  49. _privateAesStr = [g_default objectForKey:kMyPayPrivateKey];
  50. }
  51. return self;
  52. }
  53. #pragma mark ---------RSA---------
  54. // 创建最新秘钥对
  55. - (void)generateKeyPairRSA {
  56. _privateKeyRef = [self getRSAPrivateKey];
  57. _publicKeyRef = [self getRSAPublicKeyWithPrivateKey:_privateKeyRef];
  58. // OSStatus sanityCheck = noErr;
  59. // _publicKeyRef = NULL;
  60. // _privateKeyRef = NULL;
  61. //
  62. // // First delete current keys.
  63. //// [self deleteAsymmetricKeys];
  64. //
  65. // // Container dictionaries.
  66. // NSMutableDictionary * privateKeyAttr = [NSMutableDictionary dictionaryWithCapacity:0];
  67. // NSMutableDictionary * publicKeyAttr = [NSMutableDictionary dictionaryWithCapacity:0];
  68. // NSMutableDictionary * keyPairAttr = [NSMutableDictionary dictionaryWithCapacity:0];
  69. //
  70. // // Set top level dictionary for the keypair.
  71. // [keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  72. // [keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:kSecAttrKeySizeInBitsLength] forKey:(__bridge id)kSecAttrKeySizeInBits];
  73. //
  74. // // Set the private key dictionary.
  75. // [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
  76. // [privateKeyAttr setObject:_privateIdentifier forKey:(__bridge id)kSecAttrApplicationTag];
  77. // // See SecKey.h to set other flag values.
  78. //
  79. // // Set the public key dictionary.
  80. // [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
  81. // [publicKeyAttr setObject:_publicIdentifier forKey:(__bridge id)kSecAttrApplicationTag];
  82. // // See SecKey.h to set other flag values.
  83. //
  84. // // Set attributes to top level dictionary.
  85. // [keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];
  86. // [keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];
  87. //
  88. // // SecKeyGeneratePair returns the SecKeyRefs just for educational purposes.
  89. // sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &_publicKeyRef, &_privateKeyRef);
  90. // LOGGING_FACILITY( sanityCheck == noErr && _publicKeyRef != NULL && _privateKeyRef != NULL, @"Something went wrong with generating the key pair." );
  91. //
  92. // NSString *pubStr = [self getPublicKeyAsBase64];
  93. // NSString *pubJavaStr = [self getPublicKeyAsBase64ForJavaServer];
  94. // NSString *priStr = [self getPrivateKeyAsBase64];
  95. // NSLog(@"zhang_pubStr = %@", pubStr);
  96. // NSLog(@"zhang_pubJavaStr = %@", pubJavaStr);
  97. // NSLog(@"zhang_priStr = %@", priStr);
  98. }
  99. // RSA创建私钥
  100. - (SecKeyRef)getRSAPrivateKey {
  101. NSData* tag = [@"com.example.keys.mykey" dataUsingEncoding:NSUTF8StringEncoding];
  102. NSDictionary* attributes =@{
  103. (id)kSecAttrKeyType : (id)kSecAttrKeyTypeRSA,
  104. (id)kSecAttrKeySizeInBits : @1024,
  105. (id)kSecPrivateKeyAttrs : @{
  106. (id)kSecAttrIsPermanent : @YES,
  107. (id)kSecAttrApplicationTag : tag,
  108. },
  109. };
  110. CFErrorRef error = NULL;
  111. SecKeyRef privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)attributes,
  112. &error);
  113. if (!privateKey) {
  114. NSError *err = CFBridgingRelease(error); // ARC takes ownership
  115. // Handle the error. . .
  116. NSLog(@"getPrivateKeyError - %@", err);
  117. }
  118. return privateKey;
  119. }
  120. // RSA根据私钥获取公钥
  121. - (SecKeyRef)getRSAPublicKeyWithPrivateKey:(SecKeyRef)privateKey{
  122. SecKeyRef publicKey = SecKeyCopyPublicKey(privateKey);
  123. return publicKey;
  124. }
  125. - (void)setPrivateAesStr:(NSString *)privateAesStr {
  126. _privateAesStr = privateAesStr;
  127. // aes加密后的私钥保存本地
  128. [g_default setObject:privateAesStr forKey:kMyPayPrivateKey];
  129. }
  130. // 将秘钥key转data
  131. - (NSData *)getKeyBitsFromKey:(SecKeyRef)Key {
  132. CFErrorRef error = NULL;
  133. NSData* keyData = (NSData*)CFBridgingRelease( // ARC takes ownership
  134. SecKeyCopyExternalRepresentation(Key, &error)
  135. );
  136. if (!keyData) {
  137. NSError *err = CFBridgingRelease(error); // ARC takes ownership
  138. // Handle the error. . .
  139. NSLog(@"getKeyBitsFromKeyError - %@", err);
  140. }
  141. return keyData;
  142. }
  143. // 根据秘钥的base64字符串转换为秘钥key
  144. - (SecKeyRef)getRSAKeyWithBase64Str:(NSString *)base64Str isPrivateKey:(BOOL)isPrivateKey {
  145. NSData *data = [[NSData alloc]initWithBase64EncodedString:base64Str options:NSDataBase64DecodingIgnoreUnknownCharacters];
  146. // The key is assumed to be public, 2048-bit RSA
  147. NSDictionary* options;
  148. if (isPrivateKey) {
  149. options =@{
  150. (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
  151. (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
  152. (id)kSecAttrKeySizeInBits: @1024,
  153. };
  154. }else {
  155. options =@{
  156. (id)kSecAttrKeyType: (id)kSecAttrKeyTypeRSA,
  157. (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic,
  158. (id)kSecAttrKeySizeInBits: @1024,
  159. };
  160. }
  161. CFErrorRef error = NULL;
  162. SecKeyRef key = SecKeyCreateWithData((__bridge CFDataRef)data,
  163. (__bridge CFDictionaryRef)options,
  164. &error);
  165. if (!key) {
  166. NSError *err = CFBridgingRelease(error); // ARC takes ownership
  167. // Handle the error. . .
  168. }
  169. return key;
  170. }
  171. // 根据通用的key 转换为iOS秘钥base64字符串
  172. - (NSString *)getKeyForJavaServer:(NSData*)keyBits {
  173. static const unsigned char _encodedRSAEncryptionOID[15] = {
  174. /* Sequence of length 0xd made up of OID followed by NULL */
  175. 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
  176. 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00
  177. };
  178. // That gives us the "BITSTRING component of a full DER
  179. // encoded RSA public key - We now need to build the rest
  180. unsigned char builder[15];
  181. NSMutableData * encKey = [[NSMutableData alloc] init];
  182. int bitstringEncLength;
  183. // When we get to the bitstring - how will we encode it?
  184. if ([keyBits length ] + 1 < 128 )
  185. bitstringEncLength = 1 ;
  186. else
  187. bitstringEncLength = (int)(([keyBits length] + 1 ) / 256 ) + 2;
  188. // Overall we have a sequence of a certain length
  189. builder[0] = 0x30; // ASN.1 encoding representing a SEQUENCE
  190. // Build up overall size made up of -
  191. // size of OID + size of bitstring encoding + size of actual key
  192. size_t i = sizeof(_encodedRSAEncryptionOID) + 2 + bitstringEncLength +
  193. [keyBits length];
  194. size_t j = encodeLength(&builder[1], i);
  195. [encKey appendBytes:builder length:j +1];
  196. // First part of the sequence is the OID
  197. [encKey appendBytes:_encodedRSAEncryptionOID
  198. length:sizeof(_encodedRSAEncryptionOID)];
  199. // Now add the bitstring
  200. builder[0] = 0x03;
  201. j = encodeLength(&builder[1], [keyBits length] + 1);
  202. builder[j+1] = 0x00;
  203. [encKey appendBytes:builder length:j + 2];
  204. // Now the actual key
  205. [encKey appendData:keyBits];
  206. // base64 encode encKey and return
  207. return [encKey base64EncodedStringWithOptions:0];
  208. }
  209. size_t encodeLength(unsigned char * buf, size_t length) {
  210. // encode length in ASN.1 DER format
  211. if (length < 128) {
  212. buf[0] = length;
  213. return 1;
  214. }
  215. size_t i = (length / 256) + 1;
  216. buf[0] = i + 0x80;
  217. for (size_t j = 0 ; j < i; ++j) {
  218. buf[i - j] = length & 0xFF;
  219. length = length >> 8;
  220. }
  221. return i + 1;
  222. }
  223. // 删除之前存储的秘钥
  224. - (void)deleteAsymmetricKeys {
  225. OSStatus sanityCheck = noErr;
  226. NSMutableDictionary * queryPublicKey = [NSMutableDictionary dictionaryWithCapacity:0];
  227. NSMutableDictionary * queryPrivateKey = [NSMutableDictionary dictionaryWithCapacity:0];
  228. NSMutableDictionary * queryServPublicKey = [NSMutableDictionary dictionaryWithCapacity:0];
  229. // Set the public key query dictionary.
  230. [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
  231. [queryPublicKey setObject:_publicIdentifier forKey:(__bridge id)kSecAttrApplicationTag];
  232. [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  233. // Set the private key query dictionary.
  234. [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
  235. [queryPrivateKey setObject:_privateIdentifier forKey:(__bridge id)kSecAttrApplicationTag];
  236. [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  237. // Delete the private key.
  238. sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPrivateKey);
  239. LOGGING_FACILITY1( sanityCheck == noErr || sanityCheck == errSecItemNotFound, @"Error removing private key, OSStatus == %ld.", (long)sanityCheck );
  240. // Delete the public key.
  241. sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPublicKey);
  242. LOGGING_FACILITY1( sanityCheck == noErr || sanityCheck == errSecItemNotFound, @"Error removing public key, OSStatus == %ld.", (long)sanityCheck );
  243. if (_publicKeyRef) CFRelease(_publicKeyRef);
  244. if (_privateKeyRef) CFRelease(_privateKeyRef);
  245. }
  246. // 获取公钥的base64字符串
  247. - (NSString *)getRSAPublicKeyAsBase64 {
  248. return [[self getKeyBitsFromKey:_publicKeyRef] base64EncodedStringWithOptions:0];
  249. }
  250. // 获取私钥的base64字符串
  251. - (NSString *)getRSAPrivateKeyAsBase64 {
  252. return [[self getKeyBitsFromKey:_privateKeyRef] base64EncodedStringWithOptions:0];
  253. }
  254. // 获取通用公钥base64字符串
  255. - (NSString *)getRSAPublicKeyAsBase64ForJavaServer {
  256. return [self getKeyForJavaServer:[self getKeyBitsFromKey:_publicKeyRef]];
  257. }
  258. // JAVA可用base64秘钥字符串转iOS秘钥字符串
  259. - (NSString *)getPublicKeyFromJavaServer:(NSString *)keyAsBase64 {
  260. /* First decode the Base64 string */
  261. NSData *rawFormattedKey = [[NSData alloc] initWithBase64EncodedString:keyAsBase64 options:0];
  262. /* Now strip the uncessary ASN encoding guff at the start */
  263. unsigned char * bytes = (unsigned char *)[rawFormattedKey bytes];
  264. size_t bytesLen = [rawFormattedKey length];
  265. /* Strip the initial stuff */
  266. size_t i = 0;
  267. if (bytes[i++] != 0x30)
  268. return FALSE;
  269. /* Skip size bytes */
  270. if (bytes[i] > 0x80)
  271. i += bytes[i] - 0x80 + 1;
  272. else
  273. i++;
  274. if (i >= bytesLen)
  275. return FALSE;
  276. if (bytes[i] != 0x30)
  277. return FALSE;
  278. /* Skip OID */
  279. i += 15;
  280. if (i >= bytesLen - 2)
  281. return FALSE;
  282. if (bytes[i++] != 0x03)
  283. return FALSE;
  284. /* Skip length and null */
  285. if (bytes[i] > 0x80)
  286. i += bytes[i] - 0x80 + 1;
  287. else
  288. i++;
  289. if (i >= bytesLen)
  290. return FALSE;
  291. if (bytes[i++] != 0x00)
  292. return FALSE;
  293. if (i >= bytesLen)
  294. return FALSE;
  295. /* Here we go! */
  296. NSData * extractedKey = [NSData dataWithBytes:&bytes[i] length:bytesLen - i];
  297. // Base64 Encoding
  298. NSString *javaLessBase64String = [extractedKey base64EncodedStringWithOptions:0];
  299. return javaLessBase64String;
  300. }
  301. // RSA加密
  302. - (NSData *)encryptMessageRSA:(NSData *)msgData{
  303. return [self encryptMessageRSA:msgData withPublicKey:_publicKeyRef];
  304. }
  305. - (NSData *)encryptMessageRSA:(NSData *)msgData withPublicKey:(SecKeyRef)publicKey {
  306. NSData *data = msgData;
  307. size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
  308. uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
  309. memset((void *)cipherBuffer, 0*0, cipherBufferSize);
  310. NSData *plainTextBytes = data;
  311. size_t blockSize = cipherBufferSize - 11;
  312. size_t blockCount = (size_t)ceil([plainTextBytes length] / (double)blockSize);
  313. NSMutableData *encryptedData = [NSMutableData dataWithCapacity:0];
  314. for (int i=0; i<blockCount; i++) {
  315. int bufferSize = (int)MIN(blockSize,[plainTextBytes length] - i * blockSize);
  316. NSData *buffer = [plainTextBytes subdataWithRange:NSMakeRange(i * blockSize, bufferSize)];
  317. OSStatus status = SecKeyEncrypt(publicKey,
  318. kSecPaddingPKCS1,
  319. (const uint8_t *)[buffer bytes],
  320. [buffer length],
  321. cipherBuffer,
  322. &cipherBufferSize);
  323. if (status == noErr){
  324. NSData *encryptedBytes = [NSData dataWithBytes:(const void *)cipherBuffer length:cipherBufferSize];
  325. [encryptedData appendData:encryptedBytes];
  326. }else{
  327. if (cipherBuffer) {
  328. free(cipherBuffer);
  329. }
  330. return nil;
  331. }
  332. }
  333. if (cipherBuffer) free(cipherBuffer);
  334. return encryptedData;
  335. }
  336. // RSA解密
  337. - (NSData *)decryptMessageRSA:(NSData *)msgData {
  338. return [self decryptMessageRSA:msgData withPrivateKey:_privateKeyRef];
  339. }
  340. - (NSData *)decryptMessageRSA:(NSData *)msgData withPrivateKey:(SecKeyRef)privateKey {
  341. NSData *data = msgData;
  342. size_t cipherBufferSize = SecKeyGetBlockSize(privateKey);
  343. size_t keyBufferSize = [data length];
  344. NSMutableData *bits = [NSMutableData dataWithLength:keyBufferSize];
  345. OSStatus sanityCheck = SecKeyDecrypt(privateKey,
  346. kSecPaddingPKCS1,
  347. (const uint8_t *) [data bytes],
  348. cipherBufferSize,
  349. [bits mutableBytes],
  350. &keyBufferSize);
  351. if (sanityCheck != 0) {
  352. NSError *error = [NSError errorWithDomain:NSOSStatusErrorDomain code:sanityCheck userInfo:nil];
  353. NSLog(@"Error: %@", [error description]);
  354. return nil;
  355. }
  356. NSAssert(sanityCheck == noErr, @"Error decrypting, OSStatus == %ld.", (long)sanityCheck);
  357. [bits setLength:keyBufferSize];
  358. return bits;
  359. }
  360. // digest message with sha1
  361. - (NSData *)sha1:(NSString *)str
  362. {
  363. const void *data = [str cStringUsingEncoding:NSUTF8StringEncoding];
  364. CC_LONG len = (CC_LONG)strlen(data);
  365. uint8_t * md = malloc( CC_SHA1_DIGEST_LENGTH * sizeof(uint8_t) );;
  366. CC_SHA1(data, len, md);
  367. return [NSData dataWithBytes:md length:CC_SHA1_DIGEST_LENGTH];
  368. }
  369. // RSA签名
  370. - (NSString *)getSignWithRSA:(NSString *)string withPriKey:(SecKeyRef)priKey {
  371. SecKeyRef privateKeyRef = priKey;
  372. if (!privateKeyRef) { NSLog(@"添加私钥失败"); return nil; }
  373. NSData *sha1Data = [self sha1:string];
  374. unsigned char *sig = (unsigned char *)malloc(256);
  375. size_t sig_len = SecKeyGetBlockSize(privateKeyRef);
  376. OSStatus status = SecKeyRawSign(privateKeyRef, kSecPaddingPKCS1SHA1, [sha1Data bytes], CC_SHA1_DIGEST_LENGTH, sig, &sig_len);
  377. if (status != noErr) { NSLog(@"加签失败:%d",status); return nil; }
  378. NSData *outData = [NSData dataWithBytes:sig length:sig_len];
  379. return [outData base64EncodedStringWithOptions:0];
  380. }
  381. #pragma mark ---------DH---------
  382. // DH生成秘钥对
  383. - (void)generateKeyPairDH {
  384. CFErrorRef error = NULL;
  385. SecAccessControlRef sacObject;
  386. //设置ACL,使用kSecAccessControlTouchIDAny表示使用Touch ID来保护密钥。
  387. sacObject = SecAccessControlCreateWithFlags(kCFAllocatorDefault,
  388. kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly,
  389. kSecAccessControlTouchIDAny | kSecAccessControlPrivateKeyUsage, &error);
  390. NSDictionary *parameters = @{
  391. // (__bridge id)kSecAttrTokenID: (__bridge id)kSecAttrTokenIDSecureEnclave,//表示使用SecureEnclave来保存密钥
  392. (__bridge id)kSecAttrKeyType: (__bridge id)kSecAttrKeyTypeEC,//表示产生ECC密钥对,注意目前只支持256位的ECC算法
  393. (__bridge id)kSecAttrKeySizeInBits: @256,
  394. (__bridge id)kSecPrivateKeyAttrs: @{
  395. // (__bridge id)kSecAttrAccessControl: (__bridge_transfer id)sacObject,
  396. (__bridge id)kSecAttrIsPermanent: @YES,
  397. // (__bridge id)kSecAttrLabel: @"my-se-key",
  398. },
  399. };
  400. SecKeyRef publicKey, privateKey;
  401. OSStatus status = SecKeyGeneratePair((__bridge CFDictionaryRef)parameters, &publicKey, &privateKey);
  402. if (status == errSecSuccess) {
  403. NSData *privateKeyData1 = [g_securityUtil getKeyBitsFromKey:privateKey];
  404. NSData *publicKeyData1 = [g_securityUtil getKeyBitsFromKey:publicKey];
  405. NSString *priStr1 = [g_securityUtil getDHPrivateKeyAsBase64];
  406. NSString *pubStr = [g_securityUtil getDHPublicKeyAsBase64];
  407. }
  408. return;
  409. [self getDHPrivateKey];
  410. [self getDHPublicKeyWithPrivateKey];
  411. }
  412. // DH获取私钥
  413. - (SecKeyRef)getDHPrivateKey {
  414. NSData* tag = [@"com.example.keys.mykey.DH" dataUsingEncoding:NSUTF8StringEncoding];
  415. NSDictionary* attributes =@{
  416. (id)kSecAttrKeyType : (id)kSecAttrKeyTypeEC,
  417. (id)kSecAttrKeySizeInBits : @256,
  418. (id)kSecPrivateKeyAttrs : @{
  419. (id)kSecAttrIsPermanent : @NO,
  420. (id)kSecAttrApplicationTag : tag,
  421. },
  422. };
  423. CFErrorRef error = NULL;
  424. SecKeyRef privateKey = SecKeyCreateRandomKey((__bridge CFDictionaryRef)attributes,
  425. &error);
  426. if (!privateKey) {
  427. NSError *err = CFBridgingRelease(error); // ARC takes ownership
  428. // Handle the error. . .
  429. NSLog(@"getPrivateKeyError - %@", err);
  430. }
  431. _privateKeyRefDH = privateKey;
  432. return privateKey;
  433. }
  434. // DH根据私钥获取公钥
  435. - (SecKeyRef)getDHPublicKeyWithPrivateKey {
  436. SecKeyRef publicKey = SecKeyCopyPublicKey(_privateKeyRefDH);
  437. _publicKeyRefDH = publicKey;
  438. return publicKey;
  439. }
  440. // 获取共享秘钥
  441. - (NSData *) getSharedWithPrivateKey:(SecKeyRef)privateKey publicKey:(SecKeyRef)publicKey {
  442. NSString *identifier = [NSBundle mainBundle].bundleIdentifier;
  443. NSData *sharedData = [identifier dataUsingEncoding:NSUTF8StringEncoding];
  444. NSDictionary *params = @{
  445. (id)kSecKeyKeyExchangeParameterRequestedSize : @(sharedData.length),
  446. (id)kSecKeyKeyExchangeParameterSharedInfo : sharedData
  447. };
  448. CFErrorRef error = NULL;
  449. CFDataRef dataRef = SecKeyCopyKeyExchangeResult(privateKey, kSecKeyAlgorithmECDHKeyExchangeStandardX963SHA256, publicKey, (__bridge CFDictionaryRef)params, &error);
  450. return (__bridge NSData *)dataRef;
  451. }
  452. // 获取公钥base64
  453. - (NSString *)getDHPublicKeyAsBase64 {
  454. return [[self getKeyBitsFromKey:_publicKeyRefDH] base64EncodedStringWithOptions:0];
  455. }
  456. // 获取私钥base64
  457. - (NSString *)getDHPrivateKeyAsBase64 {
  458. return [[self getKeyBitsFromKey:_privateKeyRefDH] base64EncodedStringWithOptions:0];
  459. }
  460. //根据base64字符串获取秘钥
  461. - (SecKeyRef)getDHKeyWithBase64Str:(NSString *)base64Str isPrivateKey:(BOOL)isPrivateKey {
  462. NSData *data = [[NSData alloc]initWithBase64EncodedString:base64Str options:NSDataBase64DecodingIgnoreUnknownCharacters];
  463. // The key is assumed to be public, 2048-bit RSA
  464. NSDictionary* options;
  465. if (isPrivateKey) {
  466. options =@{
  467. (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC,
  468. (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPrivate,
  469. (id)kSecAttrKeySizeInBits: @256,
  470. };
  471. }else {
  472. options =@{
  473. (id)kSecAttrKeyType: (id)kSecAttrKeyTypeEC,
  474. (id)kSecAttrKeyClass: (id)kSecAttrKeyClassPublic,
  475. (id)kSecAttrKeySizeInBits: @256,
  476. };
  477. }
  478. CFErrorRef error = NULL;
  479. SecKeyRef key = SecKeyCreateWithData((__bridge CFDataRef)data,
  480. (__bridge CFDictionaryRef)options,
  481. &error);
  482. if (!key) {
  483. NSError *err = CFBridgingRelease(error); // ARC takes ownership
  484. // Handle the error. . .
  485. }
  486. return key;
  487. }
  488. // 公钥转换成JAVA可用的base64
  489. - (NSString *)getDHPublicKeyAsBase64ForJavaServer {
  490. return [self getKeyForJavaServer:[self getKeyBitsFromKey:_publicKeyRefDH]];
  491. }
  492. // 获取mac值(HMACMD5算法)
  493. - (NSData *)getHMACMD5:(NSData *)data key:(NSData *)keyData {
  494. size_t dataLength = data.length;
  495. NSData *keys = keyData;
  496. size_t keyLength = keys.length;
  497. unsigned char result[CC_MD5_DIGEST_LENGTH];
  498. CCHmac(kCCHmacAlgMD5, [keys bytes], keyLength, [data bytes], dataLength, result);
  499. for (int i = 0; i < CC_MD5_DIGEST_LENGTH; i ++) {
  500. printf("%d ",result[i]);
  501. }
  502. printf("\n-------%s-------\n",result);
  503. //这里需要将result 转base64编码,再传回去
  504. NSData *data1 = [[NSData alloc] initWithBytes:result length:sizeof(result)];
  505. // NSString *base64 = [data1 base64EncodedStringWithOptions:0];
  506. return data1;
  507. }
  508. void CCHmac(CCHmacAlgorithm algorithm,/* kCCHmacAlgSHA1, kCCHmacAlgMD5 */
  509. const void *key,
  510. size_t keyLength,/* length of key in bytes */
  511. const void *data,
  512. size_t dataLength,/* length of data in bytes */
  513. void *macOut)/* MAC written here */
  514. __OSX_AVAILABLE_STARTING(__MAC_10_4, __IPHONE_2_0);
  515. @end