Keychain與NSUserDefaults的比較
NSUserDefaults作用的場(chǎng)所:
????????NSUserDefaults其實(shí)是plist文件中鍵值存儲(chǔ)女坑,并且最大的問(wèn)題是存在與沙盒中且预,這就對(duì)安全性埋下了隱患男窟。如果攻擊者破解app,拿到了沙盒中的數(shù)據(jù),就會(huì)造成數(shù)據(jù)泄漏,后果不堪設(shè)想古毛。
????????當(dāng)然,一般也不會(huì)有把密碼直接使用NSUserDefaults存儲(chǔ)的都许,都會(huì)進(jìn)行加密稻薇、或者是多重加密后再進(jìn)行NSUserDefaults存儲(chǔ)。這么做其實(shí)是可行的胶征,前提是加密算法不能泄漏塞椎。有個(gè)小問(wèn)題就是,如果用戶(hù)刪掉app重裝的話睛低,之前所有存儲(chǔ)的敏感信息都會(huì)消失案狠。比如服傍,一個(gè)用戶(hù)誤刪了使用NSUserDefaults存儲(chǔ)密碼的app,當(dāng)重新安裝之后骂铁,由于以前是記住密碼免登錄吹零,只因?yàn)樽约翰僮鞑划?dāng),接下來(lái)要進(jìn)入找回密碼功能从铲,重新修改密碼才能再次使用app瘪校。這對(duì)用戶(hù)來(lái)說(shuō)是一種相當(dāng)不友好的體驗(yàn)澄暮。所以名段,正確的姿勢(shì)是使用Keychain服務(wù)來(lái)存儲(chǔ)。
????????Keychain保存的數(shù)據(jù)不僅僅是加密過(guò)的泣懊,而且由于Keychain是存在與沙盒之外的伸辟,當(dāng)應(yīng)用刪除之后,app存儲(chǔ)的數(shù)據(jù)并沒(méi)有被刪掉馍刮,第二次安裝時(shí)只要讀取Keychain里的數(shù)據(jù)信夫,即可得到以前存儲(chǔ)的信息
Keychain使用場(chǎng)所:
存儲(chǔ)隱私信息:
? ? ? ? ? iOS的keychain服務(wù)提供了一種安全的保存私密信息(密碼,序列號(hào)卡啰,證書(shū)等)的方式静稻,每個(gè)ios程序都有一個(gè)獨(dú)立的keychain存儲(chǔ)。相對(duì)于NSUserDefaults匈辱、文件保存等一般方式振湾,keychain保存更為安全,而且keychain里保存的信息不會(huì)因App被刪除而丟失亡脸,所以在重裝App后押搪,keychain里的數(shù)據(jù)還能使用。
數(shù)據(jù)共享:
? ?????我們可以把KeyChain理解為一個(gè)Dictionary浅碾,所有數(shù)據(jù)都以key-value的形式存儲(chǔ)大州,可以對(duì)這個(gè)Dictionary進(jìn)行add、update垂谢、get厦画、delete這四個(gè)操作。對(duì)于每一個(gè)應(yīng)用來(lái)說(shuō)滥朱,KeyChain都有兩個(gè)訪問(wèn)區(qū)苛白,私有區(qū)和公共區(qū)。私有區(qū)是一個(gè)sandbox焚虱,本程序存儲(chǔ)的任何數(shù)據(jù)都對(duì)其他程序不可見(jiàn)购裙。而要想在將存儲(chǔ)的內(nèi)容放在公共區(qū),需要先聲明公共區(qū)的名稱(chēng)鹃栽,官方文檔管這個(gè)名稱(chēng)叫“keychain access group”躏率,聲明的方法是新建一個(gè)plist文件躯畴,名字隨便起,內(nèi)容如下:
“yourAppID.com.yourCompany.whatever”就是你要起的公共區(qū)名稱(chēng)薇芝,除了whatever字段可以隨便定之外蓬抄,其他的都必須如實(shí)填寫(xiě)。這個(gè)文件的路徑要配置在 Project->build setting->Code Signing Entitlements里夯到,否則公共區(qū)無(wú)效嚷缭,配置好后,須用你正式的證書(shū)簽名編譯才可通過(guò)耍贾,否則xcode會(huì)彈框告訴你code signing有問(wèn)題阅爽。所以,蘋(píng)果限制了你只能同公司的產(chǎn)品共享KeyChain數(shù)據(jù)荐开,別的公司訪問(wèn)不了你公司產(chǎn)品的KeyChain付翁。
設(shè)備唯一標(biāo)示存儲(chǔ):
? ??????在iOS中,為了在蘋(píng)果的打壓下獲取唯一標(biāo)示符晃听,開(kāi)發(fā)者們也是想盡了辦法百侧,目前最好的方式就是獲取IDFV,并將其存儲(chǔ)到keychain中能扒。IDFV是設(shè)備區(qū)別應(yīng)用提供商的佣渴,一般來(lái)說(shuō)可以作為應(yīng)用唯一標(biāo)示符。但是IDFV缺陷就是當(dāng)設(shè)備刪除了該所有應(yīng)用提供商的app之后初斑,IDFV值會(huì)發(fā)生變化辛润,所以IDFV+Keychain的組合目前被經(jīng)常用到,來(lái)替代UDID的作用越平。特別是加上Keychain的共享服務(wù)频蛔,可以使應(yīng)用提供商下的所有app下獲取的IDFV都不會(huì)發(fā)生變化。這一服務(wù)可以說(shuō)是目前最佳的識(shí)別用戶(hù)的辦法秦叛。
Structure of a Keychain
????????Keychain內(nèi)部可以保存很多的信息晦溪。每條信息作為一個(gè)單獨(dú)的keychain item,keychain item一般為一個(gè)字典挣跋,每條keychain item包含一條data和很多attributes三圆。舉個(gè)例子,一個(gè)用戶(hù)賬戶(hù)就是一條item避咆,用戶(hù)名可以作為一個(gè)attribute , 密碼就是data舟肉。 keychain雖然是可以保存15000條item,每條50個(gè)attributes,但是蘋(píng)果工程師建議最好別放那么多查库,存幾千條密碼路媚,幾千字節(jié)沒(méi)什么問(wèn)題。
????????????如果把keychain item的類(lèi)型指定為需要保護(hù)的類(lèi)型比如password或者private key樊销,item的data會(huì)被加密并且保護(hù)起來(lái)整慎,如果把類(lèi)型指定為不需要保護(hù)的類(lèi)型脏款,比如certificates,item的data就不會(huì)被加密裤园。
item可以指定為以下幾種類(lèi)型:
extern CFTypeRef kSecClassGenericPassword
extern CFTypeRef kSecClassInternetPassword
extern CFTypeRef kSecClassCertificate
extern CFTypeRef kSecClassKey
extern CFTypeRef kSecClassIdentityOSX_AVAILABLE_STARTING(MAC_10_7, __IPHONE_2_0);
Keychain的用法
首先導(dǎo)入Security.framework 撤师。
Keychain的API提供以下幾個(gè)函數(shù)來(lái)操作Keychain
SecItemAdd 添加一個(gè)keychain item
SecItemUpdate 修改一個(gè)keychain item
SecItemCopyMatching 搜索一個(gè)keychain item
SecItemDelete 刪除一個(gè)keychain item
Keychain Access Group
????????Keychain通過(guò)provisioning profile來(lái)區(qū)分不同的應(yīng)用,provisioning文件內(nèi)含有應(yīng)用的bundle id和添加的access groups拧揽。不同的應(yīng)用是完全無(wú)法訪問(wèn)其他應(yīng)用保存在Keychain的信息剃盾,除非指定了同樣的access group。指定了同樣的group名稱(chēng)后淤袜,不同的應(yīng)用間就可以分享保存在Keychain內(nèi)的信息痒谴。
Keychain Access Group的使用方法:
????????首先要在Capabilities下打開(kāi)工程的Keychain Sharing按鈕。然后需要分享Keychain的不同應(yīng)用添 加相同的Group名稱(chēng)饮怯。Xcode6以后Group可以隨便命名闰歪,不需要加AppIdentifierPrefix前綴嚎研,并且Xcode會(huì)在以entitlements結(jié)尾的文件內(nèi)自動(dòng)添加所有Group名稱(chēng)蓖墅,然后在每一個(gè)Group前自動(dòng)加上$(AppIdentifierPrefix)前綴。雖然文檔內(nèi)提到還需要添加一個(gè)包含group的.plist文件临扮,其實(shí)它和.entitlements文件是同樣的作用论矾,所以不需要重復(fù)添加。 但是每個(gè)不同的應(yīng)用第一條Group最好以自己的bundleID命名杆勇,因?yàn)槿绻鹐ntitlements文件內(nèi)已經(jīng)有Keychain Access Groups數(shù)組后item的Group屬性默認(rèn)就為數(shù)組內(nèi)的第一條Group,其實(shí)keychaingroups的名字你可以隨便起贪壳,(最好使用app的buddleid),在keychain groups里面加上你想要共享哪個(gè)group的數(shù)據(jù)蚜退,想共享幾個(gè)就可以填寫(xiě)幾個(gè)闰靴,前提是這些group必須的team必須相同,也就是(AppIdentifierPrefix)必須相同钻注!
????????這樣設(shè)置group會(huì)導(dǎo)致存儲(chǔ)數(shù)據(jù)失敗蚂且,如果不想共享某個(gè)group的數(shù)據(jù),建議group傳入AppIdentifierPrefix+bundleiD幅恋!在其他app的keychain group中杏死,只填入想要共享數(shù)據(jù)的group!例如上圖中的MCUUId和MCaccount兩個(gè)keychain group捆交!在另一個(gè)app中加入同樣的group淑翼,就能實(shí)現(xiàn)這兩個(gè)group中的數(shù)據(jù)共享,切記代碼中傳入group的時(shí)候要加上appidentifier前綴品追,否則會(huì)存儲(chǔ)失斝ā!當(dāng)傳入的group不在entitlements文件內(nèi)時(shí)肉瓦,此時(shí)傳入的group的值必須為AppIdentifierPrefix+bundleiD遭京,否則會(huì)造成存儲(chǔ)失斠埂!查詢(xún)時(shí)也可以指定group查詢(xún)洁墙,但是必須使用真機(jī)測(cè)試
????????samkeychain的方法中涉及到的變量主要有三個(gè)蛹疯,分別如這一小節(jié)的標(biāo)題所示,是password热监、service捺弦、account。password孝扛、account分別保存的是密碼和用戶(hù)名信息列吼。service保存的是服務(wù)的類(lèi)型,就是用戶(hù)名和密碼是為什么應(yīng)用保存的一個(gè)標(biāo)志苦始。比如一個(gè)用戶(hù)可以再不同的論壇中使用相同的用戶(hù)名和密碼寞钥,那么service保存的信息分別標(biāo)識(shí)不同的論壇。由于包名通常具有一定的唯一性陌选,通常在程序中可以用包的名稱(chēng)來(lái)作為service的標(biāo)識(shí)理郑。)