123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358 |
- //
- // CryptorTools.m
- // xingchuangke
- //
- // Created by Virgil on 2019/5/5.
- // Copyright © 2019 Virgil. All rights reserved.
- //
- #import "CryptorTools.h"
- #import <CommonCrypto/CommonCrypto.h>
- // 填充模式
- #define kTypeOfWrapPadding kSecPaddingPKCS1
- @interface CryptorTools() {
- SecKeyRef _publicKeyRef; // 公钥引用
- SecKeyRef _privateKeyRef; // 私钥引用
- }
- @end
- @implementation CryptorTools
- #pragma mark - DES 加密/解密
- #pragma mark 加密
- + (NSData *)DESEncryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {
- return [self CCCryptData:data algorithm:kCCAlgorithmDES operation:kCCEncrypt keyString:keyString iv:iv];
- }
- + (NSString *)DESEncryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
- NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
- NSData *result = [self DESEncryptData:data keyString:keyString iv:iv];
-
- // BASE 64 编码
- return [result base64EncodedStringWithOptions:0];
- }
- #pragma mark 解密
- + (NSData *)DESDecryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {
- return [self CCCryptData:data algorithm:kCCAlgorithmDES operation:kCCDecrypt keyString:keyString iv:iv];
- }
- + (NSString *)DESDecryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
- // BASE 64 解码
- NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
- NSData *result = [self DESDecryptData:data keyString:keyString iv:iv];
-
- return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
- }
- #pragma mark - AES 加密/解密
- #pragma mark 加密
- + (NSData *)AESEncryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {
- return [self CCCryptData:data algorithm:kCCAlgorithmAES operation:kCCEncrypt keyString:keyString iv:iv];
- }
- + (NSString *)AESEncryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
- NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
- NSData *result = [self AESEncryptData:data keyString:keyString iv:iv];
-
- // BASE 64 编码
- return [result base64EncodedStringWithOptions:0];
- }
- + (NSData *)AESEncryptString:(NSString *)string keyData:(NSString *)keyData iv:(NSData *)iv {
- NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
- NSData *result = [self CCCryptData:data algorithm:kCCAlgorithmAES operation:kCCEncrypt keyData:keyData iv:iv];
- // BASE 64 编码
- return result;//[result base64EncodedStringWithOptions:0];
- }
- #pragma mark 解密
- + (NSData *)AESDecryptData:(NSData *)data keyString:(NSString *)keyString iv:(NSData *)iv {
- return [self CCCryptData:data algorithm:kCCAlgorithmAES operation:kCCDecrypt keyString:keyString iv:iv];
- }
- + (NSData *)AESDecryptData:(NSData *)data keyData:(NSString *)keyData iv:(NSData *)iv {
- return [self CCCryptData:data algorithm:kCCAlgorithmAES operation:kCCDecrypt keyData:keyData iv:iv];
- }
- + (NSString *)AESDecryptString:(NSString *)string keyString:(NSString *)keyString iv:(NSData *)iv {
- // BASE 64 解码
- NSData *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
- NSData *result = [self AESDecryptData:data keyString:keyString iv:iv];
-
- return [[NSString alloc] initWithData:result encoding:NSUTF8StringEncoding];
- }
- #pragma mark 对称加密&解密核心方法
- /// 对称加密&解密核心方法
- ///
- /// @param data 加密/解密的二进制数据
- /// @param algorithm 加密算法
- /// @param operation 加密/解密操作
- /// @param keyString 密钥字符串
- /// @param iv IV 向量
- ///
- /// @return 加密/解密结果
- + (NSData *)CCCryptData:(NSData *)data algorithm:(CCAlgorithm)algorithm operation:(CCOperation)operation keyData:(NSData *)keyData iv:(NSData *)iv {
-
- int keySize = (algorithm == kCCAlgorithmAES) ? kCCKeySizeAES128 : kCCKeySizeDES;
- int blockSize = (algorithm == kCCAlgorithmAES) ? kCCBlockSizeAES128: kCCBlockSizeDES;
-
- // 设置密钥
- //NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
- uint8_t cKey[keySize];
- bzero(cKey, sizeof(cKey));
- [keyData getBytes:cKey length:keySize];
-
- // 设置 IV 向量
- uint8_t cIv[blockSize];
- bzero(cIv, blockSize);
- int option = kCCOptionPKCS7Padding | kCCOptionECBMode;
- if (iv) {
- [iv getBytes:cIv length:blockSize];
- option = kCCOptionPKCS7Padding;
- }
-
- // 设置输出缓冲区
- size_t bufferSize = [data length] + blockSize;
- void *buffer = malloc(bufferSize);
-
- // 加密或解密
- size_t cryptorSize = 0;
- CCCryptorStatus cryptStatus = CCCrypt(operation,
- algorithm,
- option,
- cKey,
- keySize,
- cIv,
- [data bytes],
- [data length],
- buffer,
- bufferSize,
- &cryptorSize);
-
- NSData *result = nil;
- if (cryptStatus == kCCSuccess) {
- result = [NSData dataWithBytesNoCopy:buffer length:cryptorSize];
- } else {
- free(buffer);
- NSLog(@"[错误] 加密或解密失败 | 状态编码: %d", cryptStatus);
- }
-
- return result;
- }
- /// 对称加密&解密核心方法
- ///
- /// @param data 加密/解密的二进制数据
- /// @param algorithm 加密算法
- /// @param operation 加密/解密操作
- /// @param keyString 密钥字符串
- /// @param iv IV 向量
- ///
- /// @return 加密/解密结果
- + (NSData *)CCCryptData:(NSData *)data algorithm:(CCAlgorithm)algorithm operation:(CCOperation)operation keyString:(NSString *)keyString iv:(NSData *)iv {
- // 设置密钥
- NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
- return [self CCCryptData:data algorithm:algorithm operation:operation keyData:keyData iv:iv];
- }
- #pragma mark - RSA 加密/解密算法
- - (void)loadPublicKeyWithFilePath:(NSString *)filePath; {
-
- NSAssert(filePath.length != 0, @"公钥路径为空");
-
- // 删除当前公钥
- if (_publicKeyRef) CFRelease(_publicKeyRef);
-
- // 从一个 DER 表示的证书创建一个证书对象
- NSData *certificateData = [NSData dataWithContentsOfFile:filePath];
- SecCertificateRef certificateRef = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);
- NSAssert(certificateRef != NULL, @"公钥文件错误");
-
- // 返回一个默认 X509 策略的公钥对象,使用之后需要调用 CFRelease 释放
- SecPolicyRef policyRef = SecPolicyCreateBasicX509();
- // 包含信任管理信息的结构体
- SecTrustRef trustRef;
-
- // 基于证书和策略创建一个信任管理对象
- OSStatus status = SecTrustCreateWithCertificates(certificateRef, policyRef, &trustRef);
- NSAssert(status == errSecSuccess, @"创建信任管理对象失败");
-
- // 信任结果
- SecTrustResultType trustResult;
- // 评估指定证书和策略的信任管理是否有效
- status = SecTrustEvaluate(trustRef, &trustResult);
- NSAssert(status == errSecSuccess, @"信任评估失败");
-
- // 评估之后返回公钥子证书
- _publicKeyRef = SecTrustCopyPublicKey(trustRef);
- NSAssert(_publicKeyRef != NULL, @"公钥创建失败");
-
- if (certificateRef) CFRelease(certificateRef);
- if (policyRef) CFRelease(policyRef);
- if (trustRef) CFRelease(trustRef);
- }
- - (void)loadPrivateKey:(NSString *)filePath password:(NSString *)password {
-
- NSAssert(filePath.length != 0, @"私钥路径为空");
-
- // 删除当前私钥
- if (_privateKeyRef) CFRelease(_privateKeyRef);
-
- NSData *PKCS12Data = [NSData dataWithContentsOfFile:filePath];
- CFDataRef inPKCS12Data = (__bridge CFDataRef)PKCS12Data;
- CFStringRef passwordRef = (__bridge CFStringRef)password;
-
- // 从 PKCS #12 证书中提取标示和证书
- SecIdentityRef myIdentity;
- SecTrustRef myTrust;
- const void *keys[] = {kSecImportExportPassphrase};
- const void *values[] = {passwordRef};
- CFDictionaryRef optionsDictionary = CFDictionaryCreate(NULL, keys, values, 1, NULL, NULL);
- CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
-
- // 返回 PKCS #12 格式数据中的标示和证书
- OSStatus status = SecPKCS12Import(inPKCS12Data, optionsDictionary, &items);
-
- if (status == noErr) {
- CFDictionaryRef myIdentityAndTrust = CFArrayGetValueAtIndex(items, 0);
- myIdentity = (SecIdentityRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemIdentity);
- myTrust = (SecTrustRef)CFDictionaryGetValue(myIdentityAndTrust, kSecImportItemTrust);
- }
-
- if (optionsDictionary) CFRelease(optionsDictionary);
-
- NSAssert(status == noErr, @"提取身份和信任失败");
-
- SecTrustResultType trustResult;
- // 评估指定证书和策略的信任管理是否有效
- status = SecTrustEvaluate(myTrust, &trustResult);
- NSAssert(status == errSecSuccess, @"信任评估失败");
-
- // 提取私钥
- status = SecIdentityCopyPrivateKey(myIdentity, &_privateKeyRef);
- NSAssert(status == errSecSuccess, @"私钥创建失败");
- CFRelease(items);
- }
- - (NSString *)RSAEncryptString:(NSString *)string {
- NSData *cipher = [self RSAEncryptData:[string dataUsingEncoding:NSUTF8StringEncoding]];
-
- return [cipher base64EncodedStringWithOptions:0];
- }
- - (NSData *)RSAEncryptStringData:(NSString *)string {
- NSData *cipher = [self RSAEncryptData:[string dataUsingEncoding:NSUTF8StringEncoding]];
-
- return cipher;
- }
- - (NSData *)RSAEncryptData:(NSData *)data {
- OSStatus sanityCheck = noErr;
- size_t cipherBufferSize = 0;
- size_t keyBufferSize = 0;
-
- NSAssert(data, @"明文数据为空");
- NSAssert(_publicKeyRef, @"公钥为空");
-
- NSData *cipher = nil;
- uint8_t *cipherBuffer = NULL;
-
- // 计算缓冲区大小
- cipherBufferSize = SecKeyGetBlockSize(_publicKeyRef);
- keyBufferSize = data.length;
- if (kTypeOfWrapPadding == kSecPaddingNone) {
- NSAssert(keyBufferSize <= cipherBufferSize, @"加密内容太大");
- } else {
- NSAssert(keyBufferSize <= (cipherBufferSize - 11), @"加密内容太大");
- }
-
- // 分配缓冲区
- cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
- memset((void *)cipherBuffer, 0x0, cipherBufferSize);
-
- //SecKeyCreateEncryptedData(_publicKeyRef, kSecKeyAlgorithmRSAEncryptionPKCS1, <#CFDataRef _Nonnull plaintext#>, <#CFErrorRef _Nullable * _Nullable error#>)
- // 使用公钥加密
- sanityCheck = SecKeyEncrypt(_publicKeyRef,
- kSecPaddingNone,
- (const uint8_t *)data.bytes,
- keyBufferSize,
- cipherBuffer,
- &cipherBufferSize
- );
-
- NSAssert(sanityCheck == noErr, @"加密错误,OSStatus == %d", sanityCheck);
- // 生成密文数据
- cipher = [NSData dataWithBytes:(const void *)cipherBuffer length:(NSUInteger)cipherBufferSize];
-
- if (cipherBuffer) free(cipherBuffer);
-
- return cipher;
- }
- - (NSString *)RSADecryptString:(NSString *)string {
- NSData *keyData = [self RSADecryptData:[[NSData alloc] initWithBase64EncodedString:string options:0]];
-
- return [[NSString alloc] initWithData:keyData encoding:NSUTF8StringEncoding];
- }
- - (NSData *)RSADecryptData:(NSData *)data {
- OSStatus sanityCheck = noErr;
- size_t cipherBufferSize = 0;
- size_t keyBufferSize = 0;
-
- NSData *key = nil;
- uint8_t *keyBuffer = NULL;
-
- SecKeyRef privateKey = _publicKeyRef;//_privateKeyRef;
- NSAssert(privateKey != NULL, @"私钥不存在");
-
- // 计算缓冲区大小
- cipherBufferSize = SecKeyGetBlockSize(privateKey);
- keyBufferSize = data.length;
-
- NSAssert(keyBufferSize <= cipherBufferSize, @"解密内容太大");
-
- // 分配缓冲区
- keyBuffer = malloc(keyBufferSize * sizeof(uint8_t));
- memset((void *)keyBuffer, 0x0, keyBufferSize);
-
- // 使用私钥解密
- sanityCheck = SecKeyDecrypt(privateKey,
- kSecPaddingNone,
- (const uint8_t *)data.bytes,
- cipherBufferSize,
- keyBuffer,
- &keyBufferSize
- );
-
- NSAssert1(sanityCheck == noErr, @"解密错误,OSStatus == %d", sanityCheck);
-
- // 生成明文数据
- key = [NSData dataWithBytes:(const void *)keyBuffer length:(NSUInteger)keyBufferSize];
-
- if (keyBuffer) free(keyBuffer);
-
- return key;
- }
- - (NSString *)sha256:(NSString *)string
- {
- const char *cstr = [string cStringUsingEncoding:NSUTF8StringEncoding];
- NSData *data = [NSData dataWithBytes:cstr length:string.length];
-
- uint8_t digest[CC_SHA256_DIGEST_LENGTH];
-
- CC_SHA256(data.bytes, data.length, digest);
-
- NSMutableString* output = [NSMutableString stringWithCapacity:CC_SHA256_DIGEST_LENGTH * 2];
-
- for(int i = 0; i < CC_SHA256_DIGEST_LENGTH; i++)
- [output appendFormat:@"%02x", digest[i]];
-
- return output;
- }
- @end
|