Keychain 的概念

Keychain 是由苹果公司开发的一种安全存储系统,主要用于 macOS 和 iOS 操作系统。它通过加密技术集中管理用户的敏感信息,如密码、证书、密钥、支付卡信息等,确保数据仅能被授权应用或用户访问。

Keychain 的核心功能

  • 密码管理:存储应用、网站、Wi-Fi 的登录凭证,支持自动填充。
  • 加密保护:使用 AES-256 加密算法保护数据,密钥与设备绑定,未经授权无法解密。
  • 跨设备同步:通过 iCloud Keychain 在苹果设备间同步数据(需用户启用)。
  • 开发者集成:提供 API(如 Keychain Services)供第三方应用安全存储数据。

Keychain 的类型

  • 用户 Keychain:存储个人账户密码,默认路径为 ~/Library/Keychains/
  • 系统 Keychain:保存系统级证书和密钥,路径为 /Library/Keychains/
  • iCloud Keychain:云端同步版本,需苹果 ID 登录。

安全性与隐私

  • 生物识别验证:支持 Touch ID 或 Face ID 解锁 Keychain。
  • 访问控制:应用需声明权限(如 keychain-access-groups)才能读取数据。
  • 本地加密:即使设备越狱,未解锁的 Keychain 数据仍不可读。

常见使用场景

  • 在 Safari 中保存和自动填充网站密码。
  • 开发者存储 API 密钥或用户令牌。
  • 企业环境中管理数字证书和 VPN 配置。

如需进一步操作(如重置 Keychain 或解决同步问题),可通过 macOS 的“钥匙串访问”应用或 iOS 的“密码”设置进行管理。

依赖

import<Security/Security.h>

创建 Keychain 项

使用 SecItemAdd 函数可以创建新的 Keychain 项。需要传入一个包含项属性和数据的字典。

NSDictionary *attributes = @{
    (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
    (__bridge id)kSecAttrService: @"MyService",
    (__bridge id)kSecAttrAccount: @"user123",
    (__bridge id)kSecValueData: [@"password123" dataUsingEncoding:NSUTF8StringEncoding]
};

OSStatus status = SecItemAdd((__bridge CFDictionaryRef)attributes, NULL);
if (status == errSecSuccess) {
    NSLog(@"Item added successfully");
} else {
    NSLog(@"Error adding item: %d", (int)status);
}

读取 Keychain 项

使用 SecItemCopyMatching 函数读取 Keychain 项。需要指定搜索条件。

NSDictionary *query = @{
    (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
    (__bridge id)kSecAttrService: @"MyService",
    (__bridge id)kSecAttrAccount: @"user123",
    (__bridge id)kSecReturnData: @YES
};

CFTypeRef result = NULL;
OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result);
if (status == errSecSuccess) {

    //__bridge_transfer 是把c语言下的内存管理,交给ARC来管理,不用再手动释放了,即CFRelease()
    NSData *passwordData = (__bridge_transfer NSData *)result;
    NSString *password = [[NSString alloc] initWithData:passwordData encoding:NSUTF8StringEncoding];
    NSLog(@"Password: %@", password);
} else {
    NSLog(@"Error reading item: %d", (int)status);
}

更改 Keychain 项

使用 SecItemUpdate 函数更新 Keychain 项。需要指定搜索条件和要更新的属性。

NSDictionary *query = @{
    (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
    (__bridge id)kSecAttrService: @"MyService",
    (__bridge id)kSecAttrAccount: @"user123"
};

NSDictionary *updateAttributes = @{
    (__bridge id)kSecValueData: [@"newpassword456" dataUsingEncoding:NSUTF8StringEncoding]
};

OSStatus status = SecItemUpdate((__bridge CFDictionaryRef)query, (__bridge CFDictionaryRef)updateAttributes);
if (status == errSecSuccess) {
    NSLog(@"Item updated successfully");
} else {
    NSLog(@"Error updating item: %d", (int)status);
}

删除 Keychain 项

使用 SecItemDelete 函数删除 Keychain 项。需要指定搜索条件。

NSDictionary *query = @{
    (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword,
    (__bridge id)kSecAttrService: @"MyService",
    (__bridge id)kSecAttrAccount: @"user123"
};

OSStatus status = SecItemDelete((__bridge CFDictionaryRef)query);
if (status == errSecSuccess) {
    NSLog(@"Item deleted successfully");
} else {
    NSLog(@"Error deleting item: %d", (int)status);
}

注意事项

Keychain 操作可能返回不同的状态码,如 errSecItemNotFound 表示项不存在。处理这些状态码可以提高代码的健壮性。

在多设备环境中使用 Keychain 时,可能需要设置 kSecAttrSynchronizable 属性以实现跨设备同步。

Keychain 数据在设备备份时会加密存储,但需要考虑用户可能禁用 Keychain 备份的情况。

备注

如果要查看详细的SecKey,查看SecItem.h,错误码在SecBase.h

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