服务端配发公钥给客户端,客户端把加密的数据传回服务端,服务端用私钥解密
工具类:
DTRSAEncryptor.h
用传入的公钥加密
#import <Foundation/Foundation.h>
@interface DTRSAEncryptor : NSObject
+ (void)setSharedInstance:(DTRSAEncryptor *)instance;
+ (DTRSAEncryptor *)sharedInstance;
- (void)loadPublicKeyFromFile:(NSString *)derFilePath;
- (void)loadPublicKeyFromData:(NSData *)derData;
- (void)loadPrivateKeyFromFile:(NSString *)p12FilePath password:(NSString *)p12Password;
- (void)loadPrivateKeyFromData:(NSData *)p12Data password:(NSString *)p12Password;
- (NSString *)rsaEncryptString:(NSString *)string;
- (NSData *)rsaEncryptData:(NSData *)data;
- (NSString *)rsaDecryptString:(NSString *)string;
- (NSData *)rsaDecryptData:(NSData *)data;
@end
DTRSAEncryptor.m
#import "DTRSAEncryptor.h"
#import "NSData+Base64.h"
@implementation DTRSAEncryptor
{
SecKeyRef publicKey;
SecKeyRef privateKey;
}
static DTRSAEncryptor *sharedInstance = nil;
+ (void)setSharedInstance:(DTRSAEncryptor *)instance {
sharedInstance = instance;
}
+ (DTRSAEncryptor *)sharedInstance {
return sharedInstance;
}
- (SecKeyRef)getPublicKey {
return publicKey;
}
- (SecKeyRef)getPrivateKey {
return privateKey;
}
- (void)loadPublicKeyFromFile:(NSString *)derFilePath {
NSData *derData = [[NSData alloc] initWithContentsOfFile:derFilePath];
[self loadPublicKeyFromData:derData];
}
- (void)loadPublicKeyFromData:(NSData *)derData {
publicKey = [self getPublicKeyRefrenceFromeData:derData];
}
- (void)loadPrivateKeyFromFile:(NSString *)p12FilePath password:(NSString *)p12Password {
NSData *p12Data = [NSData dataWithContentsOfFile:p12FilePath];
[self loadPrivateKeyFromData: p12Data password:p12Password];
}
- (void)loadPrivateKeyFromData:(NSData *) p12Data password:(NSString *)p12Password {
privateKey = [self getPrivateKeyRefrenceFromData:p12Data password:p12Password];
}
#pragma mark - Private Methods
- (SecKeyRef)getPublicKeyRefrenceFromeData:(NSData *)derData {
SecCertificateRef myCertificate = SecCertificateCreateWithData(kCFAllocatorDefault, (__bridge CFDataRef)derData);
SecPolicyRef myPolicy = SecPolicyCreateBasicX509();
SecTrustRef myTrust;
OSStatus status = SecTrustCreateWithCertificates(myCertificate,myPolicy,&myTrust);
SecTrustResultType trustResult;
if (status == noErr) {
status = SecTrustEvaluate(myTrust, &trustResult);
}
SecKeyRef securityKey = SecTrustCopyPublicKey(myTrust);
CFRelease(myCertificate);
CFRelease(myPolicy);
CFRelease(myTrust);
return securityKey;
}
- (SecKeyRef)getPrivateKeyRefrenceFromData:(NSData *)p12Data password:(NSString *)password {
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;
}
}
CFRelease(items);
return privateKeyRef;
}
#pragma mark - Encrypt
- (NSString *)rsaEncryptString:(NSString *)string {
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedData = [self rsaEncryptData:data];
NSString *base64EncryptedString = [encryptedData base64EncodeDataToNSString];
return base64EncryptedString;
}
//加密的大小受限于SecKeyEncrypt函数,SecKeyEncrypt要求明文和密钥的长度一致,如果要加密更长的内容,需要把内容按密钥长度分成多份,然后多次调用SecKeyEncrypt来实现
- (NSData *)rsaEncryptData:(NSData *)data {
SecKeyRef key = [self getPublicKey];
size_t cipherBufferSize = SecKeyGetBlockSize(key);
uint8_t *cipherBuffer = malloc(cipherBufferSize * sizeof(uint8_t));
size_t blockSize = cipherBufferSize - 11; // 分段加密
size_t blockCount = (size_t)ceil([data length] / (double)blockSize);
NSMutableData *encryptedData = [[NSMutableData alloc] init] ;
for (int i=0; i<blockCount; i++) {
int bufferSize = (int)(MIN(blockSize,[data length] - i * blockSize));
NSData *buffer = [data 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 {
if (cipherBuffer) {
free(cipherBuffer);
}
return nil;
}
}
if (cipherBuffer) {
free(cipherBuffer);
}
return encryptedData;
}
#pragma mark - Decrypt
- (NSString *)rsaDecryptString:(NSString *)string {
NSData *data = [NSData dataWithBase64EncodedNSString:string];
NSData *decryptData = [self rsaDecryptData:data];
NSString *result = [[NSString alloc] initWithData:decryptData encoding:NSUTF8StringEncoding];
return result;
}
- (NSData *)rsaDecryptData:(NSData *)data {
SecKeyRef key = [self getPrivateKey];
size_t cipherLen = [data length];
void *cipher = malloc(cipherLen);
[data getBytes:cipher length:cipherLen];
size_t plainLen = SecKeyGetBlockSize(key) - 12;
void *plain = malloc(plainLen);
OSStatus status = SecKeyDecrypt(key, kSecPaddingPKCS1, cipher, cipherLen, plain, &plainLen);
if (status != noErr) {
return nil;
}
NSData *decryptedData = [[NSData alloc] initWithBytes:(const void *)plain length:plainLen];
return decryptedData;
}
- (void)dealloc {
CFRelease(publicKey);
CFRelease(privateKey);
}
@end
DTRSATool.h
这个类用来把公钥传给DTRSAEncryptor类
#import <Foundation/Foundation.h>
@interface DTRSATool : NSObject
//加密数据
- (NSString *)encryData:(NSString *)str;
@end
DTRSATool.m
#import "DTRSATool.h"
#import "DTRSAEncryptor.h"
@implementation DTRSATool
//加密数据
- (NSString *)encryData:(NSString *)str {
DTRSAEncryptor *rsaEncryptor = [[DTRSAEncryptor alloc] init];
NSString *publicKeyPath = [[NSBundle mainBundle] pathForResource:@"public_key" ofType:@"der"];
[rsaEncryptor loadPublicKeyFromFile:publicKeyPath];
NSString *returnBASE64STRING = [rsaEncryptor rsaEncryptString:str];
NSLog(@"加密后的: %@", returnBASE64STRING);//加密
NSString *privateKeyPath = [[NSBundle mainBundle] pathForResource:@"private_key" ofType:@"p12"];
[rsaEncryptor loadPrivateKeyFromFile:privateKeyPath password:@"123456"];
NSString *decryptString = [rsaEncryptor rsaDecryptString:returnBASE64STRING];//解密
NSLog(@"解密后的: %@", decryptString);
return returnBASE64STRING;
}
@end
使用方法:
NSDictionary *dic = @{@"firstparam": @"第一个参数", @"secondparam": @"第二个参数"};
DTRSATool *rsaTool = [[DTRSATool alloc] init];
NSError *error = nil;
NSData *paramsData = [NSJSONSerialization dataWithJSONObject:dic options:kNilOptions error:&error];
NSString *paramsJsonString = [[NSString alloc] initWithData:paramsData encoding:NSUTF8StringEncoding];
NSString *encryParamsStr = [rsaTool encryData:paramsJsonString];
encryParamsStr就是加密好的字符串了
网友评论