Use this function to save your public key. Pass your RAS public key and any name for 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);
}
This is the function to retrieve the public key ref. Pass the same name which one is used for save.
-(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;
}
}
Pass your public key data to this function before 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++] != '') return(nil);
// Now make a new NSData from this buffer
return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
}
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…