【问题标题】:Sensitive data: NSString VS NSMutableString (iPhone)敏感数据:NSString VS NSMutableString (iPhone)
【发布时间】:2010-03-02 09:15:35
【问题描述】:

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

【问题讨论】:

    标签: ios iphone nsstring nsmutablestring


    【解决方案1】:

    我担心 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);
    

    【讨论】:

    • 谢谢,这正是我想要的!
    • NSString 可能会为自己的目的创建传入缓冲区的其他副本。示例:调用-[NSString UTF8String] 将创建一个额外的内部副本,该副本在NSString 执行时会被释放但不会被清除。如果您想确保敏感数据被清理干净,请NOT使用NSString
    • 这不起作用。分配后添加到字符串会在内存中创建内部副本,使用 memset 时不会清除这些副本
    【解决方案2】:

    您需要使用 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 对象中。

    【讨论】:

      【解决方案3】:

      如果攻击者可以读取内存中的内容,那么你就完蛋了。

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

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

      【讨论】:

        【解决方案4】:

        从iOS9开始,从下面的sn-p获得的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);
        }
        

        【讨论】:

          猜你喜欢
          • 2013-05-26
          • 1970-01-01
          • 2019-01-12
          • 2020-11-10
          • 2016-09-12
          • 1970-01-01
          • 1970-01-01
          • 2011-05-15
          • 2019-12-16
          相关资源
          最近更新 更多