+ (NSData *)stripPublicKeyHeader:(NSData *)d_key{// Skip ASN.1 public key headerif (d_key == nil) return(nil);unsigned long len = [d_key length];if (!len) return(nil);unsigned char *c_key = (unsigned char *)[d_key bytes];unsigned int idx = 0;if (c_key[idx++] != 0x30) return(nil);if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;else idx++;// PKCS #1 rsaEncryption szOID_RSA_RSAstatic unsigned char seqiod[] ={ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,0x01, 0x05, 0x00 };if (memcmp(&c_key[idx], seqiod, 15)) return(nil);idx += 15;if (c_key[idx++] != 0x03) return(nil);if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;else idx++;if (c_key[idx++] != '/0') return(nil);// Now make a new NSData from this bufferreturn([NSData dataWithBytes:&c_key[idx] length:len - idx]);}
+ (SecKeyRef)addPublicKey:(NSString *)key{NSRange spos = [key rangeOfString:@"-----BEGIN PUBLIC KEY-----"];NSRange epos = [key rangeOfString:@"-----END PUBLIC KEY-----"];if(spos.location != NSNotFound && epos.location != NSNotFound){NSUInteger s = spos.location + spos.length;NSUInteger e = epos.location;NSRange range = NSMakeRange(s, e-s);key = [key substringWithRange:range];}key = [key stringByReplacingOccurrencesOfString:@"/r" withString:@""];key = [key stringByReplacingOccurrencesOfString:@"/n" withString:@""];key = [key stringByReplacingOccurrencesOfString:@"/t" withString:@""];key = [key stringByReplacingOccurrencesOfString:@" " withString:@""];// This will be base64 encoded, decode it.NSData *data = base64_decode(key);data = [RSA stripPublicKeyHeader:data];if(!data){return nil;}NSString *tag = @"what_the_fuck_is_this";NSData *d_tag = [NSData dataWithBytes:[tag UTF8String] length:[tag length]];// Delete any old lingering key with the same tagNSMutableDictionary *publicKey = [[NSMutableDictionary alloc] init];[publicKey setObject:(__bridge id) kSecClassKey forKey:(__bridge id)kSecClass];[publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];[publicKey setObject:d_tag forKey:(__bridge id)kSecAttrapplicationTag];SecItemDelete((__bridge CFDictionaryRef)publicKey);// Add persistent version of the key to system keychain[publicKey setObject:data forKey:(__bridge id)kSecValueData];[publicKey setObject:(__bridge id) kSecAttrKeyClassPublic forKey:(__bridge id)kSecAttrKeyClass];[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnPersistentRef];CFTypeRef persistKey = nil;OSStatus status = SecItemAdd((__bridge CFDictionaryRef)publicKey, &persistKey);if (persistKey != nil){CFRelease(persistKey);}if ((status != noErr) && (status != errSecDuplicateItem)) {return nil;}[publicKey removeObjectForKey:(__bridge id)kSecValueData];[publicKey removeObjectForKey:(__bridge id)kSecReturnPersistentRef];[publicKey setObject:[NSNumber numberWithBool:YES] forKey:(__bridge id)kSecReturnRef];[publicKey setObject:(__bridge id) kSecAttrKeyTypeRSA forKey:(__bridge id)kSecAttrKeyType];// Now fetch the SecKeyRef version of the keySecKeyRef keyRef = nil;status = SecItemCopyMatching((__bridge CFDictionaryRef)publicKey, (CFTypeRef *)&keyRef);if(status != noErr){return nil;}return keyRef;}
1 + (NSString *)encryptData:(NSData *)data publicKey:(NSString *)pubKey{ 2 if(!data || !pubKey){ 3 return nil; 4 } 5 SecKeyRef keyRef = [RSA addPublicKey:pubKey]; 6 if(!keyRef){ 7 return nil; 8 } 9 10 const uint8_t *srcbuf = (const uint8_t *)[data bytes];11 size_t srclen = (size_t)data.length;12 13 size_t outlen = SecKeyGetBlockSize(keyRef) * sizeof(uint8_t);14 if(srclen > outlen - 11){15 CFRelease(keyRef);16 return nil;17 }18 void *outbuf = malloc(outlen);19 20 OSStatus status = noErr;21 status = SecKeyEncrypt(keyRef,22 kSecPaddingNone, //原作者写的是kSecPaddingPKCS1,经春哥研究这里写成kSecPaddingNone才符合我们使用23 srcbuf,24 srclen,25 outbuf,26 &outlen27 );28 NSString *ret = nil;29 if (status != 0) {30 //NSLog(@"SecKeyEncrypt fail. Error Code: %ld", status);31 }else{32 NSData *data = [NSData dataWithBytes:outbuf length:outlen];33 ret = base64_encode_data(data);34 }35 free(outbuf);36 CFRelease(keyRef);37 return ret;38 }
新闻热点
疑难解答