Nic Hubbard
Nic Hubbard

Reputation: 42157

iCloud sync keychain

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 devices. But, I use the keychain to store the password.

Is there a way to also sync keychain data?

Upvotes: 12

Views: 6574

Answers (4)

beebcon
beebcon

Reputation: 6983

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

Upvotes: 0

Gautam Jain
Gautam Jain

Reputation: 2911

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;
    }
    

Upvotes: 5

jrc
jrc

Reputation: 21921

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.

Upvotes: 20

gaige
gaige

Reputation: 17481

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.

Upvotes: 3

Related Questions