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;
}

 

很多朋友會糾結在怎樣生成證書。我后續會更新


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com