开发者

Sensitive data: NSString VS NSMutableString (iPhone)

I have some sensitive data I want to clear directly after use. Currently, the sensitive data is in the form of NSString. NSString is in my understandi开发者_如何学编程ng immutable, meaning that I can't really clear the data. NSMutableString seems more appropriate, though, as it is mutable and has methods like replaceCharactersInRange and deleteCharactersInRange. I have no knowledge of the implementation details so I wonder if NSMutableString would serve my purpose?


I would be afraid NSMutableString would try to optimize and leave the string in memory. If you want more control try allocating your own memory then create an NSString with it. If you do that you can overwrite the memory before you release it.

char* block = malloc(200);
NSString* string = [[NSString alloc] initWithBytesNoCopy:length:encoding:freeWhenDone];
//use string
memset(block, 0, 200);// overwrite block with 0
[string release];
free(block);


You need to wipe the c pointer with zeros with a memset function however a memset call can be optimized out by the compiler, see What is the correct way to clear sensitive data from memory in iOS?

So the code could be something like this:

NSString *string = @"hi";
unsigned char *stringChars = (unsigned char *)CFStringGetCStringPtr((CFStringRef)string, CFStringGetSystemEncoding());
safeMemset(stringChars, 0, [string length]);

But be careful clearing the underlying c pointer of an NSString. On a device for example, if the string contains the word "password", the underlying c pointer just reuses or points to the same address as used by the system and you will crash by trying to wipe this area of memory.

To be safe you may want to use a char array, not the char pointer, to store your sensitive strings and wipe them after without ever putting it into an NSString object.


If an attacker can read the contents of memory, you are beyond hosed.

-release the string and be done with it. There's no way to know if you've deleted any possible copies of the string in various caches (such as if you draw it to screen, etc).

You probably have much more significant security issues to worry about.


As of iOS9, inner pointer of NSString obtained from the snippet below has become read-only and generates bad access when trying to set the bytes.

unsigned char *stringChars = (unsigned char *)CFStringGetCStringPtr((CFStringRef)string, CFStringGetSystemEncoding());

It is possible with NSMutableString but then if you have another NSString source, say from a textfield, that source will still be in memory and you're still out of luck.

If you are creating a new NSString, The best way is implement your own String class with underlying byte array. Provide a method to create NSString copies using the underlying byte array as the inner pointer.:

-(NSString *)string
{
    return [[NSString alloc] initWithBytesNoCopy:_buff length:_length encoding:NSUTF8StringEncoding freeWhenDone:NO];
}

// Will prematurely wipe data and all its copies when called
- (void)clear
{
    // Volatile keyword disables compiler's optimization
    volatile unsigned char *t = (unsigned char *)_buff;
    int len = _length;
    while (len--) {
        *t++ = 0;
    }
}

// In case you forget to clear, it will cleared on dealloc
- (void)dealloc
{
    [self clear];
    free(_buff);
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