Ios 何时使用NSSecureCodeding

Ios 何时使用NSSecureCodeding,ios,objective-c,security,nscoding,nssecurecoding,Ios,Objective C,Security,Nscoding,Nssecurecoding,我正在学习苹果在iOS 6中引入的协议 根据我到目前为止的理解,应该在类对自身实例进行编码/解码时使用它,以防止替换攻击 我想知道在其他情况下使用它是否合适 具体地说,如果一个类通过编码/解码其实例变量而不是其自身的整个实例来符合NSCoding,那么仍然建议实现NSSecureCoding 编辑 假设我有一个类正在实现NSCoding,如下所示 - (void)encodeWithCoder:(NSCoder *)encoder { [encoder encodeObject:sel

我正在学习苹果在iOS 6中引入的协议

根据我到目前为止的理解,应该在类对自身实例进行编码/解码时使用它,以防止替换攻击

我想知道在其他情况下使用它是否合适

具体地说,如果一个类通过编码/解码其实例变量而不是其自身的整个实例来符合
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:

当您调用
decodeObjectForKey:
对实例变量进行解码时,在您可以验证其类类型之前仍然会构造该对象(引入
NSSecureCoding
的原因)


因此,我假设同样的规则仍然适用于这里,因此在解码实例变量时,最好使用
decodeObjectOfClass:forKey
而不是
decodeObjectForKey:

以下是我阅读文档和帖子的感受

用于将Calss图灵为二进制。这既可以用于将数据归档到磁盘,也可以用于进程间通信。归档到磁盘是相对安全的,但是,进程间通信是有风险的,因为您可能不信任提供数据的源进程

因此,首先,如果您只是使用
NSCoding
将对象持久写入磁盘,那么您就不必担心
NSSecureCoding
(不过它很容易实现,请参见下文)

具体地说,如果一个类通过编码/解码其实例变量(而不是其自身的整个实例)来符合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 (e.g. save to an property / ivar)
   }
   return self;
}

+ (BOOL)supportsSecureCoding {
   return YES;
}
具体地说,如果一个类通过编码/解码其实例变量(而不是其自身的整个实例)来符合NSCoding,那么实现NSSecureCoding是否仍然可取

这取决于应用程序的需要。对于任何旧的应用程序,使用普通NSCoding将内容持久化到磁盘是可以的,因为正在写入的信息以及应用程序本身本质上是(不应该)敏感的。但是,假设你是一家发布申请的银行。您可以选择将某些帐户信息或API密钥持久化到磁盘,以便与服务通信、验证用户身份等。您可能不需要整个对象,但这并不重要。NSCoder不关心正在读取的内容,只关心它能够读取并正确地执行其工作。这是一个问题

就安全性而言,使用-decodeObjectOfClass:forKey:相对于-decodeObjectForKey:,有什么好处吗

是的,非常喜欢。事实上,你依赖NSCODER来序列化/反序列化一个对象(更不用说正确的对象)是一个巨大的攻击向量。一旦黑客以NSCoder使用的格式修改了信息(类似plist的结构,可供人阅读,非常容易理解),那么就无法保证你得到的是你输入的内容。NSCoder不关心是否有人决定切换存档中包含的类,因此您正在构建恶意类的对象,运行时也不关心。事实上,一个足够聪明的黑客会向应用程序中注入补丁,以确保反序列化对象会导致某种未定义状态(堆栈溢出),这可能被用来利用整个应用程序


decodeObjectOfClass:forKey:
允许您强制NSCoder在反序列化方面更加智能,并修补了一个非常大的漏洞。这并不是说在没有
NSSecureCoding
的情况下,您永远不应该使用NSCoder,而是说您必须明智地了解在什么情况下使用它

我不知道答案,所以这个问题+1。所以我想我现在的问题是:如果所有内容都存档在磁盘上,并且不涉及XPC,那么是否值得将现有代码库转换为采用
NSSecureCoding
?它有什么优势吗?我的感觉是没有-我怀疑苹果在XPC内部使用它。也就是说,
if([class-conformsToProtocol:@protocol(NSSecureCoding)]&[class-supports-securecoding])与xpc-else-throwerr一起使用
Ok,为了完整起见,我在编辑的答案中发布了一个示例。谢谢你的回答谢谢你的回答。我在我的问题中添加了一个示例,您可能想看看。在大多数应用程序中,您是编码和解码数据的人,调用
decodeObjectOfClass:forKey:
而不是
decodeObjectForKey:
,并没有什么真正的好处。回答得很好,非常感谢。让事情更复杂一点,如果我也需要支持iOS5呢。我想检查返回对象的类是唯一的方法,不是吗?编写自己的类更容易。我知道现在有很多框架支持JSON机制的键值编码,或者只是用C语言重做。不管你想出什么,毫无疑问都会比NSCoderI的混乱更快、更稳定。恐怕我不太明白你所说的“编写你自己的”是什么意思。你自己的编码员?是的。有一百万种其他格式,还有一百万种其他序列化对象的方法,我相信你可以找到一种适合你的需要并且支持旧的IOS(特别是在另一种语言中)的方法