zoukankan      html  css  js  c++  java
  • iOS RSA加密解密

    最近项目中用到了rsa加密解密,在此记录一下。

    1.使用公钥、私钥串来加密解密

    2.使用公钥der文件与私钥的p12文件来加密解密(使用p12文件解密时需要生成私钥文件时的密码)

    3.下面就附上网上找的大神代码

    .h文件

     1 @interface RSA : NSObject
     2 
     3 //使用'.der'公钥文件加密
     4 + (NSString *)encryptString:(NSString *)str publicKeyWithContentsOfFile:(NSString *)path;
     5 
     6 //使用'.12'私钥文件解密
     7 + (NSString *)decryptString:(NSString *)str privateKeyWithContentsOfFile:(NSString *)path password:(NSString *)password;
     8 
     9 
    10 //使用公钥字符串加密
    11 + (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey;
    12 
    13 //使用私钥字符串解密
    14 + (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey;
    15 
    16 @end
    查看完整代码

    .m文件

      1 #import "RSA.h"
      2 #import <Security/Security.h>
      3 
      4 @implementation RSA
      5 
      6 static NSString *base64_encode_data(NSData *data){
      7     data = [data base64EncodedDataWithOptions:0];
      8     NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
      9     return ret;
     10 }
     11  
     12 static NSData *base64_decode(NSString *str){
     13     NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
     14     return data;
     15 }
     16  
     17 #pragma mark - 使用'.der'公钥文件加密
     18 //加密
     19 + (NSString *)encryptString:(NSString *)str publicKeyWithContentsOfFile:(NSString *)path{
     20     if (!str || !path)  return nil;
     21     return [self encryptString:str publicKeyRef:[self getPublicKeyRefWithContentsOfFile:path]];
     22 }
     23  
     24 //获取公钥
     25 + (SecKeyRef)getPublicKeyRefWithContentsOfFile:(NSString *)filePath{
     26     NSData *certData = [NSData dataWithContentsOfFile:filePath];
     27     if (!certData) {
     28         return nil;
     29     }
     30     SecCertificateRef cert = SecCertificateCreateWithData(NULL, (CFDataRef)certData);
     31     SecKeyRef key = NULL;
     32     SecTrustRef trust = NULL;
     33     SecPolicyRef policy = NULL;
     34     if (cert != NULL) {
     35         policy = SecPolicyCreateBasicX509();
     36         if (policy) {
     37             if (SecTrustCreateWithCertificates((CFTypeRef)cert, policy, &trust) == noErr) {
     38                 SecTrustResultType result;
     39                 if (SecTrustEvaluate(trust, &result) == noErr) {
     40                     key = SecTrustCopyPublicKey(trust);
     41                 }
     42             }
     43         }
     44     }
     45     if (policy) CFRelease(policy);
     46     if (trust) CFRelease(trust);
     47     if (cert) CFRelease(cert);
     48     return key;
     49 }
     50  
     51 + (NSString *)encryptString:(NSString *)str publicKeyRef:(SecKeyRef)publicKeyRef{
     52     if(![str dataUsingEncoding:NSUTF8StringEncoding]){
     53         return nil;
     54     }
     55     if(!publicKeyRef){
     56         return nil;
     57     }
     58     NSData *data = [self encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] withKeyRef:publicKeyRef];
     59     NSString *ret = base64_encode_data(data);
     60     return ret;
     61 }
     62  
     63 #pragma mark - 使用'.12'私钥文件解密
     64 //解密
     65 + (NSString *)decryptString:(NSString *)str privateKeyWithContentsOfFile:(NSString *)path password:(NSString *)password{
     66     if (!str || !path) return nil;
     67     if (!password) password = @"";
     68     return [self decryptString:str privateKeyRef:[self getPrivateKeyRefWithContentsOfFile:path password:password]];
     69 }
     70  
     71 //获取私钥
     72 + (SecKeyRef)getPrivateKeyRefWithContentsOfFile:(NSString *)filePath password:(NSString*)password{
     73      
     74     NSData *p12Data = [NSData dataWithContentsOfFile:filePath];
     75     if (!p12Data) {
     76         return nil;
     77     }
     78     SecKeyRef privateKeyRef = NULL;
     79     NSMutableDictionary * options = [[NSMutableDictionary alloc] init];
     80     [options setObject: password forKey:(__bridge id)kSecImportExportPassphrase];
     81     CFArrayRef items = CFArrayCreate(NULL, 0, 0, NULL);
     82     OSStatus securityError = SecPKCS12Import((__bridge CFDataRef) p12Data, (__bridge CFDictionaryRef)options, &items);
     83     if (securityError == noErr && CFArrayGetCount(items) > 0) {
     84         CFDictionaryRef identityDict = CFArrayGetValueAtIndex(items, 0);
     85         SecIdentityRef identityApp = (SecIdentityRef)CFDictionaryGetValue(identityDict, kSecImportItemIdentity);
     86         securityError = SecIdentityCopyPrivateKey(identityApp, &privateKeyRef);
     87         if (securityError != noErr) {
     88             privateKeyRef = NULL;
     89         }
     90     }
     91     CFRelease(items);
     92     return privateKeyRef;
     93 }
     94  
     95 + (NSString *)decryptString:(NSString *)str privateKeyRef:(SecKeyRef)privKeyRef{
     96     NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
     97     if (!privKeyRef) {
     98         return nil;
     99     }
    100     data = [self decryptData:data withKeyRef:privKeyRef];
    101     NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    102     return ret;
    103 }
    104  
    105 #pragma mark - 使用公钥字符串加密
    106 /* START: Encryption with RSA public key */
    107  
    108 //使用公钥字符串加密
    109 + (NSString *)encryptString:(NSString *)str publicKey:(NSString *)pubKey{
    110     NSData *data = [self encryptData:[str dataUsingEncoding:NSUTF8StringEncoding] publicKey:pubKey];
    111     NSString *ret = base64_encode_data(data);
    112     return ret;
    113 }
    114  
    115 + (NSData *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{
    116     if(!data || !pubKey){
    117         return nil;
    118     }
    119     SecKeyRef keyRef = [self addPublicKey:pubKey];
    120     if(!keyRef){
    121         return nil;
    122     }
    123     return [self encryptData:data withKeyRef:keyRef];
    124 }
    125  
    126 + (SecKeyRef)addPublicKey:(NSString *)key{
    127     NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];
    128     NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];
    129     if(spos.location != NSNotFound && epos.location != NSNotFound){
    130         NSUInteger s = spos.location + spos.length;
    131         NSUInteger e = epos.location;
    132         NSRange range = NSMakeRange(s, e-s);
    133         key = [key substringWithRange:range];
    134     }
    135     key = [key stringByReplacingOccurrencesOfString:@"
    " withString:@""];
    136     key = [key stringByReplacingOccurrencesOfString:@"
    " withString:@""];
    137     key = [key stringByReplacingOccurrencesOfString:@"	" withString:@""];
    138     key = [key stringByReplacingOccurrencesOfString:@" "  withString:@""];
    139      
    140     // This will be base64 encoded, decode it.
    141     NSData *data = base64_decode(key);
    142     data = [self stripPublicKeyHeader:data];
    143     if(!data){
    144         return nil;
    145     }
    146      
    147     //a tag to read/write keychain storage
    148     NSString *tag = @"RSAUtil_PubKey";
    149     NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
    150      
    151     // Delete any old lingering key with the same tag
    152     NSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];
    153     [publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
    154     [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    155     [publicKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
    156     SecItemDelete((__bridge CFDictionaryRef)publicKey);
    157      
    158     // Add persistent version of the key to system keychain
    159     [publicKey setObject:data forKey:(__bridge id)kSecValueData];
    160     [publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)
    161      kSecAttrKeyClass];
    162     [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
    163      kSecReturnPersistentRef];
    164      
    165     CFTypeRef persistKey = nil;
    166     OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);
    167     if (persistKey != nil){
    168         CFRelease(persistKey);
    169     }
    170     if ((status != noErr) && (status != errSecDuplicateItem)) {
    171         return nil;
    172     }
    173      
    174     [publicKey removeObjectForKey:(__bridge id)kSecValueData];
    175     [publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
    176     [publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
    177     [publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    178      
    179     // Now fetch the SecKeyRef version of the key
    180     SecKeyRef keyRef = nil;
    181     status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);
    182     if(status != noErr){
    183         return nil;
    184     }
    185     return keyRef;
    186 }
    187  
    188 + (NSData *)stripPublicKeyHeader:(NSData *)d_key{
    189     // Skip ASN.1 public key header
    190     if (d_key == nil) return(nil);
    191      
    192     unsigned long len = [d_key length];
    193     if (!len) return(nil);
    194      
    195     unsigned char *c_key = (unsigned char *)[d_key bytes];
    196     unsigned int  idx     = 0;
    197      
    198     if (c_key[idx++] != 0x30) return(nil);
    199      
    200     if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
    201     else idx++;
    202      
    203     // PKCS #1 rsaEncryption szOID_RSA_RSA
    204     static unsigned char seqiod[] =
    205     { 0x30,   0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
    206         0x01, 0x05, 0x00 };
    207     if (memcmp(&c_key[idx], seqiod, 15)) return(nil);
    208     idx += 15;
    209     if (c_key[idx++] != 0x03) return(nil);
    210     if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
    211     else idx++;
    212     if (c_key[idx++] != '') return(nil);
    213     // Now make a new NSData from this buffer
    214     return ([NSData dataWithBytes:&c_key[idx] length:len - idx]);
    215 }
    216  
    217 + (NSData *)encryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
    218     const uint8_t *srcbuf = (const uint8_t *)[data bytes];
    219     size_t srclen = (size_t)data.length;
    220      
    221     size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
    222     void *outbuf = malloc(block_size);
    223     size_t src_block_size = block_size - 11;
    224      
    225     NSMutableData *ret = [[NSMutableData alloc] init];
    226     for(int idx=0; idx<srclen; idx+=src_block_size){
    227         //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
    228         size_t data_len = srclen - idx;
    229         if(data_len > src_block_size){
    230             data_len = src_block_size;
    231         }
    232         size_t outlen = block_size;
    233         OSStatus status = noErr;
    234         status = SecKeyEncrypt(keyRef,
    235                                kSecPaddingPKCS1,
    236                                srcbuf + idx,
    237                                data_len,
    238                                outbuf,
    239                                &outlen
    240                                );
    241         if (status != 0) {
    242             NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
    243             ret = nil;
    244             break;
    245         }else{
    246             [ret appendBytes:outbuf length:outlen];
    247         }
    248     }
    249     free(outbuf);
    250     CFRelease(keyRef);
    251     return ret;
    252 }
    253  
    254 
    255 #pragma mark - 使用私钥字符串解密
    256 
    257  
    258 //使用私钥字符串解密
    259 + (NSString *)decryptString:(NSString *)str privateKey:(NSString *)privKey{
    260     if (!str) return nil;
    261     NSData *data = [[NSData alloc] initWithBase64EncodedString:str options:NSDataBase64DecodingIgnoreUnknownCharacters];
    262     data = [self decryptData:data privateKey:privKey];
    263     NSString *ret = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
    264     return ret;
    265 }
    266  
    267 + (NSData *)decryptData:(NSData *)data privateKey:(NSString *)privKey{
    268     if(!data || !privKey){
    269         return nil;
    270     }
    271     SecKeyRef keyRef = [self addPrivateKey:privKey];
    272     if(!keyRef){
    273         return nil;
    274     }
    275     return [self decryptData:data withKeyRef:keyRef];
    276 }
    277  
    278 + (SecKeyRef)addPrivateKey:(NSString *)key{
    279     NSRange spos = [key rangeOfString:@"-----BEGIN RSA PRIVATE KEY-----"];
    280     NSRange epos = [key rangeOfString:@"-----END RSA PRIVATE KEY-----"];
    281     if(spos.location != NSNotFound && epos.location != NSNotFound){
    282         NSUInteger s = spos.location + spos.length;
    283         NSUInteger e = epos.location;
    284         NSRange range = NSMakeRange(s, e-s);
    285         key = [key substringWithRange:range];
    286     }
    287     key = [key stringByReplacingOccurrencesOfString:@"
    " withString:@""];
    288     key = [key stringByReplacingOccurrencesOfString:@"
    " withString:@""];
    289     key = [key stringByReplacingOccurrencesOfString:@"	" withString:@""];
    290     key = [key stringByReplacingOccurrencesOfString:@" "  withString:@""];
    291      
    292     // This will be base64 encoded, decode it.
    293     NSData *data = base64_decode(key);
    294     data = [self stripPrivateKeyHeader:data];
    295     if(!data){
    296         return nil;
    297     }
    298      
    299     //a tag to read/write keychain storage
    300     NSString *tag = @"RSAUtil_PrivKey";
    301     NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];
    302      
    303     // Delete any old lingering key with the same tag
    304     NSMutableDictionary *privateKey = [[NSMutableDictionary alloc] init];
    305     [privateKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];
    306     [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    307     [privateKey setObject:d_tag forKey:(__bridge id)kSecAttrApplicationTag];
    308     SecItemDelete((__bridge CFDictionaryRef)privateKey);
    309      
    310     // Add persistent version of the key to system keychain
    311     [privateKey setObject:data forKey:(__bridge id)kSecValueData];
    312     [privateKey setObject:(__bridge id) kSecAttrKeyClassPrivate forKey:(__bridge id)
    313      kSecAttrKeyClass];
    314     [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)
    315      kSecReturnPersistentRef];
    316      
    317     CFTypeRef persistKey = nil;
    318     OSStatus status = SecItemAdd((__bridge CFDictionaryRef)privateKey, &persistKey);
    319     if (persistKey != nil){
    320         CFRelease(persistKey);
    321     }
    322     if ((status != noErr) && (status != errSecDuplicateItem)) {
    323         return nil;
    324     }
    325     [privateKey removeObjectForKey:(__bridge id)kSecValueData];
    326     [privateKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];
    327     [privateKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];
    328     [privateKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];
    329      
    330     // Now fetch the SecKeyRef version of the key
    331     SecKeyRef keyRef = nil;
    332     status = SecItemCopyMatching((__bridge CFDictionaryRef)privateKey, (CFTypeRef *)&keyRef);
    333     if(status != noErr){
    334         return nil;
    335     }
    336     return keyRef;
    337 }
    338  
    339 + (NSData *)stripPrivateKeyHeader:(NSData *)d_key{
    340     // Skip ASN.1 private key header
    341     if (d_key == nil) return(nil);
    342      
    343     unsigned long len = [d_key length];
    344     if (!len) return(nil);
    345      
    346     unsigned char *c_key = (unsigned char *)[d_key bytes];
    347     unsigned int  idx     = 22; //magic byte at offset 22
    348      
    349     if (0x04 != c_key[idx++]) return nil;
    350      
    351     //calculate length of the key
    352     unsigned int c_len = c_key[idx++];
    353     int det = c_len & 0x80;
    354     if (!det) {
    355         c_len = c_len & 0x7f;
    356     } else {
    357         int byteCount = c_len & 0x7f;
    358         if (byteCount + idx > len) {
    359             //rsa length field longer than buffer
    360             return nil;
    361         }
    362         unsigned int accum = 0;
    363         unsigned char *ptr = &c_key[idx];
    364         idx += byteCount;
    365         while (byteCount) {
    366             accum = (accum << 8) + *ptr;
    367             ptr++;
    368             byteCount--;
    369         }
    370         c_len = accum;
    371     }
    372     // Now make a new NSData from this buffer
    373     return [d_key subdataWithRange:NSMakeRange(idx, c_len)];
    374 }
    375  
    376 + (NSData *)decryptData:(NSData *)data withKeyRef:(SecKeyRef) keyRef{
    377     const uint8_t *srcbuf = (const uint8_t *)[data bytes];
    378     size_t srclen = (size_t)data.length;
    379      
    380     size_t block_size = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);
    381     UInt8 *outbuf = malloc(block_size);
    382     size_t src_block_size = block_size;
    383      
    384     NSMutableData *ret = [[NSMutableData alloc] init];
    385     for(int idx=0; idx<srclen; idx+=src_block_size){
    386         //NSLog(@"%d/%d block_size: %d", idx, (int)srclen, (int)block_size);
    387         size_t data_len = srclen - idx;
    388         if(data_len > src_block_size){
    389             data_len = src_block_size;
    390         }
    391          
    392         size_t outlen = block_size;
    393         OSStatus status = noErr;
    394         status = SecKeyDecrypt(keyRef,
    395                                kSecPaddingNone,
    396                                srcbuf + idx,
    397                                data_len,
    398                                outbuf,
    399                                &outlen
    400                                );
    401         if (status != 0) {
    402             NSLog(@"SecKeyEncrypt fail. Error Code: %d", status);
    403             ret = nil;
    404             break;
    405         }else{
    406             //the actual decrypted data is in the middle, locate it!
    407             int idxFirstZero = -1;
    408             int idxNextZero = (int)outlen;
    409             for ( int i = 0; i < outlen; i++ ) {
    410                 if ( outbuf[i] == 0 ) {
    411                     if ( idxFirstZero < 0 ) {
    412                         idxFirstZero = i;
    413                     } else {
    414                         idxNextZero = i;
    415                         break;
    416                     }
    417                 }
    418             }
    419              
    420             [ret appendBytes:&outbuf[idxFirstZero+1] length:idxNextZero-idxFirstZero-1];
    421         }
    422     }
    423     free(outbuf);
    424     CFRelease(keyRef);
    425     return ret;
    426 }
    427 
    428 @end
    查看完整代码

     4.生成公钥、私钥方法请参考这篇文章 《PHP、Android、iOS接口RSA加密解密》

  • 相关阅读:
    LeetCode 79. 单词搜索
    LeetCode 1143. 最长公共子序列
    LeetCode 55. 跳跃游戏
    LeetCode 48. 旋转图像
    LeetCode 93. 复原 IP 地址
    LeetCode 456. 132模式
    LeetCode 341. 扁平化嵌套列表迭代器
    LeetCode 73. 矩阵置零
    LeetCode 47. 全排列 II
    LeetCode 46. 全排列
  • 原文地址:https://www.cnblogs.com/widgetbox/p/14693428.html
Copyright © 2011-2022 走看看