iOS 用SecItemDelete删除密码报错errSecItemNotFound,用SecItemAdd存储新的密码报错errSecDuplicateIte

155 阅读1分钟

用SecItemDelete删除密码报错:

errSecItemNotFound                       = -25300,    /* The specified item could not be found in the keychain. */

用SecItemAdd存储新的密码报错:

errSecDuplicateItem                      = -25299,    /* The specified item already exists in the keychain. */

删除keychain数据代码:

+ (BOOL)deleteSharedKeyInKeychain:(NSString *)tag {
    if (!tag) {
        return NO;
    }
    // 删除之前的共享密钥(如果存在)
    NSDictionary *attributes = @{
        (id)kSecClass: (id)kSecClassGenericPassword, // 数据类型
        (id)kSecAttrAccount: tag,                   // 唯一标识符
        (id)kSecAttrService:tag,
        (id)kSecAttrAccessible: (id)kSecAttrAccessibleAlways // 访问权限
    };
    OSStatus status = SecItemDelete((__bridge CFDictionaryRef)attributes);  // 清理旧密钥
    
    return status == noErr;
    
//    VVLog(@"deleteSharedKeyInKeychain -- deviceid:%@", tag);
}

原因分析: kSecClassGenericPassword的唯一密钥由以下几部分组成:

kSecAttrAccount
kSecAttrService

要检查其是否存在,只需使用这些属性(包括kSecReturnAttributes标志)查询密钥链存储。

包含kSecAttrLabel和kSecAttrAccessible将排除具有相同唯一键但具有不同属性的任何现有项。

确认其(不)存在后,添加附加属性并添加或更新。

因为在此之前我的存储属性是 kSecAttrAccessibleWhenUnlocked,后面改为kSecAttrAccessibleAlways,所以如果设置删除代码里面的属性为kSecAttrAccessibleAlways就会报错errSecItemNotFound找不到对应kSecAttrAccessibleWhenUnlocked的密码,所以正确的删除代码:

+ (BOOL)deleteSharedKeyInKeychain:(NSString *)tag {
    if (!tag) {
        return NO;
    }
    // 删除之前的共享密钥(如果存在)
    NSDictionary *attributes = @{
        (id)kSecClass: (id)kSecClassGenericPassword, // 数据类型
        (id)kSecAttrAccount: tag,                   // 唯一标识符
        (id)kSecAttrService:tag
    };
    OSStatus status = SecItemDelete((__bridge CFDictionaryRef)attributes);  // 清理旧密钥
    
    return status == noErr;
    
//    VVLog(@"deleteSharedKeyInKeychain -- deviceid:%@", tag);
}