通过ios实现RSA加密和解密
Posted AntonyGu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了通过ios实现RSA加密和解密相关的知识,希望对你有一定的参考价值。
在加密和解密中,我们需要了解的知识有什么事openssl;RSA加密算法的基本原理;如何通过openssl生成最后我们需要的der和p12文件。
废话不多说,直接写步骤:
第一步:openssl来生成公钥和私钥证书,最后需要得到公钥证书和私钥证书
。
这是在mac OX系统下显示的证书,如果我们用文本编辑器打开它,会发现里面是----BEGIN RSA 开头 并且----END RSA 结尾的一串字符串。
第二步:我们需要在代码中写我们的加密和机密方法,加密的字符串通过公钥进行加密,加密后的字符串也可以通过私钥进行解密。
1.在命令行下通过openssl指令获得证书
//生成长度为 1024 的私钥:private_key.pem (文件名可自定义) openssl genrsa -out private_key.pem 1024 //使用私钥文件创建所需的证书:rsaCertReq.csr(文件名可自定义) openssl req -new -key private_key.pem -out rsaCertReq.csr //使用 x509 创建证书:rsaCert.crt(文件名可自定义) openssl x509 -req -days 3650 -in rsaCertReq.csr -signkey private_key.pem -out rsaCert.crt //生成 .der 格式的公钥:public_key.der(文件名可自定义) openssl x509 -outform der -in rsaCert.crt -out public_key.der //生成解密所需 .p12文件:private_key.p12(文件名可自定义) openssl pkcs12 -export -out private_key.p12 -inkey private_key.pem -in rsaCert.crt
在命令行种可能需要你的一些信息去生成公钥和私钥
Country Name (2 letter code) [AU]:CN // 国家码
State or Province Name (full name) [Some-State]:china //地区码
Locality Name (eg, city) []:wuhan // 本地码
Organization Name (eg, company) [Internet Widgits Pty Ltd]:airway // 公司名称
Organizational Unit Name (eg, section) []:airway // 部门
Common Name (eg, YOUR name) []:airway // 名字
Email Address []: //邮箱
注意:在生成密钥对的时候需要填入 私钥的提取密码,请记住,解密的时候需要用到。
2.我们需要完善我们的代码来实现RSA加密和解密
通过在命令行中的操作,我们最后可以得到我们需要的公钥和私钥文件。
static SecKeyRef _public_key = nil; // 从公钥证书文件中获取到公钥的SecKeyRef指针: @"public_key" ofType:@"der" NSString *publicKeyPath = [paramsDict stringValueForKey:@"publicKey" defaultValue:@""]; publicKeyPath = [self getPathWithUZSchemeURL:publicKeyPath]; if (![[NSFileManager defaultManager] fileExistsAtPath:publicKeyPath]) { [self sendResultEventWithCallbackId:rsaCbId dataDict:@{@"status":[NSNumber numberWithBool:false]} errDict:@{@"code":@(-1)} doDelete:NO]; return; } NSData *certificateData = [[NSData alloc]initWithContentsOfFile:publicKeyPath]; SecCertificateRef myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (CFDataRef)certificateData); SecPolicyRef myPolicy = SecPolicyCreateBasicX509(); SecTrustRef myTrust; OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust); SecTrustResultType trustResult; if (status == noErr) { status = SecTrustEvaluate(myTrust, &trustResult); } _public_key = SecTrustCopyPublicKey(myTrust); CFRelease(myCertificate); CFRelease(myPolicy); CFRelease(myTrust); SecKeyRef key = _public_key; size_t cipherBufferSize = SecKeyGetBlockSize(key); uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t)); NSData *stringBytes = [inString dataUsingEncoding:NSUTF8StringEncoding]; size_t blockSize = cipherBufferSize - 11; size_t blockCount = (size_t)ceil([stringBytes length] / (double)blockSize); NSMutableData *encryptedData = [[NSMutableData alloc] init]; NSString *outString = [[NSString alloc] init]; for (int i=0; i<blockCount; i++) { int bufferSize = MIN(blockSize,[stringBytes length] - i * blockSize); NSData *buffer = [stringBytes subdataWithRange:NSMakeRange(i * blockSize, bufferSize)]; OSStatus status = SecKeyEncrypt(key, kSecPaddingPKCS1, (const uint8_t *)[buffer bytes], [buffer length], cipherBuffer, &cipherBufferSize); if (status == noErr){ NSData *encryptedBytes = [[NSData alloc] initWithBytes:(const void *)cipherBuffer length:cipherBufferSize]; [encryptedData appendData:encryptedBytes]; } else{ outString = @""; } } if (cipherBuffer) { free(cipherBuffer); } outString = [encryptedData base64Encoding]; } return outString;
NSString *password = [paramsDict stringValueForKey:@"password" defaultValue:@""]; NSString *inString = [paramsDict stringValueForKey:@"data" defaultValue:@""]; NSString *value = @""; if (inString.length <= 0) { //err:1 return value; } else { // 从私钥证书文件中获取到公钥的SecKeyRef指针: @"private_key" ofType:@"pem" NSString *privateKeyPath = [paramsDict stringValueForKey:@"privateKey" defaultValue:@""]; privateKeyPath = [self getPathWithUZSchemeURL:privateKeyPath]; if (![[NSFileManager defaultManager] fileExistsAtPath:privateKeyPath]) { return value; } NSData *p12Data = [[NSData alloc]initWithContentsOfFile:privateKeyPath]; SecKeyRef privateKeyRef = NULL; NSMutableDictionary *options = [[NSMutableDictionary alloc] init]; [options setObject:password forKey:(__bridge id)kSecImportExportPassphrase]; CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL); OSStatus securityError = SecPKCS12Import((__bridge CFDataRef) p12Data, (__bridge CFDictionaryRef)options, &items); if (securityError == noErr && CFArrayGetCount(items) > 0) { CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0); SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity); securityError = SecIdentityCopyPrivateKey(identityApp, &privateKeyRef); if (securityError != noErr) { privateKeyRef = NULL; } } else { return value; } CFRelease(items); NSData *cipherData = [NSData dataWithBase64EncodedString:inString]; // NSData* decryptData = [self rsaDecryptData: data]; size_t cipherLen = [cipherData length]; void *cipher = malloc(cipherLen); [cipherData getBytes:cipher length:cipherLen]; size_t plainLen = SecKeyGetBlockSize(privateKeyRef) - 12; void *plain = malloc(plainLen); OSStatus status = SecKeyDecrypt(privateKeyRef, kSecPaddingPKCS1, cipher, cipherLen, plain, &plainLen); if (status != noErr) { return value; } NSData *decryptedData = [[NSData alloc] initWithBytes:(const void *)plain length:plainLen]; value = [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding]; NSMutableString *outString = [[NSMutableString alloc] init]; //如果没有进行加密直接解密,outString 将为 nil if (!value && decryptedData && decryptedData.length > 0) { Byte *datas = (Byte*)[decryptedData bytes]; outString = [NSMutableString stringWithCapacity:decryptedData.length * 2]; for(int i = 0; i < decryptedData.length; i++){ [outString appendFormat:@"%02x", datas[i]]; } value = [outString copy]; } return value; }
以上是关于通过ios实现RSA加密和解密的主要内容,如果未能解决你的问题,请参考以下文章