FXKeychain 1.5.3

FXKeychain 1.5.3

测试已测试
语言语言 Obj-CObjective C
许可 zlib
发布最新发布2015年5月

Nick Lockwood 维护。



目的

FXKeychain 是围绕 Apple 密钥链 API 的轻量级包装器,它公开了常用的功能,同时隐藏了底层 API 的可怕复杂性和丑陋界面。

FXKeychain 将密钥链视为一个简单的字典,您可以从其中设置和获取值。在大多数情况下,您可以使用默认密钥链,但也可以根据需要创建新的密钥链实例,如果您想要通过服务对密钥链进行命名空间管理,或者通过 accessGroup 在应用程序之间共享值。

支持的 iOS 和 SDK 版本

  • 支持的构建目标 - iOS 8.0 / Mac OS 10.9 (Xcode 6.0, Apple LLVM 编译器 6.0)
  • 最早支持的部署目标 - iOS 5.0 / Mac OS 10.7
  • 最早兼容的部署目标 - iOS 4.3 / Mac OS 10.6

注意:“支持”意味着库已经与该版本进行了测试。 “兼容”意味着库应该在该 iOS 版本上运行(即它不依赖于不可用的 SDK 功能),但不再对其进行兼容性测试,可能需要调整或错误修复才能正确运行。

ARC 兼容性

FXKeychain 需要 ARC。如果您希望在非 ARC 项目中使用 FXKeychain,只需将 `-fobjc-arc` 编译器标志添加到 FXKeychain.m 类中。为此,请转到目标设置中的构建阶段选项卡,打开编译源文件分组,在列表中双击 FXKeychain.m,然后在弹出窗口中输入 `-fobjc-arc`。

如果您希望将整个项目转换为 ARC,请注释掉 FXKeychain.m 中的 #error 行,然后运行 Xcode 中的编辑 > 重构 > 转换为 Objective-C ARC... 工具,并确保所有需要使用 ARC 的文件都已选中(包括 FXKeychain.m)。

安装

要使用 FXKeychain,只需将类文件拖放到您的项目中并添加 Security 框架。您可以使用 [FXKeychain defaultKeychain] 共享实例,或者根据需要创建新实例。

线程安全

  1. 在任何线程中都可以安全地使用给定的 FXKeychain 实例。
  2. 每个线程使用一个 FXKeychain 实例,不要同时从多个线程(包括默认实例)访问单个实例。
  3. 如果您有多个指向同一服务的FKKeychain实例,您可以安全地从多个线程并发读取它们的值, 但是您不应尝试从两个不同的线程并发写入同一个密钥。

安全性

在密钥链中存储和检索非字符串对象时应谨慎。在iOS上,密钥链被沙盒化到单个应用或由单个开发者共享的一组应用。但在Mac OS上,任何应用都可以读取或写入密钥链中的任何条目。这为恶意应用提供了尝试通过更改密钥链数据来操纵另一个应用的潜在机会。

FXKeychain版本1.2及更早版本允许使用NSCoding存储任意类到密钥链中。这个功能在1.3版本中被移除,以降低应用程序更改密钥链中编码类以加载和运行不应运行的代码的风险。在版本1.5中,该功能被恢复,但受FXKEYCHAIN_USE_NSCODING宏控制。在iOS上默认启用(iOS是沙盒化,因此相对安全),在Mac OS上默认禁用(因为Mac OS不是沙盒化)。

在iOS上代码注入风险较低(除非设备越狱)。在Mac OS上,使用1.3版本及更高版本应能保护您免受代码注入,因为现在默认支持plist兼容的类,这些类不容易被恶意使用。然而,仍然建议您验证从密钥链加载的数据是否与您预期的类型和结构匹配,以保护您的应用免受恶意或恶作剧性的修改,这可能会使您的应用崩溃或出现异常行为。

属性

FXKeychain具有以下属性

@property (nonatomic, copy, readonly) NSString *service;

服务属性用于区分给定设备或同一应用内的多个应用或服务。在Mac OS和iOS模拟器上,服务在应用之间共享,所以使用唯一的值作为服务是一个好主意,比如应用程序包标识符,或者如果您希望多个应用共享服务,可以使用相同的值作为accessGroup。服务值在密钥链创建后不可更改。

@property (nonatomic, copy, readonly) NSString *accessGroup;

accessGroup属性用于共享同一家开发者多个iOS应用之间的密钥链。有关使用accessGroup的可接受值,请参阅Apple的文档。如果您不打算在应用之间共享密钥链,请将此值设为nil。在Mac OS上,密钥链已经在应用之间共享,因此此属性无效果。accessGroup在密钥链创建后不可更改。

@property (nonatomic, assign) FXKeychainAccess accessibility;

accessibility属性用于控制设备锁定时对密钥链的访问。有关可能的值,请参阅以下FXKeychainAccess值描述。在Mac OS中,10.9(Mavericks)之前此属性无效果。与其他属性不同,accessibility属性可以随时更改,但更改只会影响更改之后设置的密钥;现有的密钥链密钥将不受影响,除非它们被重新写入。

方法

+ (instancetype)defaultKeychain;

