EzDev.org

sskeychain

Simple Objective-C wrapper for the keychain that works on Mac and iOS


How can i get the evernote Token from an user with iOS SDK?

I'm trying to get the user token after the authentication succeeded with the

ENCredentials *credential = [[ENCredentials alloc] init];
NSLog(@"%@", credential.authenticationToken);

and i got this error

Error getting password from keychain: Error Domain=com. samsoffes.ENSSKeychain Code=-1001 "ENSSKeychainErrorBadArguments" UserInfo={NSLocalizedDescription=ENSSKeychainErrorBadArguments

anybody got this error yet? thanks


Source: (StackOverflow)

How to choose account and service values for SSKeychain

I'm thinking of using SSKeychain for storing a password in an iOS app, but I'm not sure if I need some specific value for the account and service, or if it will be OK with just arbitrary ones. Is there a common practice?


Source: (StackOverflow)

Using SSkeychain to store access tokens

I'm trying to figure out how to use the SSkeychain in order to store access tokens for the instagram api. I'm currently using NSUserDefault class but I dont think thats the best of ideas.

Does the SSkeychain class itself need to be allocated and initialized in order to be used as well?


Source: (StackOverflow)

CFUUID stored in SSKeychain is null in some devices

My published application makes use of the CFUUID and SSKeychain in order to identify the device (and to keep that ID unchanged even if the app is uninstalled and reinstalled)

I save those device ID in the server, and I recently noticed that some users have several of those IDs for the same real device. The only explanation I see is that the ID is not being saved or loaded from the Keychain and thus the device generates a new one. The strange thing is that it works fine on some other devices running the same iOS version.

Any ideas on what could be going on?

This is my related code in (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

NSString* identifier = @"appName";
NSString* serviceName = @"com.company.appName";
NSString *retrieveuuid = [SSKeychain passwordForService:serviceName account:identifier];
if (retrieveuuid == nil) {
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    NSString *uuid  = (NSString*) string;
    [SSKeychain setPassword:uuid forService:serviceName account:identifier];
}

EDIT: My guess is that retrieveuuid == nil is not working as expected for some reason. Later in the app I register for push notifications and send the push token to the server together with this CFUUID that I read with the same exact line [SSKeychain passwordForService:serviceName account:identifier] but when it is sent to the server it is not nil (So I can see several CFUUIDs with the same push token).

EDIT 2 to attach more actual code.

AppDelegate.m

NSString* identifier = @"appName";
NSString* serviceName = @"com.company.appName";
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    //Creating UUID
    NSString *retrieveuuid = [AppDelegate getDeviceId];
    if (retrieveuuid == nil) {
        CFUUIDRef theUUID = CFUUIDCreate(NULL);
        CFStringRef string = CFUUIDCreateString(NULL, theUUID);
        CFRelease(theUUID);
        NSString *uuid  = (NSString*) string;
        [SSKeychain setPassword:uuid forService:serviceName account:identifier];
    }

    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:
     (UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
}

+ (NSString*) getDeviceId {
    return [SSKeychain passwordForService:serviceName account:identifier];
}

- (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken
{
    NSString *newToken = [deviceToken description];
    newToken = [newToken stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    newToken = [newToken stringByReplacingOccurrencesOfString:@" " withString:@""];

    _deviceToken = [[NSString alloc] initWithString:newToken];

    NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
    NSString *user = [prefs objectForKey:@"appNameUsername"];

    if(user && ![user isEqualToString:@""]){
        RestClient *rest = [[RestClient alloc] init];
        rest.delegate = self;
        rest.tag = 2;
        [rest updateToken:newToken ForUsername:user];
        [rest release];
    }
}

RestClient.m

-(void) updateToken:(NSString *)token ForUsername:(NSString *)userName{
    NSArray* info = [NSArray arrayWithObject: [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                               userName, @"Username",
                                               token, @"TokenNo",
                                               [[UIDevice currentDevice].model hasPrefix:@"iPad"] ? @"iPad" : @"iPhone", @"Device",
                                               [UIDevice currentDevice].systemVersion, @"OSVersion",
                                               [AppDelegate getDeviceId], @"DeviceID",
                                               @"updateToken", @"CMD",
                                               nil]];
    [self doAction:info];
}

The doAction method just sends the data to the server and then callback the delegate, that part works fine. I can see on the server the logs of receiving this command:

"JSONCMD":"[
{   "TokenNo" : "f0d3aa21758350333b7e6315c38_EDIT_257c1838f49c43049f8380ec1ff63", 
    "AppVersion" : "1.0.4",
    "Username" : "user@server.com", 
    "CMD" : "updateToken", 
    "OSVersion" : "7.0.4", 
    "DeviceID" : "9B794E11-6EF7-470C-B319-5A9FCCDAFD2B", 
    "Device" : "iPhone"
}
]  

I see 2 possible candidates causing the strange behaviour, the NSStrings in the controller body and the static getDevice method. However, I don't see how this could work in many devices but fail in others.


Source: (StackOverflow)

iCloud Keychain notify on update

I'm using the new iCloud Keychain feature implemented by SSKeychain. I set kcQuery.synchronizationMode = SSKeychainQuerySynchronizationMode.Yes to my passwords

Does iCloud Keychain now work? Will it be synchronized to my other iDevices?

How long does it take before my items will pushed to iCloud?

Is there a method which notifies me if new passwords reached my device?

Thanks!


Source: (StackOverflow)

SSKeychain delete account

I want to delete an account from my SSKeychain. I only get the method to delete the password, but the account is still in the keychain.

Is there a way to delete an account or clear the SSKeychain?


Source: (StackOverflow)

How to save CFUUID in keychain

I'm developing an iPhone application.
The application access some web service that aboug other things should recognize the device ID.

Since UDID is deprecated, I need to call CFUUIDCreate to generate my own UUID for this purpose.

The ID is security-sensitive: all my network communication is encrypted, and I don't want nobody but my certificate-authenticated server to know that UUID.
Besides, I want this identifier to survive re-install.
Using the keychain to store that UUID seems like an obvious solution.

How do I do that?

On the internets, there're some samples how to store user name & password in keychain. I have neither user nor password, just 16 bytes UUID (or a single NSString).

Which kSecClass do I need to use?
Which attributes do I need to set and retrieve?
Which attributes are optional and which are mandatory?

What header/framework defines the CSSM_ALGORITHMS?
The doc mentions cssmtype.h, xcode autocompletion has <Security/cssmtype.h> however the xcode compiler says "file not found".

From the common sense, "Identity" should fit best. The docs however say "an identity is the combination of a private key and a certificate", I have neither of them. Also, I don't see the "key bytes" attribute.

Thanks in advance!


Source: (StackOverflow)

SecItemAdd and SecItemCopyMatching returns error code -34018 (errSecMissingEntitlement)

Sometimes when I run an application on device from Xcode I would try to access the keychain but fail due to error -34018. This doesn't match any of the documented keychain error codes and can't be consistently reproduced. (happens maybe 30% of the time, and it's not clear to me why it happens). What makes debugging this problem very difficult is the total lack of documentation. Any idea what causes this and how to fix it? I'm using Xcode 5 and running iOS 7.0.4 on device.

There is an open issue about this here: https://github.com/soffes/sskeychain/issues/52

EDIT: Adding keychain access code per request

I'm using the SSKeychain library for interfacing with keychain. Here's the snippet.

#define SERVICE @"default"

@implementation SSKeychain (EXT)

+ (void)setValue:(NSString *)value forKey:(NSString *)key {
    NSError *error = nil;
    BOOL success = NO;
    if (value) {
        success = [self setPassword:value forService:SERVICE account:key error:&error];
    } else {
        success = [self deletePasswordForService:SERVICE account:key error:&error];
    }
    NSAssert(success, @"Unable to set keychain value %@ for key %@ error %@", value, key, error);
    if (!success) {
        LogError(@"Unable to set value to keychain %@", error);
    }
    LogTrace(@"Will set keychain account %@. is to nil? %d", key, value == nil);
    if (value == nil)
        LogWarn(@"Setting keychain %@ to nil!!!", key);
}

+ (NSString *)valueForKey:(NSString *)key {
    NSError *error = nil;
    NSString *value = [self passwordForService:SERVICE account:key error:&error];
    if (error && error.code != errSecItemNotFound) {
        NSAssert(!error, @"Unable to retrieve keychain value for key %@ error %@", key, error);
        LogError(@"Unable to retrieve keychain value for key %@ error %@", key, error);
    }
    return value;
}

+ (BOOL)removeAllValues {
    LogInfo(@"Completely Reseting Keychain");
    return [[self accountsForService:SERVICE] all:^BOOL(NSDictionary *accountInfo) {
        return [self deletePasswordForService:SERVICE account:accountInfo[@"acct"]];
    }];
}

@end

Vast majority of the time it's just fine. Sometimes I'll hit the assertion failures where I'm unable to either write to or read from keychain, causing critical assertion failure.


Source: (StackOverflow)

Keychain doesn't retain the data after app gets update from iTunes

I have been using SSKeychain open source library for storing the data securely in my iOS app. Yesterday, I face an issue ,SSKeychain wasn't able to retain its data when I updated my app from v1.0 to v2.0 from iTunes.

Code for UUID Generation :

- (NSString *)createNewUUID
{
    CFUUIDRef theUUID = CFUUIDCreate(NULL);
    CFStringRef string = CFUUIDCreateString(NULL, theUUID);
    CFRelease(theUUID);
    return (__bridge NSString *)string;
}

Over here, I generated a unique device string and used the keychain to store the same and the app heavily depends on unique string/Device Identifier since from iOS5 to iOS7 there are lots of transformations done by Apple in concerned to Unique Device Identifier, since the methods got deprecated.

Cope snippet for Store & Retrive :

NSString *retrieveuuid = [SSKeychain passwordForService:@"com.name.appname" account:@"AppName"];
if (retrieveuuid == nil) {
    NSString *uuid  = [self createNewUUID];

    //Store the password in Keychain
    NSError *error = nil;
    [SSKeychain setPassword:uuid forService:@"com.name.appname" account:@"AppName" error:&error];

    if ([error code] == SSKeychainErrorNotFound) {
        NSLog(@"ID not found");
    }
}

So, is this something that keychain won't be able to retain its values/identifier, when the app gets updated from Apple OR am I missing out at some point. Please help out if its possible to store the Identifier permanently in device, irrelevant of Installing, uninstalling ,reset and updating the app.

Alternatively, is there any API, which can provide me the same deviceID/unique string when generated so need to store the Unique String?

Note : App has to support iOS 4.3 and above.


Source: (StackOverflow)

Tutorial on sskeychain and basic auth for iPad apps?

Where can I find a good detailed tutorial using sskeychain to store and retrieve usernames and passwords and to do basic authentication in a UIWebView? Secondarily, am I on the right track as far as the methods needed to store and use authentication for a web based application? (See explanation below.)

I found a couple tutorials using different methods:

According to recommendations from other SO questions below, sskeychain is recommended for an easier use of the keychain to store authentication parameters.

My plan is to store a username and password locally on the device in the keychain as recommended and connect over a UIWebView using basic auth to my PHP code. Is there a good step by step tutorial for xcode/Obj-C newbies on the topic of user authentication that would be recommended by experienced iOS developers?

The Apple documentation seems less than helpful. It's either pages with simple sales jargon or just head imploding descriptions of methods and parameters without many helpful examples.

Update:

I ended up just using NSUserDefaults to store the username and password locally and the AFNetworking library to do the authentication. If these are unwise I'd welcome an answer that supplies guidance on a better method.


Source: (StackOverflow)

Why does this for loop bleed memory?

I am using ARC for my iOS project and am using a library called SSKeychain to access/save items to the keychain. I expect my app to access keychain items once every 10 seconds or so (to access API security token) at peak load and as such I wanted to test this library to see how it handles when called frequently. I made this loop to simulate an insane amount of calls and noticed that it bleeds a significant amount (~75 mb) of memory when run on an iPhone (not simulator):

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    dispatch_async(dispatch_get_main_queue(), ^{
        NSUInteger beginMemory = available_memory();
        for (int i = 0; i < 10000; ++i) {

            @autoreleasepool{
                NSError *  error2 = nil;
                SSKeychainQuery*  query2 = [[SSKeychainQuery alloc] init];
                query2.service = @"Eko";
                query2.account = @"loginPINForAccountID-2";
                query2.password = nil;
                [query2 fetch:&error2];
            }
        }
        NSUInteger endMemory = available_memory();

        NSLog(@"Started with %u, ended with %u, used %u", beginMemory, endMemory, endMemory-beginMemory);
    });

    return YES;
}

static NSUInteger available_memory(void) {
    // Requires #import <mach/mach.h>
    NSUInteger result = 0;
    struct task_basic_info info;
    mach_msg_type_number_t size = sizeof(info);
    if (task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&info, &size) == KERN_SUCCESS) {
        result = info.resident_size;
    }
    return result;
}

I am using SSKeychain which can be found here. This test bleeds about ~75 mb of memory regardless if things are actually stored on the keychain.

Any ideas what is happening? Is my testing methodology flawed?


Source: (StackOverflow)

Small percentage of users getting errSecItemNotFound when retrieving data from the Keychain

I have an iOS app that stores an access token in the Keychain. In the last few months, I've noticed that around 2% of the users get an errSecItemNotFound when trying to retrieve the token.

All the relevant StackOverflow threads point to background tasks being the culprit (iOS KeyChain not retrieving values from background) or including invalid params in the query string (Keychain: Item reported as errSecItemNotFound, but receive errSecDuplicateItem on addition).

I'm using kSecAttrAccessibleAfterFirstUnlock so background tasks should be able to access the Keychain just fine.

Moreover, the search query looks like this:

NSMutableDictionary *query = [[NSMutableDictionary alloc] init];
[query setObject:(__bridge id)kSecClassGenericPassword forKey:(__bridge id)kSecClass];
[query setObject:(__bridge id)kCFBooleanTrue forKey:(__bridge id)kSecReturnData];
[query setObject:(__bridge id)kSecMatchLimitOne forKey:(__bridge id)kSecMatchLimit];
[query setObject:service forKey:(__bridge id)kSecAttrService];
[query setObject:key forKey:(__bridge id)kSecAttrGeneric];
[query setObject:key forKey:(__bridge id)kSecAttrAccount];

(Setting kSecAttrGeneric is probably redundant, but it does not affect the outcome of the query anyway)

For the record, I've experienced this bug with both SSKeyChain and UICKeychainStore.

Any hints would be highly appreciated :]


Source: (StackOverflow)

Potential Loss of Keychain Access Issue After Application Move Account A To B in iOS

Our iOS app is transfer from Account A to B, Earlier we had used the certificates which was created in Account A and upload a build on iTunes Connect using certificates of Account A.

Now when we uploading app on iTunesconenct for Beta Testing that time we have used the certificates which was created in Account B(Due to Transfer App Account).

So, Now application identifier of the live app is different from the application identifier of the Beta TestFlight Testing App on App Store. And we have got the warning potential loss of keychain access.

Right Now, We are using SSKeychain Wrapper for Store UUID to track user. [SSKeychain setPassword:UUID forService:@"com.example.appname” account:@“appname” error:&error]

If App ID Prefix changed then SSKeychain loss it’s access?

Because We track UUID in database for further use using SSKeychain. My doubt is if APPID Prefix changed then it is also effect the SSKeychain and it is generate new UUID for all devices?

So, How we can solve this issue ? Please let us know about solutions of this issue.


Source: (StackOverflow)

SSKeychain the authenticity of "AppName" cannot be verified

I've recently implemented SSKeychain in my application, every single time i try to access values from the keychain i get prompted to give permission to access the keychain with the message "the authenticity of "AppName" cannot be verified. Do you want to allow access to this item?

i've chosen "Always Allow" about a gillion times but it still prompts me no matter what. its really annoying and looks incredibly unprofessional. pulling my hair out trying to figure out what im doing wrong or how to fix it. to save a password im using

[SSKeychain setPassword:self.passwordField.stringValue forService:@"AppName" account:self.loginField.stringValue];

and to retrieve it

[SSKeychain passwordForService:@"AppName" account:self.loginField.stringValue];

any thoughts?


Source: (StackOverflow)

errSecDefault for accessing iOS keychain password

I am using SSKeychain as a wrapper to store a user's access token and user ID.

I make a web request for my user's access token during sign up and then I call [SSKeychain setPassword:@"password" forService:@"myService" account:@"myAccount"]

However, when I attempt to access the password with [SSKeychain passwordForService:@"myService" account:@"myAccount" error:&error], I get nil and when I log the error, I get errSecDefault.

I've done some online research on the errSecDefault, and I've checked out SSKeychain's documentary as well as issues on github. It seems like other's have the same problem, but I haven't found any solution. It also seems to be something inherent to Keychain, and not the wrapper, (based on what i've read from the issue threads).

Has anyone encountered this error using the keychain and figured out how what it even means?


Source: (StackOverflow)