2010-03-02 77 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'出現時會被釋放但不會被清除。如果你想保證敏感數據被清除,不要*使用'NSString'。 – rpetrich

1

您需要擦拭用memset的功能。然而memset的呼叫可以被編譯器優化掉了零的C指針,看到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對象後擦除它們。

1

如果攻擊者可以讀取內存的內容,那麼你已經沒有了。

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