将NSData转换为SecKeyRef

我有一个公共密钥,我从远程服务器收集,我想用该公钥进行RSAencryption。 但问题是我得到公钥数据缓冲区中的字节数组。 我可以将其转换为NSData,但我不能转换为SecKeyRef,所以我可以继续encryption。 我的encryption代码是这样的:

+(NSString *)encryptRSA:(NSString *)plainTextString withKey:(SecKeyRef)publicKey { size_t cipherBufferSize = SecKeyGetBlockSize(publicKey); uint8_t *cipherBuffer = malloc(cipherBufferSize); uint8_t *nonce = (uint8_t *)[plainTextString UTF8String]; SecKeyEncrypt(publicKey, kSecPaddingOAEP, nonce, strlen( (char*)nonce ), &cipherBuffer[0], &cipherBufferSize); NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize]; return [encryptedData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength]; 

}

正如你所看到的,我需要SecKeyRef对象types来完成我的encryption。 但是我的RSA公钥在NSDatavariables中。 那么如何将NSData转换为SecKeyRef对象types。 提前致谢。

使用此function来保存您的公钥。 将您的RAS公钥和任何名称传递给peername。

 - (void)addPeerPublicKey:(NSString *)peerName keyBits:(NSData *)publicKeyData { OSStatus sanityCheck = noErr; CFTypeRef persistPeer = NULL; [self removePeerPublicKey:peerName]; NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]]; NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init]; [peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass]; [peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; [peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag]; [peerPublicKeyAttr setObject:publicKeyData forKey:(id)kSecValueData]; [peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData]; sanityCheck = SecItemAdd((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&persistPeer); if(sanityCheck == errSecDuplicateItem){ TRC_DBG(@"Problem adding the peer public key to the keychain, OSStatus == %ld.", sanityCheck ); } TRC_DBG(@"SecItemAdd OSStATUS = %ld", sanityCheck); // TRC_DBG(@"PersistPeer privatekey data after import into keychain %@", persistPeer); persistPeer = NULL; [peerPublicKeyAttr removeObjectForKey:(id)kSecValueData]; sanityCheck = SecItemCopyMatching((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef*)&persistPeer); TRC_DBG(@"SecItemCopying OSStATUS = %ld", sanityCheck); // TRC_DBG(@"SecItem copy matching returned this public key data %@", persistPeer); // The nice thing about persistent references is that you can write their value out to disk and // then use them later. I don't do that here but it certainly can make sense for other situations // where you don't want to have to keep building up dictionaries of attributes to get a reference. // // Also take a look at SecKeyWrapper's methods (CFTypeRef)getPersistentKeyRefWithKeyRef:(SecKeyRef)key // & (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef. [peerTag release]; [peerPublicKeyAttr release]; if (persistPeer) CFRelease(persistPeer); } 

这是检索公钥ref的函数。 通过相同的名称,其中一个用于保存。

 -(SecKeyRef)getPublicKeyReference:(NSString*)peerName{ OSStatus sanityCheck = noErr; SecKeyRef pubKeyRefData = NULL; NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]]; NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init]; [peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass]; [peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType]; [peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag]; [peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey: (id)kSecReturnRef]; sanityCheck = SecItemCopyMatching((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef*)&pubKeyRefData); [peerTag release]; [peerPublicKeyAttr release]; TRC_DBG(@"SecItemCopying OSStATUS = %ld", sanityCheck); if(pubKeyRefData){ TRC_DBG(@"SecItem copy matching returned this publickeyref %@", pubKeyRefData); return pubKeyRefData; }else{ TRC_DBG(@"pubKeyRef is NULL"); return nil; } } 

在addPeerPublicKey之前将你的公钥数据传递给这个函数

 - (NSData *)stripPublicKeyHeader:(NSData *)d_key { // Skip ASN.1 public key header if (d_key == nil) return(nil); unsigned int 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_RSA static 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 buffer return([NSData dataWithBytes:&c_key[idx] length:len - idx]); } 

希望它会工作….

 -(NSData*)convertIOSKeyToASNFormat:(NSData*)iosKey{ static const unsigned char _encodedRSAEncryptionOID[15] = { /* Sequence of length 0xd made up of OID followed by NULL */ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00 }; // OK - that gives us the "BITSTRING component of a full DER // encoded RSA public key - we now need to build the rest unsigned char builder[15]; NSMutableData * encKey = [[[NSMutableData alloc] init] autorelease]; int bitstringEncLength; // When we get to the bitstring - how will we encode it? if ([iosKey length ] + 1 < 128 ) bitstringEncLength = 1 ; else bitstringEncLength = (([iosKey length ] +1 ) / 256 ) + 2 ; // Overall we have a sequence of a certain length builder[0] = 0x30; // ASN.1 encoding representing a SEQUENCE // Build up overall size made up of - size_t i = sizeof(_encodedRSAEncryptionOID) + 2 + bitstringEncLength + [iosKey length]; size_t j = [self encodeLen:&builder[1] length:i]; [encKey appendBytes:builder length:j +1]; // First part of the sequence is the OID [encKey appendBytes:_encodedRSAEncryptionOID length:sizeof(_encodedRSAEncryptionOID)]; // Now add the bitstring builder[0] = 0x03; j = [self encodeLen:&builder[1] length:[iosKey length] + 1]; builder[j+1] = 0x00; [encKey appendBytes:builder length:j + 2]; // Now the actual key [encKey appendData:iosKey]; return encKey; }