1. 生成私钥: openssl req -x509 -days 3650 -new -newkey rsa:2048 -keyout private_key.pem -out private_key.pem
2. 生成p12格式的文件: openssl pkcs12 -export -out private_pkcs.p12 -in private_key.pem
3. 生成自签名证书: openssl x509 -in private_key.pem -inform PEM -out public_key.der -outform DER
使用到的第三方库:https://github.com/nicklockwood/Base64
//原始字符串
NSString *value = @"测试iOS中RSA加密和解密";
//加密
NSString *encrypt= [value rsaEncrypt];
FLOG(@"encrypted string: %@",encrypt);
//解密
NSString *decrypt= [encrypt rsaDecrypt];
FLOG(@"decrypted string: %@",decrypt);
类文件:
//
// RSA.h
// MCFriends
//
// Created by marujun on 14-9-4.
// Copyright (c) 2014年 marujun. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Base64.h"
@interface RSA : NSObject
+ (NSString *)encryptWithString:(NSString *)content;
+ (NSString *)decryptWithString:(NSString *)content;
@end
@interface NSString (RSA)
- (NSString *)rsaEncrypt;
- (NSString *)rsaDecrypt;
@end
//
// RSA.m
// MCFriends
//
// Created by marujun on 14-9-4.
// Copyright (c) 2014年 marujun. All rights reserved.
//
#import "RSA.h"
@implementation RSA
static SecKeyRef _publicKey = nil;
+ (SecKeyRef)getPublicKey
{
// 从公钥证书文件中获取到公钥的SecKeyRef指针
if(_publicKey == nil){
NSData *certificateData = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"]];
SecCertificateRef myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)certificateData);
SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
SecTrustRef myTrust;
OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);
SecTrustResultType trustResult;
if (status == noErr) {
status = SecTrustEvaluate(myTrust, &trustResult);
}
_publicKey = SecTrustCopyPublicKey(myTrust);
CFRelease(myCertificate);
CFRelease(myPolicy);
CFRelease(myTrust);
}
return _publicKey;
}
+ (NSString *)encryptWithString:(NSString *)content
{
SecKeyRef key = [self getPublicKey];
// 分配内存块,用于存放加密后的数据段
size_t cipherBufferSize = SecKeyGetBlockSize(key);
uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
NSData *stringBytes = [content dataUsingEncoding:NSUTF8StringEncoding];
size_t blockSize = cipherBufferSize - 12;
size_t blockCount = (size_t)ceil([stringBytes length] / (double)blockSize);
NSMutableData *encryptedData = [NSMutableData data];
// 分段加密
for (int i = 0; i < blockCount; i++) {
NSUInteger loc = i * blockSize;
// 数据段的实际大小。最后一段可能比blockSize小。
int bufferSize = MIN(blockSize,[stringBytes length] - loc);
// 截取需要加密的数据段
NSData *buffer = [stringBytes subdataWithRange:NSMakeRange(loc, 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 {
if (cipherBuffer) {
free(cipherBuffer);
}
return nil;
}
}
if (cipherBuffer) {
free(cipherBuffer);
}
return [encryptedData base64EncodedString];
}
static SecKeyRef _privateKey = nil;
+ (SecKeyRef)getPrivateKey
{
// 从p12文件中获取到私钥的SecKeyRef指针
if(_privateKey == nil){
NSString *pkcsPassword = @"****"; //p12文件密码
NSData *p12Data = [NSData dataWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"private_pkcs" ofType:@"p12"]]; //p12文件路径
CFStringRef password = (__bridge CFStringRef)pkcsPassword;
const void *keys[] = { kSecImportExportPassphrase };
const void *values[] = { password };
CFDictionaryRef options = CFDictionaryCreate(kCFAllocatorDefault, keys, values, 1, NULL, NULL);
CFArrayRef items = CFArrayCreate(kCFAllocatorDefault, NULL, 0, NULL);
OSStatus status = SecPKCS12Import((__bridge CFDataRef)p12Data, options, &items);
if (status == errSecSuccess) {
CFDictionaryRef identity_trust_dic = CFArrayGetValueAtIndex(items, 0);
SecIdentityRef identity = (SecIdentityRef)CFDictionaryGetValue(identity_trust_dic, kSecImportItemIdentity);
SecTrustRef trust = (SecTrustRef)CFDictionaryGetValue(identity_trust_dic, kSecImportItemTrust);
// certs数组中包含了所有的证书
CFArrayRef certs = (CFArrayRef)CFDictionaryGetValue(identity_trust_dic, kSecImportItemCertChain);
if ([(__bridge NSArray *)certs count] && trust && identity) {
// 如果没有下面一句,自签名证书的评估信任结果永远是kSecTrustResultRecoverableTrustFailure
status = SecTrustSetAnchorCertificates(trust, certs);
if (status == noErr) {
SecTrustResultType trustResultType;
// 通常, 返回的trust result type应为kSecTrustResultUnspecified,如果是,就可以说明签名证书是可信的
status = SecTrustEvaluate(trust, &trustResultType);
if ((trustResultType == kSecTrustResultUnspecified || trustResultType == kSecTrustResultProceed) && status == errSecSuccess) {
// 证书可信,可以提取私钥与公钥,然后可以使用公私钥进行加解密操作
status = SecIdentityCopyPrivateKey(identity, &_privateKey);
if (status == noErr && _privateKey) {
// 成功提取私钥
}
}
}
}
}
if (options) {
CFRelease(options);
}
}
return _privateKey;
}
+ (NSString *)decryptWithString:(NSString *)content
{
SecKeyRef key = [self getPrivateKey];
// 分配内存块,用于存放解密后的数据段
size_t plainBufferSize = SecKeyGetBlockSize(key);
uint8_t *plainBuffer = malloc(plainBufferSize * sizeof(uint8_t));
NSData *cipherData = [content base64DecodedData];
// 计算数据段最大长度及数据段的个数
size_t blockSize = plainBufferSize;
size_t blockCount = (size_t)ceil([cipherData length] / blockSize);
NSMutableData *decryptedData = [NSMutableData data];
// 分段解密
for (int i = 0; i < blockCount; i++) {
NSUInteger loc = i * blockSize;
// 数据段的实际大小。最后一段可能比blockSize小。
int bufferRealSize = MIN(blockSize, [cipherData length] - loc);
// 截取需要解密的数据段
NSData *buffer = [cipherData subdataWithRange:NSMakeRange(loc, bufferRealSize)];
OSStatus status = SecKeyDecrypt(key, kSecPaddingPKCS1, (const uint8_t *)[buffer bytes], [buffer length], plainBuffer, &plainBufferSize);
if (status == noErr) {
NSData *decryptedBytes = [[NSData alloc] initWithBytes:(const void *)plainBuffer length:plainBufferSize];
[decryptedData appendData:decryptedBytes];
} else {
if (plainBuffer) {
free(plainBuffer);
}
return nil;
}
}
if (plainBuffer) {
free(plainBuffer);
}
return [[NSString alloc] initWithData:decryptedData encoding:NSUTF8StringEncoding];;
}
@end
@implementation NSString (RSA)
- (NSString *)rsaEncrypt
{
return [RSA encryptWithString:self];
}
- (NSString *)rsaDecrypt
{
return [RSA decryptWithString:self];
}
@end