此方法返回一个共享的默认密钥链实例,使用应用的包标识符作为服务,以避免在Mac OS或iOS模拟器上与其他应用的命名空间冲突。

- (id)initWithService:(NSString *)service
          accessGroup:(NSString *)accessGroup;

- (id)initWithService:(NSString *)service
          accessGroup:(NSString *)accessGroup
        accessibility:(FXKeychainAccess)accessibility;

此方法使用指定的参数创建一个新的FXKeychain实例。每个FXKeychain可以包含任意数量的键/值对,因此,您可能只需要为每个应用程序分配一个FXKeychain。每个FXKeychain都由服务参数唯一标识;请参阅属性描述了解如何使用它。您可以指定nil作为服务,在这种情况下,它将充当“通配符”选择器,对 walist(ObjectForKey:) 的调用将返回在keychain中存储的任何服务中找到的第一个值。访问组参数用于设置多个应用程序都可以访问的共享keychain;如果不需要该功能,请将其保留为nil。可选的可访问性属性控制当设备锁定时,应用程序在后台启动时keychain中的项目是否可访问(有关详细信息,请参阅下面的FXKeychainAccess值描述)。

- (BOOL)setObject:(id)object forKey:(id)key;
- (BOOL)setObject:(id)object forKeyedSubscript:(id)key;

这些方法将在keychain中保存指定的对象。任何与plist兼容的对象(NSDictionary、NSArray、NSString、NSNumber、NSDate、NSNull)都可以存储。类型为NSString的对象将存储为UTF8编码的数据,与其他keychain解决方案兼容。任何其他对象类型都将使用二进制plist编码存储。将nil作为对象的值从keychain中删除键。传递任何其他类型(或包含任何其他类型对象的集合)的对象将抛出异常。此方法的第二种形式与第一种功能相同,但包括以支持现代objective C键索引赋值语法。

- (BOOL)removeObjectForKey:(id)key;

此方法将从keychain中删除指定的键。

- (id)objectForKey:(id)key;
- (id)objectForKeyedSubscript:(id)key;

此方法从keychain返回指定键的值。如果键不存在,它将返回nil。此方法的第二种形式与第一种功能相同,但包括以支持现代objective C键索引赋值语法。

FXKeychainAccess值

FXKeychainAccessibleWhenUnlocked

这是默认值。设置为此可访问级别的keychain项目只能在设备解锁时访问。如果您的应用程序需要在后台运行时访问keychain,这可能会造成问题。

FXKeychainAccessibleAfterFirstUnlock

设置为此可访问级别的keychain项目在解锁后可以访问,并且即使在此期间设备再次锁定,也将保持可访问,直到设备重新启动。这对于需要由后台服务访问的项目是一个不错的选择。

FXKeychainAccessibleAlways

设置为此可访问级别的keychain项目可以在任何时间访问。与其他选项相比,这不太安全,但比在文件系统中存储纯文本值要好!

FXKeychainAccessibleWhenUnlockedThisDeviceOnly
FXKeychainAccessibleAfterFirstUnlockThisDeviceOnly
FXKeychainAccessibleAlwaysThisDeviceOnly

这些值的行为与非ThisDeviceOnly的对应值相同,但它们不备份和恢复,如果设备重置或升级,因此更安全(但可靠性更低)。

发行说明

版本1.5.3

  • 修复了存储值为数组时的崩溃问题

版本1.5.2

  • 修复了iOS 8上可能导致崩溃和不正确地处理accessGroup的问题

版本1.5.1

  • 如果在不存在键的情况下尝试删除键,则不再记录警告

版本1.5

  • 可访问性属性现在是readwrite,允许您按属性的基础更改可访问性。请注意,更改值只会影响在更改之后设置的密钥。
  • 当禁用NSCoding时,现在会在保存时删除NSNull值,以避免在有效代码中可能导致编码失败的潜在原因
  • 恢复了NSCoding支持,但此功能在iOS上默认开启。您可以通过预编译宏在Mac OS上启用它,但出于安全原因不推荐这样做。
  • 抑制了一些可能出现在密码包含等号的控制台警告。
  • 现在符合-Weverything警告级别。

版本1.4

  • 添加了访问参数,以便在设备锁定时可选允许密钥链访问。

版本1.3.4

  • 修复了在加载数据时某些特殊字符密码被错误地解释为属性列表的bug。
  • 添加了代码以防止基于用户提供的包含二进制plist数据的密码的注入攻击。

版本1.3.3

  • 修复了在Mac OS上删除密钥链项的问题。

版本1.3.2

  • 现在如果您尝试将无效对象类型编码,将抛出异常,而不仅仅是记录到控制台。

版本1.3.1

  • 修复了单例实现。

版本1.3

  • 由于安全原因,移除了在密钥链中存储任意类的能力(请参阅README)。仍然可以存储字典、数组等。

版本1.2

  • 现在可以对FXKeychain存储多个值。
  • 移除了帐户参数(它没有按预期的效果工作)。

版本1.1

  • 现在使用应用包标识符作为默认密钥链的命名空间。
  • 现在支持键控索引(例如,keychain["foo"] = bar;)。
  • 包含了CocoaPods podspec文件。
  • 包含了Mac OS例子。

版本1.0

  • 首次发布。