//密鑰類型鍵
創(chuàng)新互聯(lián)建站從2013年成立,先為石河子等服務建站,石河子等地企業(yè),進行企業(yè)商務咨詢服務。為石河子企業(yè)網(wǎng)站制作PC+手機+微官網(wǎng)三網(wǎng)同步一站式服務解決您的所有建站問題。
//CFTypeRef kSecClass
//
//值
//CFTypeRef kSecClassGenericPassword //一般密碼
//CFTypeRef kSecClassInternetPassword //網(wǎng)絡密碼
//CFTypeRef kSecClassCertificate //證書
//CFTypeRef kSecClassKey //密鑰
//CFTypeRef kSecClassIdentity //身份證書(帶私鑰的證書)
//
//不同類型的鑰匙串項對應的屬性不同
//
//一般密碼
//kSecClassGenericPassword
//
//對應屬性
//kSecAttrAccessible
//kSecAttrAccessGroup
//kSecAttrCreationDate
//kSecAttrModificationDate
//kSecAttrDescription
//kSecAttrComment
//kSecAttrCreator
//kSecAttrType
//kSecAttrLabel
//kSecAttrIsInvisible
//kSecAttrIsNegative
//kSecAttrAccount
//kSecAttrService
//kSecAttrGeneric
//網(wǎng)絡密碼
//kSecClassInternetPassword
//
//對應屬性
//kSecAttrAccessible
//kSecAttrAccessGroup
//kSecAttrCreationDate
//kSecAttrModificationDate
//kSecAttrDescription
//kSecAttrComment
//kSecAttrCreator
//kSecAttrType
//kSecAttrLabel
//kSecAttrIsInvisible
//kSecAttrIsNegative
//kSecAttrAccount
//kSecAttrSecurityDomain
//kSecAttrServer
//kSecAttrProtocol
//kSecAttrAuthenticationType
//kSecAttrPort
//kSecAttrPath
//證書
//kSecClassCertificate
//
//對應屬性
//kSecAttrAccessible
//kSecAttrAccessGroup
//kSecAttrCertificateType
//kSecAttrCertificateEncoding
//kSecAttrLabel
//kSecAttrSubject
//kSecAttrIssuer
//kSecAttrSerialNumber
//kSecAttrSubjectKeyID
//kSecAttrPublicKeyHash
//密鑰
//kSecClassKey
//
//對應屬性
//kSecAttrAccessible
//kSecAttrAccessGroup
//kSecAttrKeyClass
//kSecAttrLabel
//kSecAttrApplicationLabel
//kSecAttrIsPermanent
//kSecAttrApplicationTag
//kSecAttrKeyType
//kSecAttrKeySizeInBits
//kSecAttrEffectiveKeySize
//kSecAttrCanEncrypt
//kSecAttrCanDecrypt
//kSecAttrCanDerive
//kSecAttrCanSign
//kSecAttrCanVerify
//kSecAttrCanWrap
//kSecAttrCanUnwrap
//身份證書(帶私鑰的證書)
//kSecClassIdentity
//
//對應屬性
// 證書屬性
// 私鑰屬性
//鍵
//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; //所具有服務 CFStringRef
//CFTypeRef kSecAttrGeneric; //用戶自定義內(nèi)容 CFDataRef
//CFTypeRef kSecAttrSecurityDomain; //網(wǎng)絡安全域 CFStringRef
//CFTypeRef kSecAttrServer; //服務器域名或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)絡端口 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; //密鑰是否可用于導出其他密鑰 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;
在開發(fā)過程中,我們經(jīng)常會被要求獲取每個設備的唯一標示,以便后臺做相應的處理。
項目2若要使用項目1的Keychain則項目2要開啟Keychain Sharing 且 Keychain Groups要包含項目1。 項目1的Keychain Sharing 沒有要求。
使用第三方SSKeychain。
鑰匙串這個技術(shù)大家每天都在用,它相當于一個容器,里面有已加密的和未加密的用戶信息,它是怎么實現(xiàn)安全儲存Mac、App、服務器和網(wǎng)站的帳戶,開發(fā)過程中又該怎么使用這個技術(shù)呢。通過一個例子來介紹一下:
用戶要登錄你的APP,這個時候用戶在文本框輸入了他的用戶信息和密碼,那么你該如何存儲這個信息?自然我們會有一個類似用戶的結(jié)構(gòu)來存儲用戶信息
這個結(jié)構(gòu)里有一個String類型的用戶名稱和一個String類型的密碼變量, 張三輸入了它自己的用戶名“zhangsan”和密碼“******”來登陸,那么我們就會有一個生成用戶的過程
那么接下來你希望存儲到Keychain中,Keychain有哪些方法呢?第一步自然是添加
函數(shù)有三個參數(shù),但是每個似乎都不認識,所以我們先簡單看一下這三個參數(shù)要做什么
第一個參數(shù)是個字典,那自然是由許多key-value構(gòu)成,首先它要包含一個這個數(shù)據(jù)的類型,數(shù)據(jù)類型使用kSecClass來做key,kSecClass的定義:
可以看到kSecClass是一個CFString類型的全局變量,它其中可用的值由Item Class Keys and Values列出。根據(jù)數(shù)據(jù)類型的不同有不同的值,例如密碼、認證,對于密碼它的值定義為:
也是一個CFString類型的變量, class對應的值會決定數(shù)據(jù)是否被加密,當選擇這個password的時候數(shù)據(jù)就會被加密。那么我們字典中的第一個key-value對就有了:
那么這個字典還需要包含什么呢? 賬號:也就是這個數(shù)據(jù)是誰的數(shù)據(jù),這個屬性由kSecAttrAccount這個Key來定義,同樣它也是一個CFString類型的Key,它的值是你自定義的一個CFString類型的值。當然這個屬性并不是必須的,于是字典中的第二個key-value對也有了
??注意
字典中除了用戶名還需要用戶的數(shù)據(jù),數(shù)據(jù)使用kSecValueData這個Key來定義,同樣是CFString類型的Key,但是用戶的數(shù)據(jù)可能多種多樣,所以它的值類型是CFData。那么就需要把用戶的信息加工一下
這樣就得到了字典中第三個key-value對:
既然是鑰匙串,那就不能隨時隨地訪問,需要訪問控制權(quán)限,所謂訪問控制就是你希望當iPhone解鎖的時候,或者是驗證了用戶的指紋之后才能繼續(xù)進行的過程。權(quán)限由kSecAttrAccessControl這個Key來表示,它所對應的值是一個SecAccessControl的實例,而SecAccessControl又是什么?
它就是一個包含Keychain對象怎么被使用的信息的一個不透明類型,來看看它的實例化
它通過SecAccessControlCreateWithFlags(CFAllocatorRef allocator, CFTypeRef protection, SecAccessControlCreateFlags flags, CFErrorRef _Nullable *error)函數(shù)來創(chuàng)建
函數(shù)有四個參數(shù):
1.第一個參數(shù)是用來初始化SecAccessControlRef對象的. 我們可以傳 NULL 或者kCFAllocatorDefault
2.第二個參數(shù)是控制設備什么情況下可以訪問這個Keychain信息, 它的值可以是添加Keychain函數(shù)的第一個參數(shù)字典中的一個其它key(kSecAttrAccessible)對應的值,例如可以控制當設備解鎖的時候使用的值:kSecAttrAccessibleWhenUnlocked: CFString。其它可使用的還有kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly(只有這臺設備且設置了密碼)、kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly(只有這個設備第一次解鎖后)。
3.第三個參數(shù)是一組額外的訪問控制:用來控制用戶級別的訪問權(quán)限,如果設備沒有密碼總是處于unlocked的狀態(tài),你可能希望進一步限制KeyChain訪問。例如在獲取銀行賬戶的認證時候,需要在獲取認證信息之前驗證是不是授權(quán)用戶在操作,這使得KeyChain可以根據(jù)用戶的輸入來管理對Keychain的訪問,可以選擇devicePasscode來限制需要用戶需要輸入密碼或者是選擇userPresence來讓系統(tǒng)根據(jù)當前狀態(tài)選擇一種驗證方式或者是多種方式的組合
第四個是失敗原因的一個指針,這里暫時傳一個nil值
所以我們可以通過SecAccessControlCreateWithFlags來獲得一個訪問控制的參數(shù)
??注意
現(xiàn)在我們可以回到之前創(chuàng)建函數(shù)的第一個參數(shù)字典的分析了,我們得到了
SecAccessControl的實例,所以字典的第四個key-value對也有了:
現(xiàn)在字典中有了數(shù)據(jù)的類型、哪個用戶的數(shù)據(jù)、用戶要存儲的數(shù)據(jù)、什么條件可以訪問這個數(shù)據(jù)。看起來不缺少什么了。我們的一個字典參數(shù)就處理好了:
函數(shù)會通過第二個參數(shù)來返回新添加的Keychain,具體的類型是根據(jù)第一個參數(shù)中指定的返回類型決定的(例如可以通過kSecReturnData這個可以指定返回類型為CFData) 當然,通常我們可以忽略這個返回的數(shù)據(jù),所以可以傳一個nil值
函數(shù)還有一個返回值,從聲明上看是一個OSStatus類型的值,相應的定義在Security Framework Result Codes中,常見的值有:
我們通常需要將返回值和已知的返回值相比較來判斷是否操作成功了,也就是我們通??梢允褂萌缦碌恼Z句來處理添加操作
至此,添加操作就完成了。
查詢主要使用SecItemCopyMatching(CFDictionaryRef query, CFTypeRef _Nullable *result)函數(shù),函數(shù)會返回一個或者多個item,或者是指定的item屬性的copy,默認情況下只會返回匹配的第一個結(jié)果。
函數(shù)的第一個參數(shù)就是和添加Keychain函數(shù)的參數(shù)一樣的結(jié)構(gòu),通常有Keychain的class也就是由kSecClass為Key的一個key-value對。
屬性:屬性就是Keychain結(jié)果需要符合的條件,例如想查找哪個用戶的數(shù)據(jù),查詢參數(shù)還可以帶控制返回的key,因為添加方法和查詢方法都會返回結(jié)果的數(shù)據(jù)和屬性到提供的參數(shù)指針里,所以可以指定返回的key來控制指針對應的返回數(shù)據(jù)的格式,也就是通常的密碼查詢應該包含kSecReturnData為Key的key-value對。
例如可以使用kSecReturnPersistentRef這個Key來獲得一個CFData的引用,然后可以把它存儲在磁盤或在進程間傳遞,可以在這之后調(diào)用另一個SecItemCopyMatching函數(shù)將持久化引用轉(zhuǎn)為常規(guī)引用,函數(shù)參數(shù)里需要將持久化的引用的數(shù)組作為kSecMatchItemList的值傳入。如果使用kSecReturnData來控制返回data本身,搜索會返回一個代表實際數(shù)據(jù)的CFData,這個就是典型的密碼Keychain的使用方式。同時,Keychain服務會在返回給你之前對數(shù)據(jù)進行解密
搜索參數(shù):這個參數(shù)可以包含一些結(jié)果的數(shù)量條件,控制string屬性是否大小寫敏感等。
所以,希望查詢上面的用戶信息的時候查詢字典參數(shù)會如下所示
函數(shù)的第二個參數(shù)是一個CFTypeRef類型的接收函數(shù)返回的指針,我們需要先定義一個這樣的指針:
同樣我們需要判斷函數(shù)返回值是否成功:
因為查詢字典參數(shù)里攜帶了kSecReturnData,所以這個指針指向的數(shù)據(jù)類型是一個CFData類型的參數(shù),我們需要獲取對應的值
這樣 str就是我們之前存儲在KeyChain中的用戶信息了
至此,Keychain的添加和刪除都已經(jīng)具備了,基本的用戶需求就解決了。
除了基礎的使用之外,我們還可以
這些,下次再說吧
圖1 蘋果正式發(fā)布iOS 7.0.3
iCloud鑰匙串功能是可用于在已經(jīng)授權(quán)的蘋果設備上記錄用戶名,用戶密碼和綁定的信用卡賬號等信息,這是一個早已被使用在Mavericks的系統(tǒng)功能,而對于iOS系統(tǒng)來說卻是一個新功能。那么iOS 7.0.3系統(tǒng)中的iCloud鑰匙串怎么設置?下面我分享一下iCloud鑰匙串的使用教程。
iCloud鑰匙串怎么用?
我在本文中將以iPad為設備演示如何開啟iOS 7.0.3中的iCloud鑰匙串功能,在iPhone上開啟iCloud鑰匙串的方法基本一致。
1.首先在升級到iOS 7.0.3設備上找到“設置”圖標,點擊進入;
圖2 iCloud鑰匙串設置使用教程
2.在設置列表中找到“iCloud”的選項,點擊打開;
3.若升級iOS 7.0.3設備后沒有登錄iCloud賬戶,必須先登錄;已經(jīng)登錄成功的可以找到iCloud功能列表中的“鑰匙串”功能,點擊進入;
圖3 在設置中找到iCloud鑰匙串
4.這里只有“鑰匙串”功能開關(guān)選項,開啟“鑰匙串”功能;
圖4 開啟iCloud鑰匙串
5.這時候,iPad設備提示是否需要將iPad密碼用作iCloud安全碼,這個安全碼是把iCloud鑰匙串應用到其他iOS設備上的一個憑證。如果需要,則點擊“使用密碼”使用鎖屏密碼作為iCloud鑰匙串的'安全碼;
圖5 創(chuàng)建iCloud鑰匙串安全碼
6.輸入四位密碼作為iCloud鑰匙串的安全碼;
圖7 iCloud鑰匙串綁定手機號碼
8.等待蘋果系統(tǒng)激活鑰匙串功能即可完成。
iCloud鑰匙串有何用?
這里解釋一下蘋果iOS 7.0.3 iCloud鑰匙串有何作用?上文已經(jīng)講述到iCloud鑰匙串功能是可用于在已經(jīng)授權(quán)的多部蘋果設備上記錄用戶名,用戶密碼和綁定的信用卡賬號等信息,不同設備上想要使用同一個鑰匙串,必須經(jīng)過當前設備(本文中的iPad設備)批準后才能使用。
圖8 其他設備需要使用iCloud鑰匙串需經(jīng)初始設備批準
使用同一個iCloud鑰匙串功能,在不同的iOS設備上只要登錄同一個Apple ID賬號并且憑借前文中說到的安全碼即可以后任何操作都無需輸入密碼信息。
圖9 憑借iCloud鑰匙串安全碼恢復所有密碼