【iOS】Keychain 钥匙串

1,826 阅读3分钟

钥匙串,实际上是一个加密后的数据库,如下图所示。 即使把App删除,钥匙串里面的数据也不会丢失。

0304151a-f84e-44b1-8632-6698ec59854b.png

数据都是以 Item 的形式来存储的,每个 Item 由一个加密后的 Data 数据,还有一系列用来描述该 Item 属性的 Attributes 组成。 由于是数据库,关键方法只有四种,增删改查,对应的是

  • SecItemAdd
  • SecItemDelete
  • SecItemUpdate
  • SecItemCopyMatching

下面简单讲述一下使用方法

SecItemAdd

    CFTypeRef result;
    NSDictionary *query = @{
        // 一个典型的新增方法的参数,包含三个部分
        // 1.kSecClass key,它用来指定新增对象的类型
        (NSString *)kSecClass: (NSString *)kSecClassGenericPassword,
        // 2.若干项属性 key,例如 kSecAttrAccount,kSecAttrLabel 等,用来描述新增对象的属性
        (NSString *)kSecAttrAccount: @"uniqueID",
        // 3.kSecValueData key,用来设置新增对象保存的数据
        (NSString *)kSecValueData: [@"token" dataUsingEncoding:NSUTF8StringEncoding],
        // 可选
        // 如果需要获取新增的 Item 对象的属性,需要如下属性,
        (NSString *)kSecReturnData: (NSNumber *)kCFBooleanTrue,
        (NSString *)kSecReturnAttributes: (NSNumber *)kCFBooleanTrue,
    };
    OSStatus status = SecItemAdd((CFDictionaryRef)query, &result);
    if (result == errSecSuccess) {
        // 新增成功
        NSDictionary *itemInfo = (__bridge NSDictionary *)result;
        NSLog(@"info: %@", itemInfo);
    } else {
        // 其他错误
    }

result类型判断方式

kSecReturnDatakSecReturnAttributesresult
truetrueNSDictionary(包含属性与数据)
truefalseNSData(只有数据)
falsetrueNSDictionary(只包含属性)
falsefalsenull

SecItemDelete

    NSDictionary *query = @{
        // 一个典型的删除方法的参数,包含两个部分
        // 1、kSecClass key,它用来指定删除对象的类型,必填。
        (NSString *)kSecClass: (NSString *)kSecClassGenericPassword,
        // 2、若干项属性 key,可选。
        // 例如 kSecAttrAccount,kSecAttrLabel 等,用来设置删除对象的范围
        // 默认情况下,符合条件的全部 Item 都会被删除
        (NSString *)kSecAttrAccount: @"uniqueID",
    };
    OSStatus status = SecItemDelete((CFDictionaryRef)query);
    if (result == errSecSuccess) {
        // 删除成功
    } else {
        // 其他错误
    }

SecItemUpdate

    // 1、找出需要更新属性的 Item
    // 参数格式与 SecItemCopyMatching 方法中的参数格式相同
    NSDictionary *query = @{
        (NSString *)kSecClass: (NSString *)kSecClassGenericPassword,
        (NSString *)kSecAttrAccount: @"uniqueID",
    };
    
    // 2、需要更新的属性
    // 若干项属性 key
    NSDictionary *update = @{
        (NSString *)kSecAttrAccount: @"another uniqueID",
        (NSString *)kSecValueData: @"another value",
    };

    OSStatus status = SecItemUpdate((CFDictionaryRef)query, (CFDictionaryRef)update);

    if (result == errSecSuccess) {
        // 更新成功
    } else {
        // 其他错误
    }

SecItemDelete

    NSDictionary *query = @{
        // 一个典型的删除方法的参数,包含两个部分
        // 1、kSecClass key,它用来指定删除对象的类型,必填。
        (NSString *)kSecClass: (NSString *)kSecClassGenericPassword,
        // 2、若干项属性 key,可选。
        // 例如 kSecAttrAccount,kSecAttrLabel 等,用来设置删除对象的范围
        // 默认情况下,符合条件的全部 Item 都会被删除
        (NSString *)kSecAttrAccount: @"uniqueID",
    };
    OSStatus status = SecItemDelete((CFDictionaryRef)query);
    if (result == errSecSuccess) {
        // 删除成功
    } else {
        // 其他错误
    }

SecItemCopyMatching

    CFTypeRef result;
    NSDictionary *query = @{
        // 一个典型的搜索方法的参数,包含三个部分
        // 1、kSecClass key(必填),它用来指定搜索对象的类型
        (NSString *)kSecClass: (NSString *)kSecClassGenericPassword,
        // 2、若干项属性 key(可选),例如 kSecAttrAccount,kSecAttrLabel 等,用来描述搜索对象的属性
        (NSString *)kSecAttrAccount: @"uniqueID",
        // 3、搜索属性(可选)
        // 例如 kSecMatchLimit(搜索一个还是多个,影响返回结果类型)
        // kSecMatchCaseInsensitive 是否大小写敏感等
        (NSString *)kSecMatchLimit: (NSString *)kSecMatchLimitAll,
        (NSString *) kSecMatchCaseInsensitive: (NSNumber *) kCFBooleanTrue,
        // (可选)如果需要获取新增的 Item 对象的属性,需要如下属性,
        (NSString *)kSecReturnData: (NSNumber *)kCFBooleanTrue,
        (NSString *)kSecReturnAttributes: (NSNumber *)kCFBooleanTrue,
    };
    OSStatus status = SecItemCopyMatching((CFDictionaryRef)query, &result);
    if (result == errSecSuccess) {
        // 新增成功
        NSDictionary *itemInfo = (__bridge NSDictionary *)result;
        NSLog(@"info: %@", itemInfo);
    } else {
        // 其他错误
    }

result类型判断方式

kSecReturnDatakSecReturnAttributeskSecMatchLimitresult
truetruekSecMatchLimitAllNSDictionary(包含属性与数据)数组
truetruekSecMatchLimitOneNSDictionary(包含属性与数据)对象
truefalsekSecMatchLimitAllNSData(只有数据)数组
truefalsekSecMatchLimitOneNSData(只有数据)对象
falsetruekSecMatchLimitAllNSDictionary(只包含属性)数组
falsetruekSecMatchLimitOneNSDictionary(只包含属性)对象
falsefalsekSecMatchLimitAll空数组
falsefalsekSecMatchLimitOnenull

参考文档 developer.apple.com/documentati…

Demo 地址 github.com/huangrrui/K…