Apple keychain store client identity so only my application could access it

后端 未结 2 2015
独厮守ぢ
独厮守ぢ 2021-01-27 09:16

Aim

I need to store client identity on OS X application in secure way in such way that only my application could access it. No prompting asking for permissions.

2条回答
  •  醉梦人生
    2021-01-27 10:14

    I've found nice solution. The trick is to create custom key-chain and than store client identity in that key chain.

    So basically there are tree steps.

    1. First create or open custom key-chain:

      NSString *keychainpath  = self.customKeychainPath;
      unsigned char password[SHA_DIGEST_LENGTH];
      GenerateCustomKeychainPassword(password);
      OSStatus status = SecKeychainCreate(keychainpath.UTF8String,
                                          SHA_DIGEST_LENGTH,
                                          password,
                                          NO,
                                          NULL,
                                          &customKeychain);
      
      if (status == errSecDuplicateKeychain)
      {
          status = SecKeychainOpen(keychainpath.UTF8String, &customKeychain);
          if (status == errSecSuccess)
          {
              status = SecKeychainUnlock(customKeychain,
                                         SHA_DIGEST_LENGTH,
                                         password,
                                         TRUE);
      
              if (status != errSecSuccess)
              {
                  NSLog(@"%s Failed to unlock custom keychain: %@",
                             __PRETTY_FUNCTION__, NSErrorFromStatusErrorCode(status));
              }
          }
      }
      else if (status != errSecSuccess)
      {
          NSLog(@"%s Failed to unlock custom keychain: %@",
                     __PRETTY_FUNCTION__, NSErrorFromStatusErrorCode(status));
      }
      
    2. Than add client identity to that key-chain

      OSStatus status = errSecSuccess;
      
      CFTypeRef  persistent_ref = NULL;
      NSDictionary *dict = @{
                             (id)kSecValueRef:(id)secItem,
                             (id)kSecReturnPersistentRef:(id)kCFBooleanTrue,
      #if !TARGET_OS_IPHONE
                             (id)kSecUseKeychain:(__bridge id)customKeychain,
      #endif
                             };
      status = SecItemAdd((CFDictionaryRef)dict, &persistent_ref);
      NSCAssert(status != errSecParam, @"Wrong contents of dictionary");
      if (status == errSecDuplicateItem)
      {
          NSLog(@"%s Item: %@ already exists", __PRETTY_FUNCTION__, secItem);
          return NULL;
      }
      return (CFDataRef)persistent_ref;
      
    3. And to read item from a keychain (persistent_ref can be stored in user defaults)

      NSDictionary *dict = @{
                             (id)kSecClass:(__bridge id)itemType,//kSecClassIdentity,
                             (id)kSecReturnRef:(id)kCFBooleanTrue,
                             (id)kSecValuePersistentRef:persistantRef,
      #if !TARGET_OS_IPHONE
                             (id)kSecUseKeychain:(__bridge id)customKeychain,
      #endif
                             };
      
      OSStatus status =  SecItemCopyMatching((CFDictionaryRef)dict, &result);
      NSCAssert(status != errSecParam, @"Invalid arguments");
      
      return result;
      

提交回复
热议问题