IOS中RSA的加密解密

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



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值