iCloud sync keychain

后端 未结 4 829
庸人自扰
庸人自扰 2021-01-11 20:41

In my app, I want to be able to sync a configuration that gets created by the user. I wanted to use iCloud to sync that configuration so that it is always the same on all de

相关标签:
4条回答
  • 2021-01-11 21:11

    Looking to do the same, haven't tried yet but this looks helpful: https://github.com/iosengineer/BMCredentials

    0 讨论(0)
  • 2021-01-11 21:25

    No, keychain syncing is not part of iCloud. It was part of dot mac syncing, but that is no longer available.

    There will probably be feedback on whether this is a good idea or not (automatically moving passwords from one device to another), especially in the situation where multiple people share an iCloud account (likely, but not guaranteed these days).

    If you feel that storing the password on the device's keychain (and thus requiring the user to enter it at least once per device), then you will need to provide your own encryption and safety and store the data in iCloud directly, such as in the keystore.

    0 讨论(0)
  • 2021-01-11 21:31

    iCloud Keychain is a new feature in iOS 7.0.3 and OS X Mavericks 10.9. Specify the kSecAttrSynchronizable attribute when adding a keychain item using the SecItem API.

    0 讨论(0)
  • 2021-01-11 21:32

    These are the utility methods I've made for keychain. kSecAttrSynchronizable is what makes iCloud Sync work. Hope they help.

    • Keychain Query.
    • Remove item
    • Delete item
    • Save item
    • Load item

      + (NSMutableDictionary *)getKeychainQuery:(NSString *)service {
          return [NSMutableDictionary dictionaryWithObjectsAndKeys:
                  (__bridge id)kSecClassGenericPassword, (__bridge id)kSecClass,
                  service, (__bridge id)kSecAttrService,
                  service, (__bridge id)kSecAttrAccount,
                  service, (__bridge id)kSecAttrSynchronizable,
                  (__bridge id)kSecAttrAccessibleAfterFirstUnlock, (__bridge id)kSecAttrAccessible,
                  nil];
      }
      
      + (void)save:(NSString *)service data:(id)data {
          NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
          SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
          [keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(__bridge id)kSecValueData];
          SecItemAdd((__bridge CFDictionaryRef)keychainQuery, NULL);
      }
      
      + (void)remove:(NSString *)service {
           NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
           SecItemDelete((__bridge CFDictionaryRef)keychainQuery);
      }
      
      +(NSString *)keychainItem:(NSString *)service{
          id data = [self load:service];
      
          if([data isKindOfClass:[NSString class]]){
              return data;
          }
          return @"";
      }
      
      + (id)load:(NSString *)service {
          id ret = nil;
          NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
          [keychainQuery setObject:(id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
          [keychainQuery setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
          CFDataRef keyData = NULL;
          if (SecItemCopyMatching((__bridge CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr) {
              @try {
                  ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
              }
              @catch (NSException *e) {
                  NSLog(@"Unarchive of %@ failed: %@", service, e);
               }
              @finally {}
          }
          if (keyData) CFRelease(keyData);
          return ret;
      }
      
    0 讨论(0)
提交回复
热议问题