OBJ-C 在取消它之前擦除 NSData 内容

OBJ-C wipe NSData content before nullifying it

出于安全原因,我们需要始终从内存中擦除敏感数据。 通常这不是我在 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;
}

当密码是 NSData 时它应该更严格,下面的代码应该可以工作:

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

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

No matching function for call to 'memset'

我找不到一个解决方法来指向密码地址并擦除那里的字节,就像我对字符串所做的那样(字节方法应该让我按照我的理解来做,但它不会编译一些我无法弄清楚的原因)

有人对此有想法吗?

10 倍

虽然我不能说明这样做的实际安全性,但您的问题是 NSDatabytes 方法 returns 和 const void *

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

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

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

如果您使用 NSMutableData,则不必执行此操作。

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

Big remark on this implementation: You HAVE to check for NULL before calling the charPass or it might crash. There is NO guarantee that CFStringGetCStringPtr will return a value!

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

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

The number of UTF-16 code units in the receiver.

这和字节数不一样。然而 CFStringGetCStringPtr returns:

A pointer to a C string or NULL if the internal storage of theString does not allow this to be returned efficiently.

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

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

完成后,安全擦除将归结为确保这些自定义创建的 CFString 对象,又名 NSString 对象,在您的应用程序退出之前被释放。

您可以在 Memory Management Programming Guide for Core Foundation.

中找到有关 CFAllocatorCFAllocatorContext 等的信息

这让我们想到了您的实际问题,如何将 NSData 归零。幸运的是,NSData 对象是一个 CFData 对象,并且 CFDataCFDataGetBytePtrCFStringGetCStringPtr 不同,它保证 return指向实际字节的指针,直接来自文档:

This function is guaranteed to return a pointer to a CFData object's internal bytes. CFData, unlike CFString, does not hide its internal storage.

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

HTH