iOS Keychain occasionally return empty string - iphone

I write very secure application (for Bank) and I keep the private key in the Keychain.
I keep the Private key using the following code:
+(void)savePrivatekey:(NSString *)Key
{
KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"pKey" accessGroup:nil];
[keychain setObject:Key forKey:(id)kSecValueData];
[keychain release];
}
and for get the private key using the following code:
+(NSString *)privateKey
{
KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"pKey"accessGroup:nil];
NSString *privateKey = [keychain objectForKey:(id)kSecValueData];
[keychain release];
return privateKey;
}
i don't save the private key in local variable from security reasons.
because every call to server I need the private key i call to to function
"GetPrivateKey" a lot of times.
Maybe that's why sometimes i get from the keychain empty string.
i can't think of why this might happen.
I noticed that in most cases this happens when the application return from background but no only...
thanks...
I opened ticket at Apple's engineers and they responded to me:
Are you setting the kSecAttrAccessible attribute when you create the keychain item initially?
I always create the same shape keychain:
KeychainItemWrapper * keychain = [[KeychainItemWrapper alloc] initWithIdentifier: # "pKey" accessGroup: nil];
Does anyone know what their intent?
thanks...

I answered my own question a while back regarding this. I'm not sure if this is your exact problem as your code seems to look/work fine. So regarding your keychain access, I'm guessing it is a bit different. This may or may not help, but might steer you in the right direction.
iOS KeyChain not retrieving values from background

If your class is using ARC the following works for me every time.
KeychainItemWrapper *testKeychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"AppUniqueID" accessGroup:nil];
NSString *privateKey = [testKeychain objectForKey:(__bridge id)(kSecValueData)];
NSLog(#"Private Key: %# \n", privateKey);

Related

Access Keychain elements in different view

I use a Multi View, tabbed app. From the FirstViewController, I use PresentViewController to display LoginViewController.
On LoginViewController, I'm using Keychain to save a username and a password when a user logs in on my app.
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:#"LoginInfos" accessGroup:nil];
[keychainItem setObject:_password forKey:(__bridge id)(kSecValueData)];
[keychainItem setObject:_pseudo forKey:(__bridge id)(kSecAttrAccount)];
Now, I'd like to be able to check on FirstViewController if something is set in the keychain, and if so, obviously NOT display LoginViewController. But when I try to access the keychain from FirstViewController, even after doing #import 'KeychainItemWrapper.h', I get an error saying I'm using an undeclared identifier 'keychainItem'.
NSString *mdp = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSString *username = [keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];
How can I access the info stored in the Keychain from another view? And is there a better solution (for eg, a global variable?) to check if a user is logged in?
It sounds like you just need to initialize an instance of KeychainItemWrapper in your FirstViewController... Just do:
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:#"LoginInfos" accessGroup:nil];
again before you try retrieving values from it.

How to check if something is stored in the iPhone keychain?

I have this code currently storing the information into the iPhone keychain. How can I check with a simple if statement if there is something under the same name already stored there to prevent double storage and to tell me if this is the first time the user is using the app?
KeychainItemWrapper* keychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"KeychainTest" accessGroup:nil];
[keychain setObject:username.text forKey:(__bridge id)(kSecAttrAccount)];
[keychain setObject:password.text forKey:(__bridge id)(kSecValueData)];
keychain = nil;
usernameAll = [keychain objectForKey:(__bridge id)kSecAttrAccount];
passwordAll = [keychain objectForKey:(__bridge id)kSecValueData];
You won't cause double storage. You will overwrite any existing value.
Create your keychain object, then call objectForKey:. If the result is nil then you know that there is no existing value for the key.
KeychainItemWrapper* keychain = [[KeychainItemWrapper alloc] initWithIdentifier:#"KeychainTest" accessGroup:nil];
if ([keychain objectForKey:(__bridge id)(kSecAttrAccount)]) {
// existing value
} else {
// no existing value
}
Checking to see if a user is using an app for the first time is usually done by writing a value to NSUserDefaults the first time the app is used. On startup, this value is checked. If the value exists, it's not the first run. If you need this check to survive an app deletion and reinstall, then use the keychain instead of NSUserDefaults to store this flag.

MapKit in iOS 6 - How to Find Places Nearby...?

Using MapKit in iOS 6, how am I'm supposed to get nearby locations without having their specific coordinates? I'm also unsure if it's still possible...err...allowed...to use Google Maps API to accomplish this goal, as this is the only way I can think of to do this. I know everything is still in beta, but I've still found no information anywhere about this topic, on forums, in Apple's new MapKit Documentation, anywhere. All I want to do is perform a search for locations (let's say, parks, for example) within 'x' miles of the user's location.
It seems that since Apple has developed their own Maps application, they should have a way to accomplish this using MapKit or Core Location...right?
Try with this code. This may help to you.
URLManager *urlmanager = [[URLManager alloc] init];
urlmanager.delegate = self;
urlmanager.responseType = JSON_TYPE;
urlmanager.commandName = #"Search";
NSString *locationString = [NSString stringWithFormat:#"%f,%f",latitude,longitude];
//Location where you want to search
NSString *key = #"AIzaSyCNRpero6aM451X0IfgFHAd-Y3eJUssqoa8`enter code here`0E";
//This is the secret key which you will get from the Google API Console when you register your app.
NSString *radiuos = #"15000";
//This is the area within which you want to search
NSString *keyword = #"Hotel";//Search keyword you want to search
NSMutableDictionary *arguments = [[NSMutableDictionary alloc] init]; // zero argument
[arguments setValue:key forKey:#"key"];
[arguments setValue:locationString forKey:#"location"];
[arguments setValue:radiuos forKey:#"radius"];
[arguments setValue:#"true" forKey:#"sensor"];
[arguments setValue:keyword forKey:#"keyword"];
NSLog(#"Arguments are %#",arguments);
[urlmanager urlCallGetMethod:[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/search/json"] withParameters:arguments];

Work-around for setting defaults before settings.bundle is initialised

(I'm new to IOS and Objective-C so please excuse any miss-use of terminology...)
In my app I have chosen to use the settings.bundle to store my app settings but when the app is first installed and before the user navigates to Settings on their IOS device it does not load the defaults. I have read many posts explaining that the app should create its own defaults until the settings.bundle has been 'initialised'.
To do this I have written some code that reads in the settings.bundle and creates an array accordingly. But if settings.bundle has not been initialised it creates a default array to be used in the interim. I suspect that my problem is with the following line of code where I am using a logical AND operator (probably incorrectly...):
if (!([swimtypeendurance isEqualToString:#"ON"]) && !([swimtypeendurance isEqualToString:#"OFF"]))
The problem is that I cannot get a true result for the if statement above, my app always executes the 'else'. My understanding of settings.bundle is that if they have not been initialised then the switch is neither ON or OFF as if it has no value. I am therefore testing to see if the string for swimtypeendurance is neither ON or OFF, in other words if it is not ON AND it is not OFF - hence my attempted use of the ! and &&...
Perhaps a better way to exaplain what I am doing is: I am testing the value of one of my settings from settings.bundle to see if it is either on or off. If it is one of the two states then I assume that the settings bundle has been initialised and all settings can be used, if not i.e. it is stateless then I create an array to be used until the user does initialise settings.bundle.
Here is the complete snippet of code to provide context to the question:
NSMutableArray* arrayofswimtypes = [NSMutableArray arrayWithCapacity:15];
NSString *swimtt750 = [defaults boolForKey:kswimtypett750mKey]? #"ON" : #"OFF";
if ([swimtt750 isEqualToString:#"ON"]) {
swimTypeTt750m = [[NSString alloc] initWithFormat:#"Time Trial - 750m"];
[arrayofswimtypes addObject:[[NSString alloc] initWithFormat:#"%#", swimTypeTt750m]];
}
NSString *swimtt1500 = [defaults boolForKey:kswimtypett1500mKey]? #"ON" : #"OFF";
if ([swimtt1500 isEqualToString:#"ON"]) {
swimTypeTt1500m = [[NSString alloc] initWithFormat:#"Time Trial - 1500m"];
[arrayofswimtypes addObject:[[NSString alloc] initWithFormat:#"%#", swimTypeTt1500m]];
}
[arrayofswimtypes addObject:[[NSString alloc] initWithFormat:#"General Session"]];
NSString *swimtypedrills = [defaults boolForKey:kswimtypedrillsKey]? #"ON" : #"OFF";
if ([swimtypedrills isEqualToString:#"ON"]) {
swimTypeDrills = [[NSString alloc] initWithFormat:#"Drills Session"];
[arrayofswimtypes addObject:[[NSString alloc] initWithFormat:#"%#", swimTypeDrills]];
}
NSString *swimtypeendurance = [defaults boolForKey:kswimtypeenduranceKey]? #"ON" : #"OFF";
if ([swimtypeendurance isEqualToString:#"ON"]) {
swimTypeEndurance = [[NSString alloc] initWithFormat:#"Endurance Session"];
[arrayofswimtypes addObject:[[NSString alloc] initWithFormat:#"%#", swimTypeEndurance]];
}
//Place an if-else statement in here to load a default array if the user has not been to settings and initialised the settings.bundle
if (!([swimtypeendurance isEqualToString:#"ON"]) && !([swimtypeendurance isEqualToString:#"OFF"])) {
swimSessTypesArray = [[NSMutableArray alloc] initWithObjects:[[NSString alloc] initWithFormat:#"Time Trial - 750m"],
[[NSString alloc] initWithFormat:#"Time Trial - 1500m"],
[[NSString alloc] initWithFormat:#"General Session"],
[[NSString alloc] initWithFormat:#"Drills Session"],
[[NSString alloc] initWithFormat:#"Endurance Session"], nil];
NSLog(#"Count of swimSessTypesArray NOT FROM Defaults: %i", [swimSessTypesArray count]);
} else {
swimSessTypesArray = arrayofswimtypes;
NSLog(#"Count of swimSessTypesArray from Defaults: %i", [swimSessTypesArray count]);
}
Any hints and comments on this would be massively appreciated including any improvements that I can make to my coding based on your superior knowledge and experience.
Many thanks in advance for your assistance...
OK, the comment from Matthias has led me to my working solution. Essentially there are two common methods for testing if the settings.bundle for your app have been initialised by the user and set defaults to be used if not: 1) use registerDefaults and 2) create your own tests by using some IF-ELSE statements. Since the question is related to the latter of the two options I will answer it and not the registerDefaults method.
The first thing that one should know is that boolForKey will return a NO under 2 different conditions: firstly when the key does not exist (effectively when the settings bundle has not been initialised by the user) and when it is set to the no of OFF position. This makes it very impossible to test using boolForKey but if you use objectForKey to test whether or not the key exists then it works perfectly. The code looks like this (in keeping with the example code from the question):
if (![boolForKey:kswimtypeednurancekey]) {
Create your default settings to be used by the app;
} else {
Use the settings from the settings.bundle;
}

Reading using Keychain Wrapper class return Null - IOS

I am using Keychainwrapper class downloaded from Apple documentation for storing login information like password. In my apps when user click on sign in button, I am storing in key chain like below...
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc]
initWithIdentifier : #"vmo_login" accessGroup:nil];
[keychainItem setObject:email_id.text forKey:(__bridge NSString*)kSecAttrAccount];
[keychainItem setObject:password.text forKey:(__bridge NSString*)kSecValueData];
And if user click on sign out I am exiting application with exit(1). Once application is launched again, I am reading from keychain like below..
NSString *loc_email1 = [keychainItem objectForKey:(__bridge NSString*)kSecAttrAccount];
NSString *loc_pwd1 = [keychainItem objectForKey:(__bridge NSString*)kSecValueData];
I have not got what I have stored below, it returns NULL. Any Idea?.
thanks.
I have found the problem..
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc]
initWithIdentifier : #"<need to give same as when we write>" accessGroup:nil];
Working fine now.