OBJ-C在清除NSData内容之前先将其清除

时间:2018-08-12 07:08:03

标签: ios objective-c nsstring nsdata memset

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

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

我设法使用下面的代码(当密码为NSString时)擦除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”

我找不到解决办法来指向密码地址并像在字符串上那样擦拭字节(bytes方法应该让我根据我的理解进行操作,但是由于某种原因它不能编译我不知道)

有人对此有想法吗?

10x

2 个答案:

答案 0 :(得分:1)

虽然我不能保证这样做的实际安全性,但您的问题是NSData的{​​{1}}方法返回了bytes

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

如果需要,可以将其强制转换为const void *

void *

如果您使用memset((void *)[password bytes], 0, [password length]); ,则不必这样做。

答案 1 :(得分:1)

您的字符串分配器是易碎的。您写道:

  

此实现的重要说明:您必须在调用charPass之前检查NULL否则它可能会崩溃。无法保证CFStringGetCStringPtr将返回一个值!

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

如果您确实获得了有效的指针,则使用的字节数错误。呼叫[password length]返回:

  

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

,它与字节数不同。但是CFStringGetCStringPtr返回:

  

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

如果您有C字符串,则可以使用C库函数strlen()来查找其长度。

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

完成安全清除后,可以确保在应用退出之前,重新分配了这些自定义创建的CFString对象(也称为NSString对象)。

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

这给我们带来了您的实际问题,如何将NSData置零。在这里,您很幸运,NSData对象是CFData对象,并且CFData的{​​{1}}与CFDataGetBytePtr不同,可以保证返回指向该对象的指针。实际字节,直接来自文档:

  

保证该函数返回指向CFStringGetCStringPtr对象内部字节的指针。 CFDataCFData不同,它不会隐藏其内部存储空间。

因此遵循CFString模式的代码将在这里工作。请注意,文档中不能保证使用CFString的{​​{1}}来调用NSData,例如,可以调用bytes并返回< em> copy 字节,请使用CFDataGetBytePtr函数。

HTH