RSACryptor.m 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. //
  2. // RSACryptor.m
  3. //
  4. #import "RSACryptor.h"
  5. // 填充模式 kSecPaddingNone 每次加密结果是固定的,kSecPaddingPKCS1是随机变化的
  6. #define kTypeOfWrapPadding kSecPaddingNone
  7. // 公钥/私钥标签
  8. #define kPublicKeyTag "com.wendingding.sample.publickey"
  9. #define kPrivateKeyTag "com.wendingding.sample.privatekey"
  10. static const uint8_t publicKeyIdentifier[] = kPublicKeyTag;
  11. static const uint8_t privateKeyIdentifier[] = kPrivateKeyTag;
  12. @interface RSACryptor() {
  13. SecKeyRef publicKeyRef; // 公钥引用
  14. SecKeyRef privateKeyRef; // 私钥引用
  15. }
  16. @property (nonatomic, retain) NSData *publicTag; // 公钥标签
  17. @property (nonatomic, retain) NSData *privateTag; // 私钥标签
  18. @end
  19. @implementation RSACryptor
  20. + (instancetype)sharedRSACryptor {
  21. static id instance;
  22. static dispatch_once_t onceToken;
  23. dispatch_once(&onceToken, ^{
  24. instance = [[self alloc] init];
  25. });
  26. return instance;
  27. }
  28. - (instancetype)init {
  29. self = [super init];
  30. if (self) {
  31. // 查询密钥的标签
  32. _privateTag = [[NSData alloc] initWithBytes:privateKeyIdentifier length:sizeof(privateKeyIdentifier)];
  33. _publicTag = [[NSData alloc] initWithBytes:publicKeyIdentifier length:sizeof(publicKeyIdentifier)];
  34. }
  35. return self;
  36. }
  37. #pragma mark - 加密 & 解密数据
  38. - (NSData *)encryptData:(NSData *)plainData {
  39. OSStatus sanityCheck = noErr;
  40. size_t cipherBufferSize = 0;
  41. size_t keyBufferSize = 0;
  42. NSAssert(plainData != nil, @"明文数据为空");
  43. NSAssert(publicKeyRef != nil, @"公钥为空");
  44. NSData *cipher = nil;
  45. uint8_t *cipherBuffer = NULL;
  46. // 计算缓冲区大小
  47. cipherBufferSize = SecKeyGetBlockSize(publicKeyRef);
  48. keyBufferSize = [plainData length];
  49. if (kTypeOfWrapPadding == kSecPaddingNone) {
  50. NSAssert(keyBufferSize <= cipherBufferSize, @"加密内容太大");
  51. } else {
  52. NSAssert(keyBufferSize <= (cipherBufferSize - 11), @"加密内容太大");
  53. }
  54. // 分配缓冲区
  55. cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
  56. memset((void *)cipherBuffer, 0x0, cipherBufferSize);
  57. // 使用公钥加密
  58. sanityCheck = SecKeyEncrypt(publicKeyRef,
  59. kTypeOfWrapPadding,
  60. (const uint8_t *)[plainData bytes],
  61. keyBufferSize,
  62. cipherBuffer,
  63. &cipherBufferSize
  64. );
  65. NSAssert(sanityCheck == noErr, @"加密错误,OSStatus == %d", (int)sanityCheck);
  66. // 生成密文数据
  67. cipher = [NSData dataWithBytes:(const void *)cipherBuffer length:(NSUInteger)cipherBufferSize];
  68. if (cipherBuffer) free(cipherBuffer);
  69. return cipher;
  70. }
  71. - (NSData *)decryptData:(NSData *)cipherData {
  72. OSStatus sanityCheck = noErr;
  73. size_t cipherBufferSize = 0;
  74. size_t keyBufferSize = 0;
  75. NSData *key = nil;
  76. uint8_t *keyBuffer = NULL;
  77. SecKeyRef privateKey = NULL;
  78. privateKey = [self getPrivateKeyRef];
  79. NSAssert(privateKey != NULL, @"私钥不存在");
  80. // 计算缓冲区大小
  81. cipherBufferSize = SecKeyGetBlockSize(privateKey);
  82. keyBufferSize = [cipherData length];
  83. NSAssert(keyBufferSize <= cipherBufferSize, @"解密内容太大");
  84. // 分配缓冲区
  85. keyBuffer = malloc(keyBufferSize * sizeof(uint8_t));
  86. memset((void *)keyBuffer, 0x0, keyBufferSize);
  87. // 使用私钥解密
  88. sanityCheck = SecKeyDecrypt(privateKey,
  89. kTypeOfWrapPadding,
  90. (const uint8_t *)[cipherData bytes],
  91. cipherBufferSize,
  92. keyBuffer,
  93. &keyBufferSize
  94. );
  95. NSAssert1(sanityCheck == noErr, @"解密错误,OSStatus == %d", sanityCheck);
  96. // 生成明文数据
  97. key = [NSData dataWithBytes:(const void *)keyBuffer length:(NSUInteger)keyBufferSize];
  98. if (keyBuffer) free(keyBuffer);
  99. return key;
  100. }
  101. #pragma mark - 密钥处理
  102. /**
  103. * 生成密钥对
  104. */
  105. - (void)generateKeyPair:(NSUInteger)keySize {
  106. OSStatus sanityCheck = noErr;
  107. publicKeyRef = NULL;
  108. privateKeyRef = NULL;
  109. NSAssert1((keySize == 512 || keySize == 1024 || keySize == 2048), @"密钥尺寸无效 %tu", keySize);
  110. // 删除当前密钥对
  111. [self deleteAsymmetricKeys];
  112. // 容器字典
  113. NSMutableDictionary *privateKeyAttr = [[NSMutableDictionary alloc] init];
  114. NSMutableDictionary *publicKeyAttr = [[NSMutableDictionary alloc] init];
  115. NSMutableDictionary *keyPairAttr = [[NSMutableDictionary alloc] init];
  116. // 设置密钥对的顶级字典
  117. [keyPairAttr setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  118. [keyPairAttr setObject:[NSNumber numberWithUnsignedInteger:keySize] forKey:(__bridge id)kSecAttrKeySizeInBits];
  119. // 设置私钥字典
  120. [privateKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
  121. [privateKeyAttr setObject:_privateTag forKey:(__bridge id)kSecAttrApplicationTag];
  122. // 设置公钥字典
  123. [publicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecAttrIsPermanent];
  124. [publicKeyAttr setObject:_publicTag forKey:(__bridge id)kSecAttrApplicationTag];
  125. // 设置顶级字典属性
  126. [keyPairAttr setObject:privateKeyAttr forKey:(__bridge id)kSecPrivateKeyAttrs];
  127. [keyPairAttr setObject:publicKeyAttr forKey:(__bridge id)kSecPublicKeyAttrs];
  128. // SecKeyGeneratePair 返回密钥对引用
  129. sanityCheck = SecKeyGeneratePair((__bridge CFDictionaryRef)keyPairAttr, &publicKeyRef, &privateKeyRef);
  130. NSAssert((sanityCheck == noErr && publicKeyRef != NULL && privateKeyRef != NULL), @"生成密钥对失败");
  131. }
  132. /**
  133. * 加载公钥
  134. */
  135. - (void)loadPublicKey:(NSString *)publicKeyPath {
  136. NSAssert(publicKeyPath.length != 0, @"公钥路径为空");
  137. // 删除当前公钥
  138. if (publicKeyRef) CFRelease(publicKeyRef);
  139. // 从一个 DER 表示的证书创建一个证书对象
  140. NSData *certificateData = [NSData dataWithContentsOfFile:publicKeyPath];
  141. SecCertificateRef certificateRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);
  142. NSAssert(certificateRef != NULL, @"公钥文件错误");
  143. // 返回一个默认 X509 策略的公钥对象,使用之后需要调用 CFRelease 释放
  144. SecPolicyRef policyRef = SecPolicyCreateBasicX509();
  145. // 包含信任管理信息的结构体
  146. SecTrustRef trustRef;
  147. // 基于证书和策略创建一个信任管理对象
  148. OSStatus status = SecTrustCreateWithCertificates(certificateRef, policyRef, &trustRef);
  149. NSAssert(status == errSecSuccess, @"创建信任管理对象失败");
  150. // 信任结果
  151. SecTrustResultType trustResult;
  152. // 评估指定证书和策略的信任管理是否有效
  153. status = SecTrustEvaluate(trustRef, &trustResult);
  154. NSAssert(status == errSecSuccess, @"信任评估失败");
  155. // 评估之后返回公钥子证书
  156. publicKeyRef = SecTrustCopyPublicKey(trustRef);
  157. NSAssert(publicKeyRef != NULL, @"公钥创建失败");
  158. if (certificateRef) CFRelease(certificateRef);
  159. if (policyRef) CFRelease(policyRef);
  160. if (trustRef) CFRelease(trustRef);
  161. }
  162. /**
  163. * 加载私钥
  164. */
  165. - (void)loadPrivateKey:(NSString *)privateKeyPath password:(NSString *)password {
  166. NSAssert(privateKeyPath.length != 0, @"私钥路径为空");
  167. // 删除当前私钥
  168. if (privateKeyRef) CFRelease(privateKeyRef);
  169. NSData *PKCS12Data = [NSData dataWithContentsOfFile:privateKeyPath];
  170. CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
  171. CFStringRef passwordRef = (__bridge CFStringRef)password;
  172. // 从 PKCS #12 证书中提取标示和证书
  173. SecIdentityRef myIdentity;
  174. SecTrustRef myTrust;
  175. const void *keys[] = {kSecImportExportPassphrase};
  176. const void *values[] = {passwordRef};
  177. CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
  178. CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
  179. // 返回 PKCS #12 格式数据中的标示和证书
  180. OSStatus status = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
  181. if (status == noErr) {
  182. CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
  183. myIdentity = (SecIdentityRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
  184. myTrust = (SecTrustRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
  185. }
  186. if (optionsDictionary) CFRelease(optionsDictionary);
  187. NSAssert(status == noErr, @"提取身份和信任失败");
  188. SecTrustResultType trustResult;
  189. // 评估指定证书和策略的信任管理是否有效
  190. status = SecTrustEvaluate(myTrust, &trustResult);
  191. NSAssert(status == errSecSuccess, @"信任评估失败");
  192. // 提取私钥
  193. status = SecIdentityCopyPrivateKey(myIdentity, &privateKeyRef);
  194. NSAssert(status == errSecSuccess, @"私钥创建失败");
  195. }
  196. /**
  197. * 删除非对称密钥
  198. */
  199. - (void)deleteAsymmetricKeys {
  200. OSStatus sanityCheck = noErr;
  201. NSMutableDictionary *queryPublicKey = [[NSMutableDictionary alloc] init];
  202. NSMutableDictionary *queryPrivateKey = [[NSMutableDictionary alloc] init];
  203. // 设置公钥查询字典
  204. [queryPublicKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
  205. [queryPublicKey setObject:_publicTag forKey:(__bridge id)kSecAttrApplicationTag];
  206. [queryPublicKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  207. // 设置私钥查询字典
  208. [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
  209. [queryPrivateKey setObject:_privateTag forKey:(__bridge id)kSecAttrApplicationTag];
  210. [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  211. // 删除私钥
  212. sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPrivateKey);
  213. NSAssert1((sanityCheck == noErr || sanityCheck == errSecItemNotFound), @"删除私钥错误,OSStatus == %d", sanityCheck);
  214. // 删除公钥
  215. sanityCheck = SecItemDelete((__bridge CFDictionaryRef)queryPublicKey);
  216. NSAssert1((sanityCheck == noErr || sanityCheck == errSecItemNotFound), @"删除公钥错误,OSStatus == %d", sanityCheck);
  217. if (publicKeyRef) CFRelease(publicKeyRef);
  218. if (privateKeyRef) CFRelease(privateKeyRef);
  219. }
  220. /**
  221. * 获得私钥引用
  222. */
  223. - (SecKeyRef)getPrivateKeyRef {
  224. OSStatus sanityCheck = noErr;
  225. SecKeyRef privateKeyReference = NULL;
  226. if (privateKeyRef == NULL) {
  227. NSMutableDictionary * queryPrivateKey = [[NSMutableDictionary alloc] init];
  228. // 设置私钥查询字典
  229. [queryPrivateKey setObject:(__bridge id)kSecClassKey forKey:(__bridge id)kSecClass];
  230. [queryPrivateKey setObject:_privateTag forKey:(__bridge id)kSecAttrApplicationTag];
  231. [queryPrivateKey setObject:(__bridge id)kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
  232. [queryPrivateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
  233. // 获得密钥
  234. sanityCheck = SecItemCopyMatching((__bridge CFDictionaryRef)queryPrivateKey, (CFTypeRef *)&privateKeyReference);
  235. if (sanityCheck != noErr) {
  236. privateKeyReference = NULL;
  237. }
  238. } else {
  239. privateKeyReference = privateKeyRef;
  240. }
  241. return privateKeyReference;
  242. }
  243. @end