NSSecureCoding 与钥匙串

Posted

技术标签:

【中文标题】NSSecureCoding 与钥匙串【英文标题】:NSSecureCoding vs. Keychain 【发布时间】:2018-09-16 12:59:22 【问题描述】:

我了解使用“NSSecureCoding”可以将数据安全地存储到磁盘,类似于钥匙串作为安全存储信息的地方。

我还了解钥匙串具有在同一提供商的应用程序之间共享的优势。如果有人会忽略钥匙串共享功能,是否可以说,与 NSSecureCoding 相比,将数据存储在钥匙串中同样安全?

我有一个用户对象

class User: NSObject, NSSecureCoding 

private enum CodingKeys: String, CodingKey 
    case test


public static var supportsSecureCoding: Bool 

    return true


override init() 

var test: String = "teeees"


func encode(with aCoder: NSCoder) 

    aCoder.encode(self.test as NSString)


required init?(coder aDecoder: NSCoder) 

    test = aDecoder.decodeObject(of: NSString.self, forKey: CodingKeys.test.rawValue)! as String


我存档了

let user = User()
    let data = NSKeyedArchiver.archivedData(withRootObject: user)

    try! data.write(to: DocumentHelper.cashURLForID(id: "TTYYUU"))

TTYYUU的内容是:

6270 6c69 7374 3030 d401 0203 0405 0615 1658 2476 6572 7369 6f6e 5824 6f62 6a65 6374 7359 2461 7263 6869 7665 7254 2474 6f70 1200 0186 a0a4 0708 0d0e 5524 6e75 6c6c d209 0a0b 0c52 2430 5624 636c 6173 7380 0280 0356 7465 6565 6573 d20f 1011 125a 2463 6c61 7373 6e61 6d65 5824 636c 6173 7365 735f 1011 5365 6375 7265 436f 6469 6e67 2e55 7365 72a2 1314 5f10 1153 6563 7572 6543 6f64 696e 672e 5573 6572 584e 534f 626a 6563 745f 100f 4e53 4b65 7965 6441 7263 6869 7665 72d1 1718 5472 6f6f 7480 0108 111a 232d 3237 3c42 474a 5153 555c 616c 7589 8ca0 a9bb bec3 0000 0000 0000 0101 0000 0000 0000 0019 0000 0000 0000 0000 0000 0000 0000 00c5

有人可以展示解码原始信息的方法吗,它说格式是“NSPropertyList Binary Format_v1_0”,有人可以展示如何从这个二进制文件中提取“teeees”吗?

【问题讨论】:

为什么你认为 MSSecureCoding 允许securely store data to disk?你对此有什么参考吗? 除了名字没有参考?安全编码?我可能是错的,我的问题是它是否会以人类/黑客不易阅读的方式对信息进行编码 不,在这个意义上,NSSecureCoding 并不比普通的NSCoding 更安全(数据格式仍然可读)——当你想从磁盘读回数据并且是试图通过不信任存档的内容来防止任意代码执行。将数据写入钥匙串可以使其通常不被窥探。 至于您的第二个问题(已编辑):您可以通过将其写入磁盘并使用plutil 转换格式或创建NSKeyedArchiver 来查看XML 格式的plist 数据,将其.outputFormat 设置为.xml,归档根对象,并将.encodedData 视为UTF-8 字符串。 @Arash 查看我关于您发布的二进制数据的更新答案。 【参考方案1】:

一个类不是“安全的”,因为它的名称中包含此文本。没有详细描述如何、为什么(例如加密、完整性保护......)及其限制的安全性是无用的。该文档明确指出它仅是安全的against object substitution attacks

这完全意味着替换文件或更改内容并不容易。

从未在任何地方声明它可用于“将数据安全地存储到磁盘”。因此,NSSecureCoding 与专用于“为一个或多个用户提供密码、密钥、证书和注释的安全存储”的 Keychain 相比,用于完全不同的用例。

编辑:查看您添加的编码数据示例,它包含大量纯文本数据,包括teeees。您可以使用任何十六进制编辑器或strings 命令查看它。

【讨论】:

感谢您的回答,我遇到了“对象替换攻击”一词,我想知道我是否有一个具有“名称”属性的“用户”对象,我会使用 NSSecureCoding 将其保存到磁盘,基于根据您的评论,攻击者仍然能够获取文件,更改名称属性的内容,并且 NSSecureCoding 仍然能够解码用户对象,但使用新的被黑名称。这种情况是真的吗?如果这是真的,那么 NSCoding 将如何使其安全?它是否仅在对象架构完全改变的情况下使其安全?与其他电话财产一起存档? @Arash 很少有东西(加密存储不足)可以防止攻击者弄乱存档本身;相反,NSSecureCoding 设置了如何读取存档的限制。通过在代码中指定您期望的类型,您可以防止攻击者将您的User 替换为您不期望的完全任意对象。如果您[decoder decodeObjectOfClass:[User class] forKey:...,启用安全编码会阻止解码,例如,NSAttributedString(或运行时会出现的任何类)。 基本上,它可以防止大多数情况下盲目相信存档中的内容,而是将合约放入代码中。在解码过程中,您还需要做更多的工作,以确保事情确实符合您的期望(一些额外的类型验证、输入验证等),但这是这里的主要好处。

以上是关于NSSecureCoding 与钥匙串的主要内容,如果未能解决你的问题,请参考以下文章

钥匙串警告无法修改“系统根”钥匙串[关闭]

在 iOS 上存储身份验证令牌 - NSUserDefaults 与钥匙串?

苹果密码钥匙串在哪里

MacBook钥匙串怎么关闭

想使用登录钥匙串卡死

Mac钥匙串有啥用?钥匙串访问是啥