Конфиденциальные данные: NSString VS NSMutableString (iPhone) - PullRequest
6 голосов
/ 02 марта 2010

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

Ответы [ 4 ]

4 голосов
/ 02 марта 2010

Я бы боялся, что 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 голос
/ 25 января 2013

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

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

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

1 голос
/ 25 января 2013

Вам нужно стереть указатель c нулями с помощью функции memset, однако вызов memset может быть оптимизирован компилятором, см. Как правильно удалить конфиденциальные данные из памяти в iOS?

Так что код может быть примерно таким:

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

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

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

0 голосов
/ 13 октября 2015

Начиная с 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);
}
...