Reputation: 167
All this happened in my simulator. While practicing using keychain wrappers I've found myself in a strange situation. I was trying to learn how to insert and retrieve data form the keychain, and, in order to do this, I started a new project in which, the only thing I did, was writing in the "(void)viewDidLoad" method of my ViewController a default username, a default password, storing and trying to retrieve them on a second run of my Application.
This should have been a piece of cake but I've found out that my application was crashing. This is the code I used:
- (void)viewDidLoad{
[super viewDidLoad];
//Keychain wrapper definition
KeychainItemWrapper *keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:@"YourAppLogin" accessGroup:nil];
//Getting DATA:
NSLog(@"Retrieving User DATA");
password = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
username = [keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];
NSLog(@"pwd = %@",password);
NSLog(@"user = %@",username);
//Setting DATA:
[keychainItem setObject:@"password you are saving" forKey:(__bridge id)(kSecValueData)];
[keychainItem setObject:@"username you are saving" forKey:(__bridge id)(kSecAttrAccount)];
}
Xcode was giving me an NSInternalInconsistencyException uncaught. Playing around with the code I realized that the problem occurred only when setting a new password (at the first run of my App or after a reset of the keychain) and, here comes the strange part, only if I set my password before the username. So rewriting the code swapping the
//Setting DATA
[keychainItem setObject:@"username you are saving" forKey:(__bridge id)(kSecAttrAccount)];
[keychainItem setObject:@"password you are saving" forKey:(__bridge id)(kSecValueData)];
}
solved my problem. Can anybody explain me why?
Finally I would like to ask if retrieving my password in a second run of my application will result in a encrypted version of it. This because i tried to get my password in 2 ways:
1) I got it right after storing it
//saving DATA
[keychainItem setObject:@"username you are saving" forKey:(__bridge id)(kSecAttrAccount)];
[keychainItem setObject:@"password you are saving" forKey:(__bridge id)(kSecValueData)];
//getting DATA:
username = [keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];
password = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSLog(@"\nUser: %@ \nPassword: %@",username,password);
the result was
User: username you are saving
Password: password you are saving
2)I got my password in a second run putting the setting part under comment
//saving DATA
//[keychainItem setObject:@"username you are saving" forKey:(__bridge id)(kSecAttrAccount)];
//[keychainItem setObject:@"password you are saving" forKey:(__bridge id)(kSecValueData)];
//getting DATA:
username = [keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];
password = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSLog(@"\nUser: %@ \nPassword: %@",username,password);
the result was
User: username you are saving
Password: <70617373 776f7264 20796f75 20617265 20736176 696e67>
So is this a encrypted version of my password or what???
Thank you
Upvotes: 0
Views: 1632
Reputation: 167
I haven't understood why putting in the Keychain the password before the username makes the app crash, but I learned that, in order to get the password back from the keychain you have to store it first in a NSData, you should do so:
NSData *pwd = [keychainItem objectForKey:(__bridge id)(kSecValueData)];
password = [[NSString alloc] initWithData:pwd encoding:NSUTF8StringEncoding];
Upvotes: 1