views:

611

answers:

5

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.

+3  A: 

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?

Ronald
That wouldn't stop anyone from reading them.
Chuck
True. But you wouldn't be able to use the md5 string for authentication or whatever the passwords are being using for.
Ronald
It would stop them reading the password but allow access to the hash which is different.
Roger Nolan
The strings do need to be randomly accessed so need to be able to convert them back to a usable state.
rjstelling
+10  A: 

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 :-)

Graham Lee
+3  A: 

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.

Roger Nolan
you missed stringWithCapacity: line 8
nico
+1  A: 

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.

+2  A: 

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.

source for GDataServiceBase.m

// 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.

Brian Chapados
Thanks Brian, originally this is what I was referring to but Graham Lee's answer does better solve my problem. But this is also very useful +1
rjstelling