RSA秘钥 .cem 证书加密代码

   1、使用.pem加密

注:iOS上没有直接处理RSA加密的API,网上说的大多数也是处理X.509的证书的方法来实现,不过X.509证书是带签名的,在这里我们利用ios兼容c程序的特点,利用openssl的api实现rsa的加密解密,代码如下:

.h文件

#import <Foundation/Foundation.h>  
#include <openssl/rsa.h>  
#include <openssl/pem.h>  
#include <openssl/err.h>  
   
typedef enum {  
    KeyTypePublic,  
    KeyTypePrivate  
}KeyType;  
   
typedef enum {  
    RSA_PADDING_TYPE_NONE       = RSA_NO_PADDING,  
    RSA_PADDING_TYPE_PKCS1      = RSA_PKCS1_PADDING,  
    RSA_PADDING_TYPE_SSLV23     = RSA_SSLV23_PADDING  
}RSA_PADDING_TYPE;  
   
@interface CRSA : NSObject{  
    RSA *_rsa;  
}  
+ (id)shareInstance;  
- (BOOL)importRSAKeyWithType:(KeyType)type;  
- (int)getBlockSizeWithRSA_PADDING_TYPE:(RSA_PADDING_TYPE)padding_type;  
- (NSString *) encryptByRsa:(NSString*)content withKeyType:(KeyType)keyType;  
- (NSString *) decryptByRsa:(NSString*)content withKeyType:(KeyType)keyType;  
@end  

 .m文件

#import "CRSA.h"  
   
#define BUFFSIZE  1024  
#import "Base64.h"  
   
#define PADDING RSA_PADDING_TYPE_PKCS1  
@implementation CRSA  
   
+ (id)shareInstance  
{  
    static CRSA *_crsa = nil;  
    static dispatch_once_t onceToken;  
    dispatch_once(&onceToken, ^{  
        _crsa = [[self alloc] init];  
    });  
    return _crsa;  
}  
- (BOOL)importRSAKeyWithType:(KeyType)type  
{  
    FILEFILE *file;  
    NSString *keyName = type == KeyTypePublic ? @"public_key" : @"private_key";  
    NSString *keyPath = [[NSBundle mainBundle] pathForResource:keyName ofType:@"pem"];  
       
    file = fopen([keyPath UTF8String], "rb");  
       
    if (NULL != file)  
    {  
        if (type == KeyTypePublic)  
        {  
            _rsa = PEM_read_RSA_PUBKEY(file, NULL, NULL, NULL);  
            assert(_rsa != NULL);  
        }  
        else  
        {  
            _rsa = PEM_read_RSAPrivateKey(file, NULL, NULL, NULL);  
            assert(_rsa != NULL);  
        }  
           
        fclose(file);  
           
        return (_rsa != NULL) ? YES : NO;  
    }  
       
    return NO;  
}  
   
- (NSString *) encryptByRsa:(NSString*)content withKeyType:(KeyType)keyType  
{  
    if (![self importRSAKeyWithType:keyType])  
         return nil;  
       
    int status;  
    int length  = [content length];  
    unsigned char input[length + 1];  
    bzero(input, length + 1);  
    int i = 0;  
    for (; i < length; i++)  
    {  
        input[i] = [content characterAtIndex:i];  
    }  
       
    NSInteger  flen = [self getBlockSizeWithRSA_PADDING_TYPE:PADDING];  
       
    charchar *encData = (char*)malloc(flen);  
    bzero(encData, flen);  
       
    switch (keyType) {  
        case KeyTypePublic:  
            status = RSA_public_encrypt(length, (unsigned char*)input, (unsigned char*)encData, _rsa, PADDING);  
            break;  
               
        default:  
            status = RSA_private_encrypt(length, (unsigned char*)input, (unsigned char*)encData, _rsa, PADDING);  
            break;  
    }  
       
    if (status)  
    {  
        NSData *returnData = [NSData dataWithBytes:encData length:status];  
        free(encData);  
        encData = NULL;  
           
        NSString *ret = [returnData base64EncodedString];  
        return ret;  
    }  
       
    free(encData);  
    encData = NULL;  
       
    return nil;  
}  
   
- (NSString *) decryptByRsa:(NSString*)content withKeyType:(KeyType)keyType  
{  
    if (![self importRSAKeyWithType:keyType])  
        return nil;  
       
    int status;  
   
    NSData *data = [content base64DecodedData];  
    int length = [data length];  
       
    NSInteger flen = [self getBlockSizeWithRSA_PADDING_TYPE:PADDING];  
    charchar *decData = (char*)malloc(flen);  
    bzero(decData, flen);  
       
    switch (keyType) {  
        case KeyTypePublic:  
            status = RSA_public_decrypt(length, (unsigned char*)[data bytes], (unsigned char*)decData, _rsa, PADDING);  
            break;  
               
        default:  
            status = RSA_private_decrypt(length, (unsigned char*)[data bytes], (unsigned char*)decData, _rsa, PADDING);  
            break;  
    }  
       
    if (status)  
    {  
        NSMutableString *decryptString = [[NSMutableString alloc] initWithBytes:decData length:strlen(decData) encoding:NSASCIIStringEncoding];  
        free(decData);  
        decData = NULL;  
           
        return decryptString;  
    }  
       
    free(decData);  
    decData = NULL;  
       
    return nil;  
}  
   
- (int)getBlockSizeWithRSA_PADDING_TYPE:(RSA_PADDING_TYPE)padding_type  
{  
    int len = RSA_size(_rsa);  
       
    if (padding_type == RSA_PADDING_TYPE_PKCS1 || padding_type == RSA_PADDING_TYPE_SSLV23) {  
        len -= 11;  
    }  
       
    return len;  
}  
@end  

 

 

 2、使用证书加密

  使用证书加密非常简单,可以在github上搜索Cryptor

#import "CryptorTools.h"
#import <CommonCrypto/CommonCrypto.h>

// 填充模式
#define kTypeOfWrapPadding		kSecPaddingPKCS1

@interface CryptorTools() {
    SecKeyRef _publicKeyRef;                             // 公钥引用
    SecKeyRef _privateKeyRef;                            // 私钥引用
}

@end

@implementation CryptorTools

 

#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 *)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);
    
    // 使用公钥加密
    sanityCheck = SecKeyEncrypt(_publicKeyRef,
                                kTypeOfWrapPadding,
                                (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 *data = [[NSData alloc] initWithBase64EncodedString:string options:0];
    NSData *tempData =  [data subdataWithRange:NSMakeRange(0, 100)];
    NSData *keyData = [self RSADecryptData:tempData];
    
    return [[NSString alloc] initWithData:keyData encoding:NSUTF8StringEncoding];
}

- (NSData *)RSADecryptData:(NSData *)data {
    OSStatus sanityCheck = noErr;
    size_t cipherBufferSize = 0;
    size_t keyBufferSize = 0;
    
    
//    NSMutableData
//    for (int i = 0; i <data.length; i +=128) {
//        
//    }
    NSData *key = nil;
    uint8_t *keyBuffer = NULL;
    
    SecKeyRef privateKey = _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,
                                kTypeOfWrapPadding,
                                (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;
}

 

很多朋友会纠结在怎样生成证书。我后续会更新

posted @ 2015-09-11 15:52  老皮硕  阅读(917)  评论(0编辑  收藏  举报