出于安全原因,我们需要始终擦除内存中的敏感数据。 通常,这不是我在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;
}
当密码是NSData时,它应该向前移动更多,并且下面的代码应该可以工作:
memset([password bytes], 0, [password length]);
但这给了我一个编译错误:
没有匹配功能可调用“ memset”
我找不到解决办法来指向密码地址并像在字符串上那样擦拭字节(bytes方法应该让我根据我的理解进行操作,但是由于某种原因它不能编译我不知道)
有人对此有想法吗?
10x
答案 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
,它是默认副本的副本,只是您已将deallocate
和reallocate
指针更改为您拥有的函数根据默认的allocate
,reallocate
和deallocate
实现,但也适当调用memset
以清除内存。
完成安全清除后,可以确保在应用退出之前,重新分配了这些自定义创建的CFString
对象(也称为NSString
对象)。
您可以在Memory Management Programming Guide for Core Foundation中找到有关CFAllocator
,CFAllocatorContext
等的信息。
这给我们带来了您的实际问题,如何将NSData
置零。在这里,您很幸运,NSData
对象是CFData
对象,并且CFData
的{{1}}与CFDataGetBytePtr
不同,可以保证返回指向该对象的指针。实际字节,直接来自文档:
保证该函数返回指向
CFStringGetCStringPtr
对象内部字节的指针。CFData
与CFData
不同,它不会隐藏其内部存储空间。
因此遵循CFString
模式的代码将在这里工作。请注意,文档中不能保证使用CFString
的{{1}}来调用NSData
,例如,可以调用bytes
并返回< em> copy 字节,请使用CFDataGetBytePtr
函数。
HTH