【问题标题】:OBJ-C wipe NSData content before nullifying itOBJ-C 在取消之前擦除 NSData 内容
【发布时间】:2019-01-19 06:04:09
【问题描述】:

出于安全原因,我们需要始终从内存中擦除敏感数据。 通常这不是我在 IOS 中看到的,但对于需要扩展安全性的应用程序来说,这非常重要。

如果 NSData 和 NSString 对象通常需要擦除的数据(指向 nil 不会擦除数据,这是一个安全漏洞)

我已经设法用下面的代码擦除了我的 NSStrings(当密码是 NSString 时):

unsigned char *charPass;
if (password != nil) {
    charPass = (unsigned char*) CFStringGetCStringPtr((CFStringRef) password, CFStringGetSystemEncoding());
    memset(charPass, 0, [password length]);
    password = nil;
}
  • 关于此实现的重要说明:您必须在调用 charPass 之前检查 NULL,否则它可能会崩溃。不能保证 CFStringGetCStringPtr 会返回一个值!

当密码为 NSData 时,它假设更加严格并且下面的代码假设可以工作:

memset([password bytes], 0, [password length]);

但这给了我一个编译错误:

没有匹配的函数调用'memset'

我找不到一种解决方法来指向密码地址并像我对字符串所做的那样擦除那里的字节(字节方法应该让我按照我的理解做到这一点,但由于某种原因它无法编译我想不通)

有人对此有想法吗?

10 倍

【问题讨论】:

    标签: ios objective-c nsstring nsdata memset


    【解决方案1】:

    你的字符串释放器是脆弱的。你写:

    关于这个实现的重要说明:你必须在调用 charPass 之前检查 NULL,否则它可能会崩溃。不能保证 CFStringGetCStringPtr 会返回一个值!

    这是记录在案的行为,因为CFString(因此NSString)确实保证您可以直接访问其内部缓冲区。你没有说你是如何处理这种情况的,但如果你不擦除内存,你可能会遇到安全问题。

    如果你确实得到了一个有效的指针,那么你使用了错误的字节数。调用[password length] 返回:

    接收器中 UTF-16 代码单元的数量。

    这与字节数不同。然而CFStringGetCStringPtr 返回:

    指向 C 字符串的指针,如果 theString 的内部存储不允许有效返回,则为 NULL。

    如果你有一个 C 字符串,你可以使用 C 库函数 strlen() 来查找它的长度。

    要解决CFStringGetCStringPtr 返回NULL 的情况,您可以自己创建字符串作为CFString 并提供自定义CFAllocater。您不需要自己编写完整的分配器,而是可以基于系统构建一个。您可以获得默认分配器CFAllocatorContext,它将返回系统使用的函数指针。然后,您可以基于 CFAllocatorContext 创建一个新的 CFAllocator,它是默认的副本,除非您更改了 deallocatereallocate 指向您根据默认 @987654336 实现的函数的指针@、reallocatedeallocate,但也可以适当地调用 memset 以清除内存。

    一旦您完成了安全擦除,就可以确保这些自定义创建的 CFString 对象(也称为 NSString 对象)在您的应用退出之前被释放。

    您可以在Memory Management Programming Guide for Core Foundation 中找到有关CFAllocatorCFAllocatorContext 等的信息。

    这给我们带来了您的实际问题,如何将NSData 归零。幸运的是,NSData 对象是 CFData 对象,CFDataCFDataGetBytePtrCFStringGetCStringPtr 不同,保证直接从文档返回指向实际字节的指针:

    此函数保证返回指向CFData 对象内部字节的指针。 CFDataCFString 不同,不会隐藏其内部存储。

    因此,遵循CFString 模式的代码将在这里工作。请注意,使用NSDatabytes 在文档中保证调用CFDataGetBytePtr,例如它可以调用CFDataGetBytes 并返回一个副本字节,使用CFData 函数。

    HTH

    【讨论】:

    • 嗨@CRD,你是对的,我最终所做的是使用 NSMutableData 创建具有不同签名的相同方法,这样我就不会破坏现有的 API,如果有人需要额外的安全性,他们将使用更安全的方法,我可以在其中使用 memset 方法擦除内存。据我了解,没有真正的方法可以从内存中擦除 NSStrings 字节。 10 倍。
    【解决方案2】:

    虽然我不能保证这样做的实际安全性,但您的问题是 NSDatabytes 方法返回 const void *

    https://developer.apple.com/documentation/foundation/nsdata/1410616-bytes?language=objc

    如果需要,您可以将其转换为 void *

    memset((void *)[password bytes], 0, [password length]);
    

    如果您使用NSMutableData,则不必这样做。

    【讨论】:

    • 嗨@Mobile Ben,自己想办法,然后看到你回答...... 10x
    猜你喜欢
    • 1970-01-01
    • 2012-12-12
    • 1970-01-01
    • 2010-11-27
    • 2016-06-22
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 2016-06-05
    相关资源
    最近更新 更多