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