iOS keychain 卸载后依然存在的持久化存储
// 封装
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface SecItemHelper : NSObject
+ (void)saveFromName:(NSString *)name data:(id)data;
+ (id)loadFromName:(NSString *)name;
+ (void)deletedataFromName:(NSString *)name;
@end
NS_ASSUME_NONNULL_END
#import “SecItemHelper.h”
@implementation SecItemHelper
+ (void)saveFromName:(NSString *)name data:(id)data
{
NSMutableDictionary *keychainQuery = [self getKeychainQuery:name];
// 清空
SecItemDelete((CFDictionaryRef)keychainQuery);
// 赋值
[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
// 添加
SecItemAdd((CFDictionaryRef)keychainQuery, NULL);
}
+ (id)loadFromName:(NSString *)name
{
id ret = nil;
NSMutableDictionary *keychainQuery = [self getKeychainQuery:name];
[keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
[keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
CFDataRef keyData = NULL;
if (SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef *)&keyData) == noErr)
{
@try
{
ret = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)keyData];
}
@catch (NSException *e)
{
NSLog(@”Unarchive of %@ failed: %@”, name, e);
}
@finally
{
}
}
if (keyData)
{
CFRelease(keyData);
}
return ret;
}
+ (void)deletedataFromName:(NSString *)name
{
NSMutableDictionary *keychainQuery = [self getKeychainQuery:name];
SecItemDelete((CFDictionaryRef)keychainQuery);
}
+ (NSMutableDictionary *)getKeychainQuery:(NSString *)name
{
NSMutableDictionary *dic = [NSMutableDictionary dictionary];
[dic setValue:(id)kSecClassGenericPassword forKey:(id)kSecClass];
[dic setValue:name forKey:(id)kSecAttrAccount];
[dic setValue:name forKey:(id)kSecAttrService];
// 解锁后可以的安全蛇者
[dic setValue:(id)kSecAttrAccessibleAfterFirstUnlock forKey:(id)kSecAttrAccessible];
return dic;
}
@end
// 调用
#import “ViewController.h”
#import “SecItemHelper.h”
@interface ViewController ()
@end
@implementation ViewController
– (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSString *name = NSStringFromClass(ViewController.class);
NSMutableDictionary *dic =[NSMutableDictionary dictionary];
[dic setValue:@”xiaoming” forKey:@”user”];
[dic setValue:@”123456″ forKey:@”password”];
[SecItemHelper saveFromName:name data:dic];
id data = [SecItemHelper loadFromName:name];
NSLog(@”%@”,data);
// [SecItemHelper deletedata:name];
// id data2 = [SecItemHelper load:name];
// NSLog(@”%@”,data2);
}
– (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
// 译文
kSecAttrAccessibleWhenUnlocked
当解锁时,kSec具有可访问性 推荐使用 iCloud同步
kSecAttrAccessibleAfterFirstUnlock
*次解锁后可访问kSec iCloud同步
kSecAttrAccessibleAlways
一直访问 不建议使用 iCloud同步
kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly
当密码仅设置此设备时,kSec Attr可访问 iCloud不同步
kSecAttrAccessibleWhenUnlockedThisDeviceOnly
只有在解锁此设备时才能访问kSec Attr iCloud不同步
kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly
只有在首次解锁此设备后才能访问kSec Attr iCloud不同步
kSecAttrAccessibleAlwaysThisDeviceOnly
kSec Attr始终只能访问此设备 iCloud不同步
kSecClassInternetPassword
表示Internet密码项的值。
kSecClassCertificate
表示证书项的值。
kSecClassKey
表示加密密钥项的值。
kSecClassIdentity
表示标识项的值。