2010-03-02 1 views
6

У меня есть некоторые конфиденциальные данные, которые я хочу очистить сразу после использования. В настоящее время конфиденциальные данные находятся в форме NSString. NSString в моем понимании неизменен, что означает, что я не могу действительно очистить данные. NSMutableString кажется более подходящим, хотя, поскольку он изменен и имеет методы, такие как replaceCharactersInRange и deleteCharactersInRange. Я не знаю деталей реализации, поэтому я задаюсь вопросом, будет ли NSMutableString служить моей цели?Чувствительные данные: NSString VS NSMutableString (iPhone)

ответ

3

Я боялся, что 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); 
+0

Спасибо, это именно то, о чем я просил! – AOO

+1

'NSString' может создавать дополнительные копии буфера, переданного для собственных целей. Пример: вызов '- [NSString UTF8String]' создаст дополнительную внутреннюю копию, которая будет выпущена, но не будет удалена, когда будет выполняться 'NSString'. Если вы хотите гарантировать, что конфиденциальные данные будут очищены, сделайте * NOT * использовать 'NSString'. – rpetrich

1

Вам нужно стереть гр указатель с нулями с функцией MemSet однако вызов 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]); 

Но будьте осторожны, очищая основной указатель c NSString. Например, на устройстве, если строка содержит слово «пароль», базовый c-указатель просто повторяет или указывает на тот же адрес, который используется системой, и вы потерпите крах, пытаясь стереть эту область памяти.

Чтобы быть в безопасности, вы можете использовать массив символов, а не указатель символов, чтобы хранить ваши чувствительные строки и уничтожить их после того, как они не будут помещены в объект NSString.

1

Если злоумышленник может читать содержимое памяти, вы находитесь за пределами hosed.

-release Строка и сделайте с ней. Невозможно узнать, удалили ли вы какие-либо возможные копии строки в разных кешах (например, если вы нарисуете ее на экране и т. Д.).

У вас, вероятно, есть гораздо более серьезные проблемы с безопасностью, о которых нужно беспокоиться.

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