敏感数据:NSString VS NSMutableString (iPhone)

发布于 2024-08-23 15:05:36 字数 219 浏览 8 评论 0原文

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

I have some sensitive data I want to clear directly after use. Currently, the sensitive data is in the form of NSString. NSString is in my understanding immutable, meaning that I can't really clear the data. NSMutableString seems more appropriate, though, as it is mutable and has methods like replaceCharactersInRange and deleteCharactersInRange. I have no knowledge of the implementation details so I wonder if NSMutableString would serve my purpose?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

妄断弥空 2024-08-30 15:05:36

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

I would be afraid NSMutableString would try to optimize and leave the string in memory. If you want more control try allocating your own memory then create an NSString with it. If you do that you can overwrite the memory before you release it.

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);
爱*していゐ 2024-08-30 15:05:36

您需要使用 memset 函数用零擦除 c 指针,但是编译器可以优化 memset 调用,请参阅 从 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 对象中。

You need to wipe the c pointer with zeros with a memset function however a memset call can be optimized out by the compiler, see What is the correct way to clear sensitive data from memory in iOS?

So the code could be something like this:

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

But be careful clearing the underlying c pointer of an NSString. On a device for example, if the string contains the word "password", the underlying c pointer just reuses or points to the same address as used by the system and you will crash by trying to wipe this area of memory.

To be safe you may want to use a char array, not the char pointer, to store your sensitive strings and wipe them after without ever putting it into an NSString object.

层林尽染 2024-08-30 15:05:36

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

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

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

If an attacker can read the contents of memory, you are beyond hosed.

-release the string and be done with it. There's no way to know if you've deleted any possible copies of the string in various caches (such as if you draw it to screen, etc).

You probably have much more significant security issues to worry about.

老旧海报 2024-08-30 15:05:36

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

As of iOS9, inner pointer of NSString obtained from the snippet below has become read-only and generates bad access when trying to set the bytes.

unsigned char *stringChars = (unsigned char *)CFStringGetCStringPtr((CFStringRef)string, CFStringGetSystemEncoding());

It is possible with NSMutableString but then if you have another NSString source, say from a textfield, that source will still be in memory and you're still out of luck.

If you are creating a new NSString, The best way is implement your own String class with underlying byte array. Provide a method to create NSString copies using the underlying byte array as the inner pointer.:

-(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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文