iOS設(shè)備中的Keychain是一個安全的存儲容器根欧,可以用來為不同應(yīng)用保存敏感信息比如用戶名疾忍,密碼,網(wǎng)絡(luò)密碼横媚,認證令牌纠炮。蘋果自己用keychain來保存Wi-Fi網(wǎng)絡(luò)密碼,VPN憑證等等灯蝴。它是一個sqlite數(shù)據(jù)庫.
位于/private/var/Keychains/keychain-2.db恢口,其保存的所有數(shù)據(jù)都是加密過的。模擬器下keychain文件路徑:~/Library/Application Support/iPhone Simulator/4.3/Library/Keychains
keychain里保存的信息不會因App被刪除而丟失穷躁,在用戶重新安裝App后依然有效耕肩,數(shù)據(jù)還在。
關(guān)于備份折砸,?只會備份數(shù)據(jù)看疗,到那時不會備份設(shè)備的密鑰,換句話說睦授,即使拿到數(shù)據(jù)两芳,也沒有辦法解密里面的內(nèi)容。
?密鑰類型
密鑰類型的鍵 ? ?CFTypeRef kSecClass
密鑰類型的值:
//CFTypeRef kSecClassGenericPassword? ? ? ? ? ? //一般密碼
//CFTypeRef kSecClassInternetPassword? ? ? ? ? //網(wǎng)絡(luò)密碼
//CFTypeRef kSecClassCertificate? ? ? ? ? ? ? ? //證書
//CFTypeRef kSecClassKey? ? ? ? ? ? ? ? ? ? ? ? //密鑰
//CFTypeRef kSecClassIdentity? ? ? ? ? ? ? ? ? //身份證書(帶私鑰的證書)
不同類型的鑰匙串項對應(yīng)的屬性不同
1.一般密碼?kSecClassGenericPassword
a.對應(yīng)屬性
//kSecAttrAccessible
//kSecAttrAccessGroup
//kSecAttrCreationDate
//kSecAttrModificationDate
//kSecAttrDescription
//kSecAttrComment
//kSecAttrCreator
//kSecAttrType
//kSecAttrLabel
//kSecAttrIsInvisible
//kSecAttrIsNegative
//kSecAttrAccount
//kSecAttrService
//kSecAttrGeneric
2.網(wǎng)絡(luò)密碼 ?kSecClassInternetPassword
a.對應(yīng)屬性
//kSecAttrAccessible
//kSecAttrAccessGroup
//kSecAttrCreationDate
//kSecAttrModificationDate
//kSecAttrDescription
//kSecAttrComment
//kSecAttrCreator
//kSecAttrType
//kSecAttrLabel
//kSecAttrIsInvisible
//kSecAttrIsNegative
//kSecAttrAccount
//kSecAttrSecurityDomain
//kSecAttrServer
//kSecAttrProtocol
//kSecAttrAuthenticationType
//kSecAttrPort
//kSecAttrPath
3.證書 ?kSecClassCertificate
c.對應(yīng)屬性
//kSecAttrAccessible
//kSecAttrAccessGroup
//kSecAttrCertificateType
//kSecAttrCertificateEncoding
//kSecAttrLabel
//kSecAttrSubject
//kSecAttrIssuer
//kSecAttrSerialNumber
//kSecAttrSubjectKeyID
//kSecAttrPublicKeyHash
4.密鑰 ??kSecClassKey
d.對應(yīng)屬性
//kSecAttrAccessible
//kSecAttrAccessGroup
//kSecAttrKeyClass
//kSecAttrLabel
//kSecAttrApplicationLabel
//kSecAttrIsPermanent
//kSecAttrApplicationTag
//kSecAttrKeyType
//kSecAttrKeySizeInBits
//kSecAttrEffectiveKeySize
//kSecAttrCanEncrypt
//kSecAttrCanDecrypt
//kSecAttrCanDerive
//kSecAttrCanSign
//kSecAttrCanVerify
//kSecAttrCanWrap
//kSecAttrCanUnwrap
?證書屬性
1.私鑰屬性
鍵 ?CFTypeRef kSecAttrAccessible ? ? ? ? ? //可訪問性 類型透明
值
//? ? ? ? ? CFTypeRef kSecAttrAccessibleWhenUnlocked;? ? ? ? ? ? ? ? ? //解鎖可訪問去枷,備份
//? ? ? ? ? CFTypeRef kSecAttrAccessibleAfterFirstUnlock; ? ? ? ? ? //第一次解鎖后可訪問怖辆,備份
//? ? ? ? ? CFTypeRef kSecAttrAccessibleAlways; ? ? ? ? ? ? ? ? ? //一直可訪問是复,備份
//? ? ? ? ? CFTypeRef kSecAttrAccessibleWhenUnlockedThisDeviceOnly;? ? //解鎖可訪問,不備份
//? ? ? ? ? CFTypeRef kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly;//第一次解鎖后可訪問竖螃,不備份
//? ? ? ? ? CFTypeRef kSecAttrAccessibleAlwaysThisDeviceOnly;? ? ? ? ? //一直可訪問淑廊,不備份
//CFTypeRef kSecAttrCreationDate;? ? ? //創(chuàng)建日期? ? ? ? ? CFDateRef
//CFTypeRef kSecAttrModificationDate;? //最后一次修改日期? CFDateRef
//CFTypeRef kSecAttrDescription;? ? ? //描述? ? ? ? ? ? CFStringRef
//CFTypeRef kSecAttrComment;? ? ? ? ? //注釋? ? ? ? ? ? CFStringRef
//CFTypeRef kSecAttrCreator;? ? ? ? ? //創(chuàng)建者? ? ? ? ? ? CFNumberRef(4字符,如'aLXY')
//CFTypeRef kSecAttrType;? ? ? ? ? ? ? //類型? ? ? ? ? ? CFNumberRef(4字符特咆,如'aTyp')
//CFTypeRef kSecAttrLabel;? ? ? ? ? ? //標簽(給用戶看)? ? CFStringRef
//CFTypeRef kSecAttrIsInvisible;? ? ? //是否隱藏? ? ? ? ? CFBooleanRef(kCFBooleanTrue,kCFBooleanFalse)
//CFTypeRef kSecAttrIsNegative;? ? ? ? //是否具有密碼? ? ? CFBooleanRef(kCFBooleanTrue,kCFBooleanFalse)此項表示當前的item是否只是一個占位項季惩,或者說是只有key沒有value。
//CFTypeRef kSecAttrAccount;? ? ? ? ? //賬戶名? ? ? ? ? ? CFStringRef
//CFTypeRef kSecAttrService;? ? ? ? ? //所具有服務(wù)? ? ? ? CFStringRef
//CFTypeRef kSecAttrGeneric;? ? ? ? ? //用戶自定義內(nèi)容? ? ? CFDataRef
//CFTypeRef kSecAttrSecurityDomain;? ? //網(wǎng)絡(luò)安全域? ? ? ? CFStringRef
//CFTypeRef kSecAttrServer;? ? ? ? ? ? //服務(wù)器域名或IP地址? CFStringRef
//鍵 CFTypeRef kSecAttrProtocol; ? ? ? ? ? ? ? //協(xié)議類型 CFNumberRef
?值
//? ? ? ? ? CFTypeRef kSecAttrProtocolFTP; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolFTPAccount;?
//? ? ? ? ? CFTypeRef kSecAttrProtocolHTTP; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolIRC; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolNNTP; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolPOP3; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolSMTP; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolSOCKS; ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolIMAP; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolLDAP; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolAppleTalk; ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolAFP; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolTelnet; ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolSSH; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolFTPS; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolHTTPS; ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolHTTPProxy; ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolHTTPSProxy; ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolFTPProxy; ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolSMB; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolRTSP; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolRTSPProxy; ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolDAAP; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolEPPC; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolIPP; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolNNTPS; ? ??
//? ? ? ? ? CFTypeRef kSecAttrProtocolLDAPS; ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolTelnetS; ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolIMAPS; ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolIRCS; ? ? ? ?
//? ? ? ? ? CFTypeRef kSecAttrProtocolPOP3S; ? ? ?
//鍵 CFTypeRef kSecAttrAuthenticationType ? ? ? ?
?認證類型 CFNumberRef
?值
//? ? ? ? ? CFTypeRef kSecAttrAuthenticationTypeNTLM;? ? ? ? //
//? ? ? ? ? CFTypeRef kSecAttrAuthenticationTypeMSN;? ? ? ? //
//? ? ? ? ? CFTypeRef kSecAttrAuthenticationTypeDPA;? ? ? ? //
//? ? ? ? ? CFTypeRef kSecAttrAuthenticationTypeRPA;? ? ? ? //
//? ? ? ? ? CFTypeRef kSecAttrAuthenticationTypeHTTPBasic;? //
//? ? ? ? ? CFTypeRef kSecAttrAuthenticationTypeHTTPDigest;? //
//? ? ? ? ? CFTypeRef kSecAttrAuthenticationTypeHTMLForm;? ? //
//? ? ? ? ? CFTypeRef kSecAttrAuthenticationTypeDefault;? ? //
//CFTypeRef kSecAttrPort;? ? ? ? ? ? ? ? //網(wǎng)絡(luò)端口? ? ? ? ? CFNumberRef
//CFTypeRef kSecAttrPath;? ? ? ? ? ? ? ? //訪問路徑? ? ? ? ? CFStringRef
//CFTypeRef kSecAttrSubject;? ? ? ? ? ? ? //X.500主題名稱? ? ? CFDataRef
//CFTypeRef kSecAttrIssuer;? ? ? ? ? ? ? //X.500發(fā)行者名稱? ? CFDataRef
//CFTypeRef kSecAttrSerialNumber;? ? ? ? //序列號? ? ? ? ? ? CFDataRef
//CFTypeRef kSecAttrSubjectKeyID;? ? ? ? //主題ID? ? ? ? ? ? CFDataRef
//CFTypeRef kSecAttrPublicKeyHash;? ? ? ? //公鑰Hash值? ? ? ? CFDataRef
//CFTypeRef kSecAttrCertificateType;? ? ? //證書類型? ? ? ? ? ? CFNumberRef
//CFTypeRef kSecAttrCertificateEncoding;? //證書編碼類型? ? ? ? CFNumberRef
//CFTypeRef kSecAttrKeyClass ? ? ? ? ? ? //加密密鑰類? CFTypeRef
值
//? ? ? ? ? CFTypeRef kSecAttrKeyClassPublic;? ? //公鑰
//? ? ? ? ? CFTypeRef kSecAttrKeyClassPrivate;? ? //私鑰
//? ? ? ? ? CFTypeRef kSecAttrKeyClassSymmetric;? //對稱密鑰
//CFTypeRef kSecAttrApplicationLabel;? //標簽(給程序使用)? ? ? ? ? CFStringRef(通常是公鑰的Hash值)
//CFTypeRef kSecAttrIsPermanent;? ? ? //是否永久保存加密密鑰? ? ? CFBooleanRef
//CFTypeRef kSecAttrApplicationTag;? ? //標簽(私有標簽數(shù)據(jù))? ? ? ? CFDataRef
//CFTypeRef kSecAttrKeyType ?//加密密鑰類型(算法)? CFNumberRef
?值
//? ? ? ? ? extern const CFTypeRef kSecAttrKeyTypeRSA;
//CFTypeRef kSecAttrKeySizeInBits;? ? //密鑰總位數(shù)? ? ? ? ? ? ? CFNumberRef
//CFTypeRef kSecAttrEffectiveKeySize;? //密鑰有效位數(shù)? ? ? ? ? ? ? CFNumberRef
//CFTypeRef kSecAttrCanEncrypt;? ? ? ? //密鑰是否可用于加密? ? ? ? CFBooleanRef
//CFTypeRef kSecAttrCanDecrypt;? ? ? ? //密鑰是否可用于加密? ? ? ? CFBooleanRef
//CFTypeRef kSecAttrCanDerive;? ? ? ? //密鑰是否可用于導(dǎo)出其他密鑰? CFBooleanRef
//CFTypeRef kSecAttrCanSign;? ? ? ? ? //密鑰是否可用于數(shù)字簽名? ? ? CFBooleanRef
//CFTypeRef kSecAttrCanVerify;? ? ? ? //密鑰是否可用于驗證數(shù)字簽名? CFBooleanRef
//CFTypeRef kSecAttrCanWrap;? ? ? ? ? //密鑰是否可用于打包其他密鑰? CFBooleanRef
//CFTypeRef kSecAttrCanUnwrap;? ? ? ? //密鑰是否可用于解包其他密鑰? CFBooleanRef
//CFTypeRef kSecAttrAccessGroup;? ? ? //訪問組? ? ? ? ? ? ? ? ? CFStringRef
搜索
//CFTypeRef kSecMatchPolicy;? ? ? ? ? ? ? ? //指定策略? ? ? ? ? ? SecPolicyRef
//CFTypeRef kSecMatchItemList;? ? ? ? ? ? ? //指定搜索范圍? ? ? ? CFArrayRef(SecKeychainItemRef, SecKeyRef, SecCertificateRef, SecIdentityRef,CFDataRef)數(shù)組內(nèi)的類型必須唯一腻格。仍然會搜索鑰匙串画拾,但是搜索結(jié)果需要與該數(shù)組取交集作為最終結(jié)果。
//CFTypeRef kSecMatchSearchList;? ? ? ? ? ? //
//CFTypeRef kSecMatchIssuers;? ? ? ? ? ? ? ? //指定發(fā)行人數(shù)組? ? ? CFArrayRef
//CFTypeRef kSecMatchEmailAddressIfPresent;? //指定郵件地址? ? ? ? CFStringRef
//CFTypeRef kSecMatchSubjectContains;? ? ? ? //指定主題? ? ? ? ? ? CFStringRef
//CFTypeRef kSecMatchCaseInsensitive;? ? ? ? //指定是否不區(qū)分大小寫? CFBooleanRef(kCFBooleanFalse或不提供此參數(shù),區(qū)分大小寫;kCFBooleanTrue,不區(qū)分大小寫)
//CFTypeRef kSecMatchTrustedOnly;? ? ? ? ? ? //指定只搜索可信證書? ? CFBooleanRef(kCFBooleanFalse或不提供此參數(shù),全部證書;kCFBooleanTrue,只搜索可信證書)
//CFTypeRef kSecMatchValidOnDate;? ? ? ? ? ? //指定有效日期? ? ? ? CFDateRef(kCFNull表示今天)
//CFTypeRef kSecMatchLimit;? ? ? ? ? ? ? ? ? //指定結(jié)果數(shù)量? ? ? ? CFNumberRef(kSecMatchLimitOne;kSecMatchLimitAll)
//CFTypeRef kSecMatchLimitOne;? ? ? ? ? ? ? //首條結(jié)果
//CFTypeRef kSecMatchLimitAll;? ? ? ? ? ? ? //全部結(jié)果
列表
//CFTypeRef kSecUseItemList;? //CFArrayRef(SecKeychainItemRef, SecKeyRef, SecCertificateRef, SecIdentityRef,CFDataRef)數(shù)組內(nèi)的類型必須唯一菜职。用戶提供用于查詢的列表青抛。當這個列表被提供的時候,不會再搜索鑰匙串酬核。
?返回值類型
//可以同時指定多種返回值類型
//CFTypeRef kSecReturnData;? ? ? ? ? //返回數(shù)據(jù)(CFDataRef)? ? ? ? ? ? ? ? ? CFBooleanRef
//CFTypeRef kSecReturnAttributes;? ? //返回屬性字典(CFDictionaryRef)? ? ? ? CFBooleanRef
//CFTypeRef kSecReturnRef;? ? ? ? ? ? //返回實例(SecKeychainItemRef, SecKeyRef, SecCertificateRef, SecIdentityRef, or CFDataRef)? ? ? ? CFBooleanRef
//CFTypeRef kSecReturnPersistentRef;? //返回持久型實例(CFDataRef)? ? ? ? ? ? CFBooleanRef
寫入值類型
//CFTypeRef kSecValueData;
//CFTypeRef kSecValueRef;
//CFTypeRef kSecValuePersistentRef;
-------------------------------------------------------------------
簡單實現(xiàn):
在”Build Phases“中導(dǎo)入庫"Security.framework"
+ (BOOL)save:(NSString*)service data:(id)data;
+ (id)load:(NSString*)service;
+ (void)delete:(NSString*)service;
+ (NSMutableDictionary*) getKeychainQuery: (NSString*)service {
return [NSMutableDictionary dictionaryWithObjectsAndKeys:
(id)kSecClassGenericPassword, (id)kSecClass,
service, (id)kSecAttrService,
service, (id)kSecAttrAccount,
(id)kSecAttrAccessibleAfterFirstUnlock, (id)kSecAttrAccessible,
nil nil];
}
+ (BOOL) save:(NSString*)service data:(id)data {
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
SecItemDelete((CFDictionaryRef)keychainQuery);
[keychainQuery setObject:[NSKeyedArchiver archivedDataWithRootObject:data] forKey:(id)kSecValueData];
return SecItemAdd((CFDictionaryRef)keychainQuery, NULL) == noErr;
}
+ (id) load:(NSString*)service {
id ret = NULL;
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
[keychainQuery setObject:(id)kCFBooleanTrue forKey:(id)kSecReturnData];
[keychainQuery setObject:(id)kSecMatchLimitOne forKey:(id)kSecMatchLimit];
NSData *keyData = NULL;
if(SecItemCopyMatching((CFDictionaryRef)keychainQuery, (CFTypeRef*)(void*)&keyData) == noErr) {
@try {
ret = [NSKeyedUnarchiver unarchiveObjectWithData:keyData];
}
@catch (NSException *exception) {
NSLog(@"Unarchive of %@ failed: %@", service, exception);
}
@finally {
}
}
return ret;
}
+ (void) delete:(NSString*)service {
NSMutableDictionary *keychainQuery = [self getKeychainQuery:service];
SecItemDelete((CFDictionaryRef)keychainQuery);
}