敏感数据:NSString VS NSMutableString(iPhone)

时间:2010-03-02 09:15:36

标签: ios iphone nsstring nsmutablestring

我想要在使用后直接清除一些敏感数据。目前,敏感数据采用NSString的形式。 NSString在我的理解中是不可变的,这意味着我无法真正清除数据。但是,NSMutableString似乎更合适,因为它是可变的并且具有replaceCharactersInRange和deleteCharactersInRange等方法。我不知道实现细节,所以我想知道NSMutableString是否符合我的目的?

4 个答案:

答案 0 :(得分:4)

我担心NSMutableString会尝试优化并将字符串保留在内存中。如果你想要更多的控制尝试分配你自己的内存,然后用它创建一个NSString。如果这样做,您可以在释放之前覆盖内存。

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

答案 1 :(得分:1)

您需要使用memset函数用零擦除c指针,但编译器可以优化memset调用,请参阅What is the correct way to clear sensitive data from memory in iOS?

所以代码可能是这样的:

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

但要小心清除NSString的底层c指针。例如,在设备上,如果字符串包含单词“password”,则底层c指针只是重用或指向系统使用的相同地址,并且您将通过尝试擦除此内存区域而崩溃。

为了安全起见,您可能希望使用char数组而不是char指针来存储敏感字符串并在不将其放入NSString对象之后擦除它们。

答案 2 :(得分:1)

如果攻击者可以读取内存的内容,那么你就无法使用。

-release字符串并完成它。没有办法知道你是否在各种缓存中删除了任何可能的字符串副本(例如,如果你将它绘制到屏幕上等)。

您可能需要担心更重要的安全问题。

答案 3 :(得分:0)

从iOS9开始,从下面的代码段获取的NSString的内部指针在尝试设置字节时变为只读并生成错误访问

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

可以使用NSMutableString但是如果你有另一个NSString源,比如说来自文本字段,那么该源仍然会在内存中,你仍然不幸。

如果要创建新的NSString,最好的方法是使用基础字节数组实现自己的String类。提供一种使用基础字节数组作为内部指针创建NSString副本的方法。:

-(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);
}