CryptorTools.m 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. //
  2. // CryptorTools.m
  3. // xingchuangke
  4. //
  5. // Created by Virgil on 2019/5/5.
  6. // Copyright © 2019 Virgil. All rights reserved.
  7. //
  8. #import "CryptorTools.h"
  9. #import <CommonCrypto/CommonCrypto.h>
  10. // 填充模式
  11. #define kTypeOfWrapPadding kSecPaddingPKCS1
  12. @interface CryptorTools() {
  13. SecKeyRef _publicKeyRef; // 公钥引用
  14. SecKeyRef _privateKeyRef; // 私钥引用
  15. }
  16. @end
  17. @implementation CryptorTools
  18. #pragma mark - DES 加密/解密
  19. #pragma mark 加密
  20. + (NSData *)DESEncryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {
  21. return [self CCCryptData:data algorithm:kCCAlgorithmDES operation:kCCEncrypt keyString:keyString iv:iv];
  22. }
  23. + (NSString *)DESEncryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
  24. NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
  25. NSData *result = [self DESEncryptData:data keyString:keyString iv:iv];
  26. // BASE 64 编码
  27. return [result base64EncodedStringWithOptions:0];
  28. }
  29. #pragma mark 解密
  30. + (NSData *)DESDecryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {
  31. return [self CCCryptData:data algorithm:kCCAlgorithmDES operation:kCCDecrypt keyString:keyString iv:iv];
  32. }
  33. + (NSString *)DESDecryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
  34. // BASE 64 解码
  35. NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
  36. NSData *result = [self DESDecryptData:data keyString:keyString iv:iv];
  37. return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
  38. }
  39. #pragma mark - AES 加密/解密
  40. #pragma mark 加密
  41. + (NSData *)AESEncryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {
  42. return [self CCCryptData:data algorithm:kCCAlgorithmAES operation:kCCEncrypt keyString:keyString iv:iv];
  43. }
  44. + (NSString *)AESEncryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
  45. NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
  46. NSData *result = [self AESEncryptData:data keyString:keyString iv:iv];
  47. // BASE 64 编码
  48. return [result base64EncodedStringWithOptions:0];
  49. }
  50. + (NSData *)AESEncryptString:(NSString *)string keyData:(NSString *)keyData iv:(NSData *)iv {
  51. NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
  52. NSData *result = [self CCCryptData:data algorithm:kCCAlgorithmAES operation:kCCEncrypt keyData:keyData iv:iv];
  53. // BASE 64 编码
  54. return result;//[result base64EncodedStringWithOptions:0];
  55. }
  56. #pragma mark 解密
  57. + (NSData *)AESDecryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {
  58. return [self CCCryptData:data algorithm:kCCAlgorithmAES operation:kCCDecrypt keyString:keyString iv:iv];
  59. }
  60. + (NSData *)AESDecryptData:(NSData *)data keyData:(NSString *)keyData iv:(NSData *)iv {
  61. return [self CCCryptData:data algorithm:kCCAlgorithmAES operation:kCCDecrypt keyData:keyData iv:iv];
  62. }
  63. + (NSString *)AESDecryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
  64. // BASE 64 解码
  65. NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
  66. NSData *result = [self AESDecryptData:data keyString:keyString iv:iv];
  67. return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
  68. }
  69. #pragma mark 对称加密&解密核心方法
  70. /// 对称加密&解密核心方法
  71. ///
  72. /// @param data 加密/解密的二进制数据
  73. /// @param algorithm 加密算法
  74. /// @param operation 加密/解密操作
  75. /// @param keyString 密钥字符串
  76. /// @param iv IV 向量
  77. ///
  78. /// @return 加密/解密结果
  79. + (NSData *)CCCryptData:(NSData *)data algorithm:(CCAlgorithm)algorithm operation:(CCOperation)operation keyData:(NSData *)keyData iv:(NSData *)iv {
  80. int keySize = (algorithm == kCCAlgorithmAES) ? kCCKeySizeAES128 : kCCKeySizeDES;
  81. int blockSize = (algorithm == kCCAlgorithmAES) ? kCCBlockSizeAES128: kCCBlockSizeDES;
  82. // 设置密钥
  83. //NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
  84. uint8_t cKey[keySize];
  85. bzero(cKey, sizeof(cKey));
  86. [keyData getBytes:cKey length:keySize];
  87. // 设置 IV 向量
  88. uint8_t cIv[blockSize];
  89. bzero(cIv, blockSize);
  90. int option = kCCOptionPKCS7Padding | kCCOptionECBMode;
  91. if (iv) {
  92. [iv getBytes:cIv length:blockSize];
  93. option = kCCOptionPKCS7Padding;
  94. }
  95. // 设置输出缓冲区
  96. size_t bufferSize = [data length] + blockSize;
  97. void *buffer = malloc(bufferSize);
  98. // 加密或解密
  99. size_t cryptorSize = 0;
  100. CCCryptorStatus cryptStatus = CCCrypt(operation,
  101. algorithm,
  102. option,
  103. cKey,
  104. keySize,
  105. cIv,
  106. [data bytes],
  107. [data length],
  108. buffer,
  109. bufferSize,
  110. &cryptorSize);
  111. NSData *result = nil;
  112. if (cryptStatus == kCCSuccess) {
  113. result = [NSData dataWithBytesNoCopy:buffer length:cryptorSize];
  114. } else {
  115. free(buffer);
  116. NSLog(@"[错误] 加密或解密失败 | 状态编码: %d", cryptStatus);
  117. }
  118. return result;
  119. }
  120. /// 对称加密&解密核心方法
  121. ///
  122. /// @param data 加密/解密的二进制数据
  123. /// @param algorithm 加密算法
  124. /// @param operation 加密/解密操作
  125. /// @param keyString 密钥字符串
  126. /// @param iv IV 向量
  127. ///
  128. /// @return 加密/解密结果
  129. + (NSData *)CCCryptData:(NSData *)data algorithm:(CCAlgorithm)algorithm operation:(CCOperation)operation keyString:(NSString *)keyString iv:(NSData *)iv {
  130. // 设置密钥
  131. NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
  132. return [self CCCryptData:data algorithm:algorithm operation:operation keyData:keyData iv:iv];
  133. }
  134. #pragma mark - RSA 加密/解密算法
  135. - (void)loadPublicKeyWithFilePath:(NSString *)filePath; {
  136. NSAssert(filePath.length != 0, @"公钥路径为空");
  137. // 删除当前公钥
  138. if (_publicKeyRef) CFRelease(_publicKeyRef);
  139. // 从一个 DER 表示的证书创建一个证书对象
  140. NSData *certificateData = [NSData dataWithContentsOfFile:filePath];
  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. - (void)loadPrivateKey:(NSString *)filePath password:(NSString *)password {
  163. NSAssert(filePath.length != 0, @"私钥路径为空");
  164. // 删除当前私钥
  165. if (_privateKeyRef) CFRelease(_privateKeyRef);
  166. NSData *PKCS12Data = [NSData dataWithContentsOfFile:filePath];
  167. CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
  168. CFStringRef passwordRef = (__bridge CFStringRef)password;
  169. // 从 PKCS #12 证书中提取标示和证书
  170. SecIdentityRef myIdentity;
  171. SecTrustRef myTrust;
  172. const void *keys[] = {kSecImportExportPassphrase};
  173. const void *values[] = {passwordRef};
  174. CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
  175. CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
  176. // 返回 PKCS #12 格式数据中的标示和证书
  177. OSStatus status = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
  178. if (status == noErr) {
  179. CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
  180. myIdentity = (SecIdentityRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
  181. myTrust = (SecTrustRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
  182. }
  183. if (optionsDictionary) CFRelease(optionsDictionary);
  184. NSAssert(status == noErr, @"提取身份和信任失败");
  185. SecTrustResultType trustResult;
  186. // 评估指定证书和策略的信任管理是否有效
  187. status = SecTrustEvaluate(myTrust, &trustResult);
  188. NSAssert(status == errSecSuccess, @"信任评估失败");
  189. // 提取私钥
  190. status = SecIdentityCopyPrivateKey(myIdentity, &_privateKeyRef);
  191. NSAssert(status == errSecSuccess, @"私钥创建失败");
  192. CFRelease(items);
  193. }
  194. - (NSString *)RSAEncryptString:(NSString *)string {
  195. NSData *cipher = [self RSAEncryptData:[string dataUsingEncoding:NSUTF8StringEncoding]];
  196. return [cipher base64EncodedStringWithOptions:0];
  197. }
  198. - (NSData *)RSAEncryptStringData:(NSString *)string {
  199. NSData *cipher = [self RSAEncryptData:[string dataUsingEncoding:NSUTF8StringEncoding]];
  200. return cipher;
  201. }
  202. - (NSData *)RSAEncryptData:(NSData *)data {
  203. OSStatus sanityCheck = noErr;
  204. size_t cipherBufferSize = 0;
  205. size_t keyBufferSize = 0;
  206. NSAssert(data, @"明文数据为空");
  207. NSAssert(_publicKeyRef, @"公钥为空");
  208. NSData *cipher = nil;
  209. uint8_t *cipherBuffer = NULL;
  210. // 计算缓冲区大小
  211. cipherBufferSize = SecKeyGetBlockSize(_publicKeyRef);
  212. keyBufferSize = data.length;
  213. if (kTypeOfWrapPadding == kSecPaddingNone) {
  214. NSAssert(keyBufferSize <= cipherBufferSize, @"加密内容太大");
  215. } else {
  216. NSAssert(keyBufferSize <= (cipherBufferSize - 11), @"加密内容太大");
  217. }
  218. // 分配缓冲区
  219. cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
  220. memset((void *)cipherBuffer, 0x0, cipherBufferSize);
  221. //SecKeyCreateEncryptedData(_publicKeyRef, kSecKeyAlgorithmRSAEncryptionPKCS1, <#CFDataRef _Nonnull plaintext#>, <#CFErrorRef _Nullable * _Nullable error#>)
  222. // 使用公钥加密
  223. sanityCheck = SecKeyEncrypt(_publicKeyRef,
  224. kSecPaddingNone,
  225. (const uint8_t *)data.bytes,
  226. keyBufferSize,
  227. cipherBuffer,
  228. &cipherBufferSize
  229. );
  230. NSAssert(sanityCheck == noErr, @"加密错误,OSStatus == %d", sanityCheck);
  231. // 生成密文数据
  232. cipher = [NSData dataWithBytes:(const void *)cipherBuffer length:(NSUInteger)cipherBufferSize];
  233. if (cipherBuffer) free(cipherBuffer);
  234. return cipher;
  235. }
  236. - (NSString *)RSADecryptString:(NSString *)string {
  237. NSData *keyData = [self RSADecryptData:[[NSData alloc] initWithBase64EncodedString:string options:0]];
  238. return [[NSString alloc] initWithData:keyData encoding:NSUTF8StringEncoding];
  239. }
  240. - (NSData *)RSADecryptData:(NSData *)data {
  241. OSStatus sanityCheck = noErr;
  242. size_t cipherBufferSize = 0;
  243. size_t keyBufferSize = 0;
  244. NSData *key = nil;
  245. uint8_t *keyBuffer = NULL;
  246. SecKeyRef privateKey = _publicKeyRef;//_privateKeyRef;
  247. NSAssert(privateKey != NULL, @"私钥不存在");
  248. // 计算缓冲区大小
  249. cipherBufferSize = SecKeyGetBlockSize(privateKey);
  250. keyBufferSize = data.length;
  251. NSAssert(keyBufferSize <= cipherBufferSize, @"解密内容太大");
  252. // 分配缓冲区
  253. keyBuffer = malloc(keyBufferSize * sizeof(uint8_t));
  254. memset((void *)keyBuffer, 0x0, keyBufferSize);
  255. // 使用私钥解密
  256. sanityCheck = SecKeyDecrypt(privateKey,
  257. kSecPaddingNone,
  258. (const uint8_t *)data.bytes,
  259. cipherBufferSize,
  260. keyBuffer,
  261. &keyBufferSize
  262. );
  263. NSAssert1(sanityCheck == noErr, @"解密错误,OSStatus == %d", sanityCheck);
  264. // 生成明文数据
  265. key = [NSData dataWithBytes:(const void *)keyBuffer length:(NSUInteger)keyBufferSize];
  266. if (keyBuffer) free(keyBuffer);
  267. return key;
  268. }
  269. - (NSString *)sha256:(NSString *)string
  270. {
  271. const char *cstr = [string cStringUsingEncoding:NSUTF8StringEncoding];
  272. NSData *data = [NSData dataWithBytes:cstr length:string.length];
  273. uint8_t digest[CC_SHA256_DIGEST_LENGTH];
  274. CC_SHA256(data.bytes, data.length, digest);
  275. NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
  276. for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++)
  277. [output appendFormat:@"%02x", digest[i]];
  278. return output;
  279. }
  280. @end