Skip to content

Latest commit

 

History

History
475 lines (347 loc) · 14.3 KB

README.md

File metadata and controls

475 lines (347 loc) · 14.3 KB

UICKeyChainStore

CI Status Coverage Status Carthage Compatibility Version License Platform

UICKeyChainStore is a simple wrapper for Keychain that works on iOS and OS X. Makes using Keychain APIs as easy as NSUserDefaults.

Looking for the library written in Swift?

Try KeychainAccess.
KeychainAccess is next generation of UICKeyChainStore.

Transitioning from 1.x to 2.0

synchronize method is deprecated. Calling this method is no longer required (Just ignored).

💡 Features

📖 Usage

🔑 Basics

Saving Application Password

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"com.example.github-token"];
keychain[@"kishikawakatsumi"] = @"01234567-89ab-cdef-0123-456789abcdef";

Saving Internet Password

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithServer:[NSURL URLWithString:@"https://github.com"]
                                                          protocolType:UICKeyChainStoreProtocolTypeHTTPS];
keychain[@"kishikawakatsumi"] = @"01234567-89ab-cdef-0123-456789abcdef";

🔑 Instantiation

Create Keychain for Application Password

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"com.example.github-token"];
UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"kishikawakatsumi.git"
                                                            accessGroup:@"12ABCD3E4F.shared"];

Create Keychain for Internet Password

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithServer:[NSURL URLWithString:@"https://github.com"]
                                                          protocolType:UICKeyChainStoreProtocolTypeHTTPS];
UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithServer:[NSURL URLWithString:@"https://github.com"]
                                                          protocolType:UICKeyChainStoreProtocolTypeHTTPS
                                                    authenticationType:UICKeyChainStoreAuthenticationTypeHTMLForm];

🔑 Adding an item

subscripting

keychain["kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef"

set method

[keychain setString:@"01234567-89ab-cdef-0123-456789abcdef" forKey:@"kishikawakatsumi"];

error handling

if (![keychain setString:@"01234567-89ab-cdef-0123-456789abcdef" forKey:@"kishikawakatsumi"]) {
    // error has occurred
}
NSError *error;
[keychain setString:@"01234567-89ab-cdef-0123-456789abcdef" forKey:@"kishikawakatsumi" error:&error];
if (error) {
    NSLog(@"%@", error.localizedDescription);
}

🔑 Obtaining an item

subscripting (automatically converts to string)

NSString *token = keychain["kishikawakatsumi"]

get methods

as String
NSString *token = [keychain stringForKey:@"kishikawakatsumi"];
as NSData
NSData *data = [keychain dataForKey:@"kishikawakatsumi"];

error handling

First, get the failable (value or error) object

NSError *error;
NSString *token = [keychain stringForKey:@"" error:&error];
if (error) {
    NSLog(@"%@", error.localizedDescription);
}

🔑 Removing an item

subscripting

keychain["kishikawakatsumi"] = nil

remove method

[keychain removeItemForKey:@"kishikawakatsumi"];

error handling

if (![keychain removeItemForKey:@"kishikawakatsumi"]) {
    // error has occurred
}
NSError *error;
[keychain removeItemForKey:@"kishikawakatsumi" error:&error];
if (error) {
    NSLog(@"%@", error.localizedDescription);
}

🔑 Label and Comment

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithServer:[NSURL URLWithString:@"https://github.com"]
                                                          protocolType:UICKeyChainStoreProtocolTypeHTTPS];
[keychain setString:@"01234567-89ab-cdef-0123-456789abcdef"
             forKey:@"kishikawakatsumi"
              label:@"github.com (kishikawakatsumi)"
            comment:@"github access token"];

🔑 Configuration (Accessibility, Sharing, iCould Sync)

Default accessibility matches background application (=kSecAttrAccessibleAfterFirstUnlock)
UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"com.example.github-token"];
For background application
Creating instance
UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"com.example.github-token"];
keychain.accessibility = UICKeyChainStoreAccessibilityAfterFirstUnlock;

keychain[@"kishikawakatsumi"] = @"01234567-89ab-cdef-0123-456789abcdef"
For foreground application
Creating instance
UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"com.example.github-token"];
keychain.accessibility = UICKeyChainStoreAccessibilityWhenUnlocked;

keychain[@"kishikawakatsumi"] = @"01234567-89ab-cdef-0123-456789abcdef"

👫 Sharing Keychain items

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"kishikawakatsumi.git"
                                                            accessGroup:@"12ABCD3E4F.shared"];
Creating instance
UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"com.example.github-token"];
keychain.synchronizable = YES;

keychain[@"kishikawakatsumi"] = @"01234567-89ab-cdef-0123-456789abcdef"

Any Operation that require authentication must be run in the background thread.
If you run in the main thread, UI thread will lock for the system to try to display the authentication dialog.

🔐 Adding a Touch ID protected item

If you want to store the Touch ID protected Keychain item, specify accessibility and authenticationPolicy attributes.

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"com.example.github-token"];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    [keychain setAccessibility:UICKeyChainStoreAccessibilityWhenPasscodeSetThisDeviceOnly
          authenticationPolicy:UICKeyChainStoreAuthenticationPolicyUserPresence];

    keychain[@"kishikawakatsumi"] = @"01234567-89ab-cdef-0123-456789abcdef"
});

🔐 Updating a Touch ID protected item

The same way as when adding.

Do not run in the main thread if there is a possibility that the item you are trying to add already exists, and protected. Because updating protected items requires authentication.

