Keychain 的介紹
Keychain 是蘋果公司 Mac OS(也包含 Mac OSX) 中的密碼管理系統(tǒng)最冰。
Keychain的作用
Keychain 可以包含許多種類型的數(shù)據(jù):密碼(包括網(wǎng)站鸿吆、FTP服務器柑肴、SSH賬戶、網(wǎng)絡共享证薇、無線網(wǎng)絡悠轩、群組軟件、加密磁盤鏡像)俊戳,私鑰,電子證書馆匿、加密筆記等抑胎。
Keychain 的四個方法介紹
1、存儲數(shù)據(jù)的方法
OSStatus SecItemAdd(CFDictionaryRef attributes, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
@attributes : 是要添加的數(shù)據(jù)渐北。
@result : 這是存儲數(shù)據(jù)后阿逃,返回一個指向該數(shù)據(jù)的引用,如果不是使用該引用時可以傳入 NULL 。
2恃锉、根據(jù)條件查詢數(shù)據(jù)
OSStatus SecItemCopyMatching(CFDictionaryRef query, CFTypeRef * __nullable CF_RETURNS_RETAINED result)
@query : 要查詢數(shù)據(jù)的條件搀菩。
@result: 根據(jù)條件查詢得到數(shù)據(jù)的引用。
3破托、更新數(shù)據(jù)
OSStatus SecItemUpdate(CFDictionaryRef query, CFDictionaryRef attributesToUpdate)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
@query : 要更新數(shù)據(jù)的查詢條件肪跋。
@attributesToUpdate : 要更新的數(shù)據(jù)。
4土砂、刪除數(shù)據(jù)
OSStatus SecItemDelete(CFDictionaryRef query)
__OSX_AVAILABLE_STARTING(__MAC_10_6, __IPHONE_2_0);
@query : 刪除的數(shù)據(jù)的查詢條件州既。
5、總結(jié)
以上四個方法萝映,就是Keychain 的常用的四個方法易桃,也就是 增、刪锌俱、改、查 敌呈。一般應用這四個方法就可以完全滿足贸宏。
Keychain 的一些Key 和 Value 的解釋和介紹
1、設置信息的保密程度
2磕洪、kSecClass 的可選value
3吭练、kSecClassGenericPassword 密碼所包含的所有類型參數(shù)
其他密碼的參數(shù)和普通密碼的參數(shù)大致相同,就不一一列舉析显。
Keychain 的封裝類KeyChainManager 的介紹和使用
1鲫咽、該類的 .h 文件
//
// KeyChainManager.h
// KeyChain
//
// Created by MAC on 2017/11/8.
// Copyright ? 2017年 NetworkCode小賤. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface KeyChainManager : NSObject
/*!
保存數(shù)據(jù)
@data 要存儲的數(shù)據(jù)
@identifier 存儲數(shù)據(jù)的標示
*/
+(BOOL) keyChainSaveData:(id)data withIdentifier:(NSString*)identifier ;
/*!
讀取數(shù)據(jù)
@identifier 存儲數(shù)據(jù)的標示
*/
+(id) keyChainReadData:(NSString*)identifier ;
/*!
更新數(shù)據(jù)
@data 要更新的數(shù)據(jù)
@identifier 數(shù)據(jù)存儲時的標示
*/
+(BOOL)keyChainUpdata:(id)data withIdentifier:(NSString*)identifier ;
/*!
刪除數(shù)據(jù)
@identifier 數(shù)據(jù)存儲時的標示
*/
+(void) keyChainDelete:(NSString*)identifier ;
@end
2、該類的 .m 文件
//
// KeyChainManager.m
// KeyChain
// Created by MAC on 2017/11/8.
// Copyright ? 2017年 NetworkCode小賤. All rights reserved.
//
#import "KeyChainManager.h"
#import <Security/Security.h>
@implementation KeyChainManager
/*!
創(chuàng)建生成保存數(shù)據(jù)查詢條件
*/
+(NSMutableDictionary*) keyChainIdentifier:(NSString*)identifier {
NSMutableDictionary * keyChainMutableDictionary = [NSMutableDictionary dictionaryWithObjectsAndKeys:(id)kSecClassGenericPassword,kSecClass,identifier,kSecAttrService,identifier,kSecAttrAccount,kSecAttrAccessibleAfterFirstUnlock,kSecAttrAccessible, nil];
return keyChainMutableDictionary;
}
/*!
保存數(shù)據(jù)
*/
+(BOOL) keyChainSaveData:(id)data withIdentifier:(NSString*)identifier{
// 獲取存儲的數(shù)據(jù)的條件
NSMutableDictionary * saveQueryMutableDictionary = [self keyChainIdentifier:identifier];
// 刪除舊的數(shù)據(jù)
SecItemDelete((CFDictionaryRef)saveQueryMutableDictionary);
// 設置新的數(shù)據(jù)
[saveQueryMutableDictionary setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
// 添加數(shù)據(jù)
OSStatus saveState = SecItemAdd((CFDictionaryRef)saveQueryMutableDictionary, nil);
// 釋放對象
saveQueryMutableDictionary = nil ;
// 判斷是否存儲成功
if (saveState == errSecSuccess) {
return YES;
}
return NO;
}
/*!
讀取數(shù)據(jù)
*/
+(id) keyChainReadData:(NSString*)identifier{
id idObject = nil ;
// 通過標記獲取數(shù)據(jù)查詢條件
NSMutableDictionary * keyChainReadQueryMutableDictionary = [self keyChainIdentifier:identifier];
// 這是獲取數(shù)據(jù)的時谷异,必須提供的兩個屬性
// TODO: 查詢結(jié)果返回到 kSecValueData
[keyChainReadQueryMutableDictionary setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
// TODO: 只返回搜索到的第一條數(shù)據(jù)
[keyChainReadQueryMutableDictionary setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
// 創(chuàng)建一個數(shù)據(jù)對象
CFDataRef keyChainData = nil ;
// 通過條件查詢數(shù)據(jù)
if (SecItemCopyMatching((CFDictionaryRef)keyChainReadQueryMutableDictionary , (CFTypeRef *)&keyChainData) == noErr){
@try {
idObject = [NSKeyedUnarchiver unarchiveObjectWithData:(__bridge NSData *)(keyChainData)];
} @catch (NSException * exception){
NSLog(@"Unarchive of search data where %@ failed of %@ ",identifier,exception);
}
}
if (keyChainData) {
CFRelease(keyChainData);
}
// 釋放對象
keyChainReadQueryMutableDictionary = nil;
// 返回數(shù)據(jù)
return idObject ;
}
/*!
更新數(shù)據(jù)
@data 要更新的數(shù)據(jù)
@identifier 數(shù)據(jù)存儲時的標示
*/
+(BOOL)keyChainUpdata:(id)data withIdentifier:(NSString*)identifier {
// 通過標記獲取數(shù)據(jù)更新的條件
NSMutableDictionary * keyChainUpdataQueryMutableDictionary = [self keyChainIdentifier:identifier];
// 創(chuàng)建更新數(shù)據(jù)字典
NSMutableDictionary * updataMutableDictionary = [NSMutableDictionary dictionaryWithCapacity:0];
// 存儲數(shù)據(jù)
[updataMutableDictionary setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
// 獲取存儲的狀態(tài)
OSStatus updataStatus = SecItemUpdate((CFDictionaryRef)keyChainUpdataQueryMutableDictionary, (CFDictionaryRef)updataMutableDictionary);
// 釋放對象
keyChainUpdataQueryMutableDictionary = nil;
updataMutableDictionary = nil;
// 判斷是否更新成功
if (updataStatus == errSecSuccess) {
return YES ;
}
return NO;
}
/*!
刪除數(shù)據(jù)
*/
+(void) keyChainDelete:(NSString*)identifier {
// 獲取刪除數(shù)據(jù)的查詢條件
NSMutableDictionary * keyChainDeleteQueryMutableDictionary = [self keyChainIdentifier:identifier];
// 刪除指定條件的數(shù)據(jù)
SecItemDelete((CFDictionaryRef)keyChainDeleteQueryMutableDictionary);
// 釋放內(nèi)存
keyChainDeleteQueryMutableDictionary = nil ;
}
@end
KeyChainManager 類的測試使用
1分尸、測試代碼
// 存儲數(shù)據(jù)
BOOL save = [KeyChainManager keyChainSaveData:@"思念訴說,眼神多像云朵" withIdentifier:Keychain];
if (save) {
NSLog(@"存儲成功");
}else {
NSLog(@"存儲失敗");
}
// 獲取數(shù)據(jù)
NSString * readString = [KeyChainManager keyChainReadData:Keychain];
NSLog(@"獲取得到的數(shù)據(jù):%@",readString);
// 更新數(shù)據(jù)
BOOL updata = [KeyChainManager keyChainUpdata:@"長發(fā)落寞歹嘹,我期待的女孩" withIdentifier:Keychain];
if (updata) {
NSLog(@"更新成功");
}else{
NSLog(@"更新失敗");
}
// 讀取數(shù)據(jù)
NSString * readUpdataString = [KeyChainManager keyChainReadData:Keychain];
NSLog(@"獲取更新后得到的數(shù)據(jù):%@",readUpdataString);
// 刪除數(shù)據(jù)
[KeyChainManager keyChainDelete:Keychain];
// 讀取數(shù)據(jù)
NSString * readDeleteString = [KeyChainManager keyChainReadData:Keychain];
NSLog(@"獲取刪除后得到的數(shù)據(jù):%@",readDeleteString);