Reputation: 25665
I need to store passwords in NSString
objects; however, I would like some way to obfuscate them, so they cannot be read directly from memory.
This is a Mac OS X (10.5) application, but a solution that also works on iPhone would be much appreciated.
Upvotes: 8
Views: 2475
Reputation: 4916
I think the poster is referring to obfuscating the password in memory, so you can't just read the contents of the ivar out of memory. The GData library from google has some useful code for XORing passwords stored as NSMutableData in instance variables.
// XorPlainMutableData is a simple way to keep passwords held in heap objects
// from being visible as plain-text
static void XorPlainMutableData(NSMutableData *mutable) {
// this helps avoid storing passwords on the heap in plaintext
const unsigned char theXORValue = 0x95; // 0x95 = 0xb10010101
unsigned char *dataPtr = [mutable mutableBytes];
NSUInteger length = [mutable length];
for (NSUInteger idx = 0; idx < length; idx++) {
dataPtr[idx] ^= theXORValue;
}
}
You can save/restore the password using XOR (see #password and #setUserCredentialsWithUsername:password: methods in the same file). XOR is not high-tech encryption, but it's good enough to deter casual snooping. In the case of the GData client where you might have a long-lived service/manager object in an application that retains a reference to the password data, I think this is a reasonable approach.
Upvotes: 2
Reputation:
A very useful set of code for storing and retrieving passwords to and from the keychain can be found here:
http://log.scifihifi.com/post/55837387/simple-iphone-keychain-code
I've used it, and it worked well.
Upvotes: 1
Reputation: 17170
On the iPhone, the sandbox will stop anyone accessing your passwords. on the desktop it's not so easy.
You should store the passwords as hashes rather than cleartext. I believe this will get you the results you want without affecting functionality. The only think you will never be able to do is access the cleartext password again - if you want to analyse it for strength or pass it on to another service. In general though, hashes will not sacrifice functionality.
The following code takes a password in rawPassword and stores its SHA-1 hash in passwordHash.
#import <CommonCrypto/CommonDigest.h>
const char* utf8PasswordRepresentation = [rawPassword UTF8String];
unsigned char * rawHash = malloc(CC_SHA1_DIGEST_LENGTH);
CC_SHA1(utf8PasswordRepresentation, strlen(utf8PasswordRepresentation), rawHash);
NSMutableString* passwordHash = [NSMutableString CC_SHA1_DIGEST_LENGTH*2];
for (int i = 0 ; i< CC_SHA1_DIGEST_LENGTH; i++)
[passwordHash appendFormat:@"%02x" , rawHash[i]];
Note that there is no memory management here.
Check out the wikipedia entry for an explanation of password hashing.
There are many versions of this same code around the intertubes.
Upvotes: 3
Reputation:
If you use the keychain for storing passwords then instead of passing strings around you could handle the opaque keychain SecKeychainItemRefs
, only retrieving plaintext at the point where it's required. That's also the way Mac users expect their passwords to be dealt with. Unfortunately without knowing why you "need to store passwords in NSString
objects" I can't tell if that's really true :-)
Upvotes: 12
Reputation: 16383
Couldn't you just md5 them before putting them in the NSString? Then when you go to test, md5 the input string and compare that with what is stored?
Upvotes: 3