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:@"\r" withString:@""];
136     key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
137     key = [key stringByReplacingOccurrencesOfString:@"\t" 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++] != '\0') 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:@"\r" withString:@""];
288     key = [key stringByReplacingOccurrencesOfString:@"\n" withString:@""];
289     key = [key stringByReplacingOccurrencesOfString:@"\t" 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加密解密》

posted @ 2021-04-23 13:43  WidgetBox  阅读(213)  评论(0编辑  收藏  举报