2014-10-17 74 views
4

iOS的钥匙串所以我知道我可以用我下面的代码保存RSA密钥到钥匙扣:贮藏RSA公钥到使用kSecAttrAccessible

+ (void)savePublicKeyToKeychain:(NSData *)key tag:(NSString *)tagString deleteExisting:(BOOL)deleteExisting { 
    NSData *tag = [SecKeyWrapper getKeyTag:tagString]; 

    NSDictionary *saveDict = @{ 
      (__bridge id) kSecClass : (__bridge id) kSecClassKey, 
      (__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeRSA, 
      (__bridge id) kSecAttrApplicationTag : tag, 
      (__bridge id) kSecAttrKeyClass : (__bridge id) kSecAttrKeyClassPublic, 
      (__bridge id) kSecValueData : key 
    }; 
    [self saveKeyToKeychain:saveDict tag:tagString deleteExisting:deleteExisting]; 
} 

+ (void)saveKeyToKeychain:(NSDictionary *)saveDict tag:(NSString *)tagString deleteExisting:(BOOL)deleteExisting { 
    OSStatus sanityCheck = SecItemAdd((__bridge CFDictionaryRef) saveDict, NULL); 
    if (sanityCheck != errSecSuccess) { 
     if (sanityCheck == errSecDuplicateItem && deleteExisting) { 
      // delete the duplicate and save again 
      SecItemDelete((__bridge CFDictionaryRef) saveDict); 
      sanityCheck = SecItemAdd((__bridge CFDictionaryRef) saveDict, NULL); 
     } 
     if (sanityCheck != errSecSuccess) { 
      NSLog(@"Problem saving the key to keychain, OSStatus == %d.", (int) sanityCheck); 
     } 
    } 
    // remove from cache 
    [keyCache removeObjectForKey:tagString]; 
} 

这我可以保存和检索正确。如果我尝试设置保存kSecAttrAccessible值:

+ (void)savePublicKeyToKeychain:(NSData *)key tag:(NSString *)tagString deleteExisting:(BOOL)deleteExisting { 
    NSData *tag = [SecKeyWrapper getKeyTag:tagString]; 

    NSDictionary *saveDict = @{ 
      (__bridge id) kSecClass : (__bridge id) kSecClassKey, 
      (__bridge id) kSecAttrKeyType : (__bridge id) kSecAttrKeyTypeRSA, 
      (__bridge id) kSecAttrApplicationTag : tag, 
      (__bridge id) kSecAttrKeyClass : (__bridge id) kSecAttrKeyClassPublic, 
      (__bridge id) kSecAttrAccessible: (__bridge id) kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly, 
      (__bridge id) kSecValueData : key 
    }; 
    [self saveKeyToKeychain:saveDict tag:tagString deleteExisting:deleteExisting]; 
} 

,然后试图检索,我收到垃圾。这是垃圾,因为当我保存后立即检索它,插入的值和检索的值是不同的。

任何人都有代码示例或知道如何设置密钥链项目的可访问性,特别是对于RSA密钥?

+0

我有类似的问题。原来,我错过了kSecAttrKeyClassPublic属性,即使在其他调用中(例如获取关键引用),只是应用程序标记就足够了。但对于SecItemAdd,每个属性都很重要。 – Alexey 2015-10-14 12:04:54

回答

3

为公众所知,事实证明,用于存储数据到钥匙链需要的属性是EXACTLY什么是用来从钥匙串中的数据。如果您缺少其中一个属性,即使它看起来只是用于存储的属性(如kSecAttrAccessible),您也会得到错误的数据。你甚至不会得到errSecItemNotFound。它返回垃圾。

+0

这是有道理的,你得到的垃圾可能是数据解密不正确,因为它得到不正确的可访问属性。 – Joe 2014-10-17 18:52:32

+0

@Joe:实际上,关键是垃圾,而不是数据。如果没有任何一个属性匹配,则该方法应该返回'errSecItemNotFound',而不是假装用一个不好的密钥成功。这里没有什么涉及数据,只是存储和检索密钥。对我而言,一个关键字应该添加所有属性集。然后应该使用匹配的任何属性(如搜索)来检索,而不是要求插入时使用的所有属性。目前的行为鼓励开发人员使用尽可能少的属性来存储密钥,以便检索更容易。 – mikeho 2014-10-19 21:47:24