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加密解密》