何时使用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; }