Additionally, you want to show custom authentication prompt message when updating, specify an authenticationPrompt attribute. If the item not protected, the authenticationPrompt parameter just be ignored.

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"com.example.github-token"];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    [keychain setAccessibility:UICKeyChainStoreAccessibilityWhenPasscodeSetThisDeviceOnly
          authenticationPolicy:UICKeyChainStoreAuthenticationPolicyUserPresence];
    keychain.authenticationPrompt = @"Authenticate to update your access token";

    keychain[@"kishikawakatsumi"] = @"01234567-89ab-cdef-0123-456789abcdef"
});

🔐 Obtaining a Touch ID protected item

The same way as when you get a normal item. It will be displayed automatically Touch ID or passcode authentication If the item you try to get is protected.
If you want to show custom authentication prompt message, specify an authenticationPrompt attribute. If the item not protected, the authenticationPrompt parameter just be ignored.

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"com.example.github-token"];

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
    [keychain setAccessibility:UICKeyChainStoreAccessibilityWhenPasscodeSetThisDeviceOnly
          authenticationPolicy:UICKeyChainStoreAuthenticationPolicyUserPresence];
    keychain.authenticationPrompt = @"Authenticate to update your access token";

    NSString *token = keychain[@"kishikawakatsumi"];
});

🔐 Removing a Touch ID protected item

The same way as when you remove a normal item. There is no way to show Touch ID or passcode authentication when removing Keychain items.

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithService:@"com.example.github-token"];

keychain[@"kishikawakatsumi"] = nil;

🔑 Debugging

Display all stored items if print keychain object

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithServer:[NSURL URLWithString:@"https://github.com"]
                                                          protocolType:UICKeyChainStoreProtocolTypeHTTPS];
NSLog(@"%@", keychain);
=>
(
{
    accessibility = ak;
    authenticationType = dflt;
    class = InternetPassword;
    key = kishikawakatsumi;
    protocol = htps;
    server = "github.com";
    synchronizable = 0;
    value = "01234567-89ab-cdef-0123-456789abcdef";
}    {
    accessibility = ck;
    authenticationType = dflt;
    class = InternetPassword;
    key = hirohamada;
    protocol = htps;
    server = "github.com";
    synchronizable = 1;
    value = "11111111-89ab-cdef-1111-456789abcdef";
}    {
    accessibility = ak;
    authenticationType = dflt;
    class = InternetPassword;
    key = honeylemon;
    protocol = htps;
    server = "github.com";
    synchronizable = 0;
    value = "22222222-89ab-cdef-2222-456789abcdef";
})

Obtaining all stored keys

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithServer:[NSURL URLWithString:@"https://github.com"]
                                                          protocolType:UICKeyChainStoreProtocolTypeHTTPS];

NSArray *keys = keychain.allKeys;
for (NSString *key in keys) {
    NSLog(@"key: %@", key);
}
=>
key: kishikawakatsumi
key: hirohamada
key: honeylemon

Obtaining all stored items

UICKeyChainStore *keychain = [UICKeyChainStore keyChainStoreWithServer:[NSURL URLWithString:@"https://github.com"]
                                                          protocolType:UICKeyChainStoreProtocolTypeHTTPS];

NSArray *items = keychain.allItems;
for (NSString *item in items) {
    NSLog(@"item: %@", item);
}
=>

item: {
    accessibility = ak;
    authenticationType = dflt;
    class = InternetPassword;
    key = kishikawakatsumi;
    protocol = htps;
    server = "github.com";
    synchronizable = 0;
    value = "01234567-89ab-cdef-0123-456789abcdef";
}
item: {
    accessibility = ck;
    authenticationType = dflt;
    class = InternetPassword;
    key = hirohamada;
    protocol = htps;
    server = "github.com";
    synchronizable = 1;
    value = "11111111-89ab-cdef-1111-456789abcdef";
}
item: {
    accessibility = ak;
    authenticationType = dflt;
    class = InternetPassword;
    key = honeylemon;
    protocol = htps;
    server = "github.com";
    synchronizable = 0;
    value = "22222222-89ab-cdef-2222-456789abcdef";
}

Convienient class methods

Add items using default service name (=bundle identifer).

[UICKeyChainStore setString:@"01234567-89ab-cdef-0123-456789abcdef" forKey:@"kishikawakatsumi"];

Or specify the service name.

[UICKeyChainStore setString:@"01234567-89ab-cdef-0123-456789abcdef"
                     forKey:@"kishikawakatsumi"
                    service:@"com.example.github-token"];

Remove items.

[UICKeyChainStore removeItemForKey:@"kishikawakatsumi" service:@"com.example.github-token"];

To set nil value also works remove item for the key.

[UICKeyChainStore setString:nil forKey:@"kishikawakatsumi" service:@"com.example.github-token"];

Requirements

iOS 4.3 or later OS X 10.7 or later

Installation

CocoaPods

UICKeyChainStore is available through CocoaPods. To install it, simply add the following line to your Podfile:

pod 'UICKeyChainStore'

Carthage

UICKeyChainStore is available through Carthage. To install it, simply add the following line to your Cartfile:

github "kishikawakatsumi/UICKeyChainStore"

To manually add to your project

  1. Add Security.framework to your target.
  2. Copy files in Lib (UICKeyChainStore.h and UICKeyChainStore.m) to your project.

Author

kishikawa katsumi, [email protected]

License

UICKeyChainStore is available under the MIT license. See the LICENSE file for more info.