使用适用于iOS的Keychain保护用户数据

在本文中,我将讨论使用Apple的钥匙串服务在iOS应用中安全地持久存储数据。 我将向您介绍Keychain Services API的功能,并说明通过实现包装程序在应用程序中开始使用Keychain功能的快速简便的方法。

钥匙串提供了一种安全的替代方法,可以使用NSUserDefaults,plist或类似方法来保存敏感数据,例如用户名和密码。

您可能已经知道,NSUserDefaults简单有效,可以将小的,简单的数据位(例如NSNumbers或NSStrings)保存到设备的文件系统中。 但是这些数据绝不能安全地存储,因为黑客可以很容易地从设备访问它。

苹果提供了Keychain Services API来解决此问题,并帮助开发人员构建可安全处理密码和其他敏感信息的应用程序。

Apple文档中将钥匙串定义为:

“……一个加密的容器,代表应用程序和安全服务安全地存储小块数据。”

“…只是存储在文件系统中的数据库。”

钥匙串之所以出色,是因为在将数据加密存储到文件系统之前,它会自动进行处理,因此无需浪费时间来构建加密算法。

可以将OS和iOS中的钥匙串配置为锁定。 锁定后,将无法访问和解密存储的钥匙串项目。 对于iOS,钥匙串在设备锁定时被锁定,在设备解锁时被解锁。 即使已解锁,除非另有配置,只有创建项目的应用程序才能访问它。

钥匙串还提供其他功能,例如:在应用程序之间访问钥匙串项目。 通常,一个应用程序只能访问其创建的项目,但是可以进行配置以使其访问一组指定应用程序内的数据。

实施钥匙串API

使用钥匙串直接存储和检索数据并非易事。 不幸的是,Keychain API使用起来有些折磨。 它是用C编写的,需要大量耗时的配置。 幸运的是,Apple和许多其他贡献者创建了更高级别的包装程序,以隐藏令人费解的C代码,并从底层组织推动事情发展。

如果您想直接使用API​​,似乎这是最好的教程(尽管已经过时了):Ray Wenderlich在iOS 5中的基本安全性。

Apple API参考文档的这一页也是查看如何直接在您的应用程序中实现钥匙串的好方法。

包装器实施

苹果自己的钥匙串包装器称为GenericKeychain,可在Objective C和Swift的示例代码中找到。

其他包装器作为Cocoapods或Github和其他依赖项管理站点上的扩展库存在。

这是我推荐的一些钥匙扣包装纸:

  1. Jason Rendel(jrendel) 的Swift的 SwiftKeychainWrapper https://cocoapods.org/pods/SwiftKeychainWrapper或https://github.com/jrendel/SwiftKeychainWrapper
  2. Sam Soffes为目标C设计的SAMKeychain.https://cocoapods.org/pods/SAMKeychain
  3. 马修·帕尔默 Matthew Palmer)的《 锁匠》( Swift) (查看视频教程)https://github.com/matthewpalmer/Locksmith

大多数包装器都包含三种方法:一种添加钥匙串项,一种编辑钥匙串项,一种删除它,并通过一行代码即可访问和编辑钥匙串项。

分步指南:使用包装器实施钥匙串

让我们在Jason Rendel的SwiftKeychainWrapper的帮助下逐步实现对Swift程序的Keychain。

  1. 打开一个Xcode Swift项目,您想在其中存储敏感数据或使用Keychain进行测试。
  2. 转到包装的源文件。 在我们的情况下,它将是:https://cocoapods.org/pods/SwiftKeychainWrapper,为了使更新更容易,我们将使用cocoapod。 在这里,您可以查看包装器的文档,并查看如何将数据作为钥匙串项添加,编辑和删除。

在该包装器的文档中,我们可以看到建议的用法是保存字符串。 因此,对于此示例,我们将保存一个假定的密码。

3.为您的项目创建一个pod文件,并添加最新的SwiftKeychainWrapper Cocoapod,如下所示:

保存并记住在命令行中为您的项目执行“ pod安装”。

4.打开项目的工作区文件。

在实际的应用程序中,您可以通过各种方式接收敏感字符串,无论是从请求到服务器的用户名和密码请求,还是从用户输入信息的文本字段。

对于我们的示例,我们将使它成为一个简单的文本字段,该字段收集要存储在钥匙串中的密码字符串。

转到情节提要,并设置带有文本字段和一个按钮的视图控制器,如下所示:

将此视图控制器设置为与视图控制器类相对应。

然后,使IBOutlet将文本字段连接到视图控制器,并使IBAction连接按钮。 您的视图控制器类应如下所示:

这意味着字符串已保存到钥匙串!

6.要从钥匙串中检索字符串,让我们设置另一个按钮。

除了将检索到的字符串打印到控制台外,此按钮不会执行任何操作。

连接其IBAction并使用所需的方法检索字符串。 见下文。

将以下代码添加到retrievePasswordButtonTapped方法。

7.使用以下方法从“钥匙串”中删除项目遵循相同的模式:

 let removeSuccessful: Bool = KeychainWrapper.standard.remove(key: "myKey") 

8.现在,您已成功使用SwiftKeychainWrapper安全地持久保存并访问字符串值!

如您所见,使用包装器在Keychain中进行添加,检索和删除操作仅需一行简单的代码即可完成。

每个包装器都有自己独特的语法和可配置选项,但是它们或多或少都遵循与本示例相同的模式。

感谢您的阅读!

查看资源以获取更多详细信息。

资源:

https://developer.apple.com/library/content/documentation/Security/Conceptual/keychainServConcepts/01introduction/introduction.html

通用钥匙扣
有关如何在iOS上使用钥匙串服务的示例。 developer.apple.com

有用的文章和教程:

NSUserDefaults不是敏感数据的地方!
如果您已经为iOS开发了一段时间,您就会知道NSUserDefaults几乎是“事实上的”存储方式… www.andyibanez.com 在iOS钥匙串中存储信息
AppStore中的许多应用程序都处理帐户信息和其他私有数据。 这意味着他们服用… devmonologue.com

很棒的教程更深入地介绍了该主题:

如何保护iOS用户数据:钥匙串,Touch ID和1Password
2016年5月8日更新:已针对Xcode 7.3和Swift 2.2更新(如果您使用的是Swift 3.0,请在论坛中查看我的评论…… www.raywenderlich.com

有用的视频: