何时使用NSSecureCoding
我正在学习Apple在iOS 6中引入的NSSecureCoding
协议。
从我迄今为止的理解来看,每当一个类对自身的实例进行编码/解码时,就应该使用它来防止replace攻击。
我想知道在其他情况下使用它是否合适。
特别是如果一个类通过对其实例variables进行编码/解码来符合NSCoding
,而不是整个实例本身,那么实现NSSecureCoding
还是可取的吗?
编辑
假设我有一个像下面这样实现NSCoding
类
- (void)encodeWithCoder:(NSCoder *)encoder { [encoder encodeObject:self.aString forKey:@"aMeaningfulString"]; } - (id)initWithCoder:(NSCoder *)decoder { if((self = [super init])) { self.aString = [decoder decodeObjectForKey:@"aMeaningfulString"]; } return self; }
并且假设不涉及XPC。 这个类的实例将被存档在存储在磁盘上的plist中。
安全性方面,使用-decodeObjectOfClass:forKey:
与-decodeObjectForKey:
相反有什么好处吗?
特别是如果一个类通过对其实例variables进行编码/解码来符合NSCoding,而不是整个实例本身,那么实现NSSecureCoding还是可取的吗?
这取决于您的应用程序的需求。 对于任何旧的应用程序,用普通的NSCoding持久化磁盘是好的,因为正在编写的信息和应用程序本身是(不应该)在本质上是敏感的。 但是,假设您是银行发布申请。 您可以select持有一些帐户信息或API密钥到磁盘,以便您可以与您的服务进行通信,validation用户的身份等。您可能不希望整个对象,但这不重要。 NSCoder不关心正在被读取的内容,只是它可以读取并正确地执行它的工作。 这是个问题。
安全性方面,使用-decodeObjectOfClass:forKey:与-decodeObjectForKey:相反有什么好处吗?
是的,非常非常。 事实上,你依靠NSCoder序列化/反序列化一个对象(更不用说正确的对象)是一个巨大的攻击载体。 一旦黑客修改了NSCoder所使用格式的信息(一种类似plist的结构,这种结构既易于阅读,又非常易于使用),那么就无法保证你所得到的是你所input的内容。NSCoder并不关心有人决定切换档案中包含的类,所以你重新构造了一个恶意类的对象,运行时也没有。 事实上,一个足够聪明的黑客会在应用程序中注入一个补丁,以确保反序列化的对象会导致某种未定义的状态(堆栈溢出),这可能会被用来潜在地利用整个应用程序。
decodeObjectOfClass:forKey:
允许您强制NSCoder在反序列化方面更加智能化,并且修补了一个非常大的漏洞。 这并不是说你不应该在没有 NSSecureCoding的情况下使用NSCoder,而是你必须对使用NSCoder的情况NSSecureCoding
了解。
当你调用decodeObjectForKey:
来解码一个实例variables的时候,这个对象仍然是可以validation它的类types(之所以引入NSSecureCoding
的原因)。
所以我假设这里仍然应用相同的规则,因此在解码实例variables时,最好使用decodeObjectOfClass:forKey
而不是decodeObjectForKey:
。
这是我阅读文档和NSHipsters后的感觉。
你使用NSCoding
来把你的calsses变成二进制。 这是为了将数据build立到磁盘或进程间通信。 归档到磁盘是相对安全的,但是,进程间通信是有风险的,因为您可能不相信给您数据的源进程。
所以,首先,如果您只是使用NSCoding
将对象持久地写入磁盘,那么您不必担心NSSecureCoding
(但是它的实现非常容易,请参见下文)
特别是如果一个类通过对其实例variables进行编码/解码来符合NSCoding,而不是整个实例本身,那么实现NSSecureCoding还是可取的吗?
我不知道如何解码一个类的整个实例。 一个类是通过解码来自存档器的一些数据并对其进行解码来解码的。
- (id) initWithCoder:(NSCoder *)aDecoder { if (self = [super initWithCoder:aDecoder]) { // Old way //obj myUnsecureObj = [aDecoder decodeObjectForKey:@"myKey"]; // New way obj mySecureObj = [aDecoder decodeObjectOfClass:[MyClass class] forKey:@"myKey2"]; // Use mySecureObj (eg save to an property / ivar) } return self; } + (BOOL)supportsSecureCoding { return YES; }