【译】Android中的安全数据— Android中的加密(第2部分)
目錄
- 鎖屏
- 選擇一個(gè)鑰匙
- 密鑰存儲(chǔ)
- 密鑰生成
- 密鑰管理
- 加密與解密
- 使用范例
- 下一步是什么
- 安全提示
鎖屏
如果要保護(hù)數(shù)據(jù),請(qǐng)保護(hù)設(shè)備。
為了更加安全,在提供對(duì)任何應(yīng)用程序功能的訪問權(quán)限之前,我們可以要求用戶設(shè)置其設(shè)備的鎖屏(如果尚未設(shè)置)。另外,我們將在本系列的稍后部分中介紹的其他一些功能(例如指紋)也需要設(shè)置鎖定屏幕。
還有一項(xiàng)特殊的系統(tǒng)服務(wù)-KeyguardManager,可以幫助我們完成此任務(wù)。
isDeviceSecure?方法-檢查設(shè)備是否用PIN,碼型或密碼保護(hù)。可從API 23獲得。
isKeyguardSecure?方法-檢查鍵盤鎖是否由PIN,圖案或密碼保護(hù),或者當(dāng)前是否已鎖定SIM卡。可從API 16獲得。這不是最佳選擇,因?yàn)樗€在檢查SIM卡是否被鎖定,但總比沒有好。
?
秘密守護(hù)者,注冊(cè)屏幕
現(xiàn)在,在onStart()“活動(dòng)”中,只需檢查設(shè)備是否已使用鎖定屏幕進(jìn)行保護(hù),如果沒有,則顯示安全警報(bào)。
完整的源代碼在這里。
選擇一個(gè)鑰匙
現(xiàn)在,當(dāng)使用鎖屏保護(hù)設(shè)備時(shí),我們可以集中精力于應(yīng)用程序敏感的數(shù)據(jù)保護(hù),例如用戶主密碼和機(jī)密(請(qǐng)參閱Android中的加密(第1部分),示例項(xiàng)目)。我們已經(jīng)知道加密將用于此目的。首先,我們需要選擇要使用的密鑰(對(duì)稱,非對(duì)稱)和算法。
我們也知道,對(duì)稱密鑰可從Android 23+ API獲得,而非對(duì)稱密鑰可從18+ API獲得(請(qǐng)參閱Android中的加密(第1部分),Android密鑰存儲(chǔ))。我們的選擇是可以預(yù)測(cè)的,我們將使用非對(duì)稱密鑰,但是仍然選擇哪種算法?讓我們?cè)谖臋n中尋求幫助:
?
Android密鑰存儲(chǔ)系統(tǒng)。可用的密碼轉(zhuǎn)換,格式為:算法/模式/填充
RSA-我們可以Cipher在API 18+設(shè)備上用于Android密鑰存儲(chǔ)非對(duì)稱密鑰的唯一一種可用算法。
密鑰存儲(chǔ)
在Android上,加密密鑰存儲(chǔ)在中KeyStore:
還有一種架構(gòu)getInstance("type")方法,該方法KeyStore通過遍歷已注冊(cè)安全提供者的列表(從最喜歡的?一個(gè))開始創(chuàng)建具有給定類型的實(shí)例。我們將搜索“?AndroidKeyStore?”類型。
還有另一個(gè)KeyStoreFabric方法:—?從指定的Provider?返回指定類型的對(duì)象。getInstance("type", "provider")KeyStore
基本上稱之為:
val keyStore = KeyStore.getInstance(“ AndroidKeyStore”)keyStore.provider.name // AndroidKeyStore keyStore.type // AndroidKeyStorekeyStore.provider.name // AndroidKeyStore keyStore.type // AndroidKeyStore與調(diào)用幾乎相同:
val provider =“ AndroidKeyStore” val keyStore = KeyStore.getInstance(提供者,提供者)keyStore.provider.name // AndroidKeyStore keyStore.type // AndroidKeyStorekeyStore.provider.name // AndroidKeyStore keyStore.type // AndroidKeyStore但是請(qǐng)注意,如果在不同的提供程序中有多個(gè)具有相同名稱的注冊(cè)類型,則getInstance(“type”)method將返回它們中的第一個(gè)匹配結(jié)果。這有兩個(gè)不同的方面:
- 您(或設(shè)備供應(yīng)商)可以創(chuàng)建自己的Provider,并將其設(shè)置為最喜歡的,只需設(shè)置其位置即可(在本系列文章的后面部分中,您將了解如何進(jìn)行設(shè)置)。從理論上講,這可能會(huì)導(dǎo)致一些混亂,您會(huì)出錯(cuò),而不是預(yù)期的密鑰存儲(chǔ)類型。
- 另一方面,這種方法可用于解決一些兼容性問題,即系統(tǒng)將AndroidKeyStore在另一個(gè)Provider中添加新類型的實(shí)現(xiàn),并保持相同的名稱約定(還有另一個(gè)系統(tǒng)Provider,稱為“?AndroidKeyStoreBCWorkaround”,我們將在“加密和解密”段落)。這使我們可以在不同的API上保持相同的工作代碼,這很酷。
getInstance(“type”)到目前為止,該方法一直對(duì)我有效。文檔樣本也引用了此方法,因此,我建議您使用它來獲取KeyStore實(shí)例,而不是其他getInstance(“type”, “provider”)方法。
如果您仍然有疑問或某些功能無法正常使用,請(qǐng)使用keyStore.provider.name和keyStore.type方法來驗(yàn)證所創(chuàng)建KeyStore實(shí)例的詳細(xì)信息。
獲取實(shí)例之后,您必須調(diào)用load(loadStoreParameter)方法,該方法將基于提供的加載密鑰存儲(chǔ)數(shù)據(jù)ProtectionParameter。
保護(hù)參數(shù)可用于檢查密鑰存儲(chǔ)數(shù)據(jù)的完整性,或用于保護(hù)敏感密鑰存儲(chǔ)數(shù)據(jù)(例如PrivateKey)的機(jī)密性。
對(duì)于AndroidKeyStore提供者,我們只需要null作為參數(shù)傳遞,系統(tǒng)將根據(jù)我們的應(yīng)用程序標(biāo)識(shí)符將數(shù)據(jù)加載到后臺(tái)。
密鑰生成
在Android上,非對(duì)稱加密密鑰的創(chuàng)建方式KeyPairGenerator如下:
與密鑰存儲(chǔ)區(qū)類似,有一種fabric?getInstance(“algorithm”, “provider”)?方法,應(yīng)使用該方法來創(chuàng)建密鑰。
該方法還有另一個(gè)簡化版本getInstance(“algorithm”)。不要使用它。這種方法在所有現(xiàn)有的提供程序中搜索算法,與密鑰庫不同,密鑰存儲(chǔ)區(qū)我們使用的是非常獨(dú)特的“?AndroidKeyStore?”類型,算法名稱在不同的提供程序中很常見(“?RSA?”幾乎無處不在)。在這里,我們需要顯式定義我們要使用的提供程序。
KeyPairGenerator實(shí)例必須使用規(guī)范初始化。在M之前,KeyPairGeneratorSpec應(yīng)使用class提供它:
在Android密鑰存儲(chǔ)區(qū)中,每個(gè)密鑰必須具有一個(gè)標(biāo)識(shí)符-alias。如果您嘗試使用已存在的別名將密鑰保存到密鑰存儲(chǔ)中,它將被新密鑰覆蓋。使用setAlias()builders方法提供別名。
非對(duì)稱密鑰必須使用證書簽名。它主要用于客戶端-服務(wù)器通信中,其中客戶端(或服務(wù)器)正在驗(yàn)證證書,以確保服務(wù)器確實(shí)是他聲稱的身份(而不是中間人)。沒有證書,您將無法保存非對(duì)稱密鑰。
如果在一個(gè)應(yīng)用程序中都希望同時(shí)使用公鑰和私鑰,則只需創(chuàng)建一個(gè)偽造的,自簽名的證書即可。
證書需要一個(gè)開始日期和結(jié)束日期(有效期),可以使用setStartDate和setEndDate構(gòu)建器方法進(jìn)行設(shè)置。另外,您還需要提供序列號(hào)和證書主題,可以與setSerialNumberand?setSubjectbuilder方法一起使用。
偽造的自簽名證書的打印輸出:
<span style="color:#292929">數(shù)據(jù):版本:3(0x2)序列號(hào):1(0x1) 簽名算法:sha256WithRSAEncryption 頒發(fā)者:CN = MASTER_KEY CA證書有效期:2017年11月7日12:59:12 GMT 不之后:Nov 7 12:59:12 2037 GMT 主題:CN = MASTER_KEY CA證書主題公鑰信息:公鑰算法:rsaEncryption 公鑰:(2048位)模數(shù):00:b8:bf:51:10:fc:8c:7f:39:31:cc:是:43:43:81:f1:8b:5a:55:94:c4:5c:8c:56:51:5a:63:85:36:87:ff:3e:f2:a2:3b:9c: b0:e0:a8:3d:5e:1b:41:9c:00:6e:02:b2:42:d0:9c:e8:2f:4a:52:62:ac:7d:8e:75:a0:5e:58:57:ae:a5:2e:2c:48:0c:7f:cc:1a:95:46:2b:2b:a7:5e:96:69:d7:98:b8:32: 92:7d:80:e9:19:07:da:52:1a:29:de:e1:fb:56:43:60:7f:28:ce:23:ca:ee:12:11:17: 1d:0b:86:76:1a:f1:99:69:81:01:b0:d3:2c:6b:e7:ac:4f:f2:f7:97:88:ef:94:7a:28:a4:66:6e:d5:29:67:84:12:2e:d3:d3:d7:a6:f6:d4:ed:81:a4:24:9b:f2:2a:77:16:d9: 0d:62:31:cd:cc:c4:f0:fc:be:8d:6a:b4:14:fc:26:6b:a0:06:79:95:40:68:0e:da:5e: 25:69:f9:36:fb:eb:35:a5:e2:63:81:f0:88:c2:8e:be:fc:8d:65:ce:99:7f:88:cf:af:50:9a:59:77:dc:cd:76:a9:8c:64:de:e8:57:3b:40:bf:72:21:2c:60:3d:e0:7b:dd:1e: 01:81:3a:24:81:d4:a9:e2:e8:af:80:f6:00:f6:7f:fd:9f:48:d2:f7:96:d1 指數(shù):65537(0x10001) 簽名算法:sha256WithRSAEncryption 1f:f6:40:99:1c:c1:62:19:89:1f:35:fb:18:7e:93:1e:99:8c:84 :a4:cd:7b:93:c7:23:46:7c:9a:50:aa:a5:f2:34:07:82:ef:45:28:ac:50:6c:4e:a2:92 :35:e4:75:97:12:47:ef:80:e4:6d:b2:61:e4:4b:7f:79:4c:7c:ee:87:a9:ad:23:a1:ec :e9:1a:2c:8e:0c:04:61:6c:4b:f3:6e:a6:ff:3e:bb:ad:45:5a:c5:0f:ae:4e:7c:d5:93 :d0:98:69:0d:3e:bc:22:1f:85:11:db:0e:80:66:ff:58:4d:57:2f:64:cb:f8:c0:07:c9 :91:f9:7a:a8:48:0e:f6:2a:08:d9:db:89:8c:5b:24:a7:ad:8a:08:f5:aa:3e:ac:99:31 :15:9d:93:4f:d1:c5:7b:2d:41:f2:7e:99:5b:38:b8:1d:1a:63:d2:57:34:10:4b:06:95 :39:41:df:22:38:8d:a9:4f:9b:05:86:46:09:02:51:fc:41:39:54:ca:dd:1d:8e:34:77:01:1b:87:51:22:9c:4b:e8:ae:d5:8d: d8:e6:e1:ba:18:41:94:ef:64:b6:63:d9:2e:06:ea:1e:ae:80:11:5f:71:b2:28:b0:cc: 4e:18:5e:3f:4f:28:ae:4f:90:57:1e:41:51:36:02:94:ad:9b:7d:03:25:e7:f7:8a:4d: 26</span>提供關(guān)鍵細(xì)節(jié)后,初始化的KeyPairGenerator使用規(guī)范實(shí)例initialize(specification)方法。
在M中KeyGenParameterSpec被介紹。它用于初始化非對(duì)稱和對(duì)稱密鑰。KeyPairGeneratorSpec不推薦使用。
KeyGenParameterSpec要求指定密鑰用法的目的。例如,使用創(chuàng)建的密鑰KeyProperties.PURPOSE_ENCRYPT不能用于解密。
另外,您必須指定要與此密鑰一起使用的阻止模式和加密填充(請(qǐng)參閱“?加密,模式和填充”)。使用setBlockModes和setEncryptionPaddings構(gòu)建方法。
不再需要手動(dòng)定義偽造的證書,KeyGenParameterSpec它將自動(dòng)執(zhí)行。您仍然可以使用以下方法自定義默認(rèn)值:
最后,當(dāng)KeyPairGenerator實(shí)例使用規(guī)范初始化時(shí),使用generateKeyPair()方法創(chuàng)建私鑰-公鑰對(duì)。在Android Key Store提供程序中,此方法將自動(dòng)?保存?鍵入?KeyStore。
密鑰管理
KeyStore?提供的方法可以幫助我們管理保存的密鑰:
getKey(“ alias”,“ password”)?—返回具有給定別名的鍵,如果給定別名不存在或未標(biāo)識(shí)與鍵相關(guān)的條目,則返回null。在Android Key Store中,不需要密碼。
getCertificate(“ alias”)?—返回證書,如果給定的別名不存在或不包含證書,則返回null。
deleteEntry(“ alias”)?—?jiǎng)h除具有給定別名的密鑰。KeyStoreException
如果無法刪除該條目,將被拋出。
完整的源代碼在這里。
加密與解密
在Android上,加密和解密是通過進(jìn)行的Cipher:
有一種結(jié)構(gòu)getInstance(“transformation”)方法,即在現(xiàn)有的提供程序之間搜索給定的轉(zhuǎn)換(就像我們?cè)谏厦婊仡櫟钠渌用芙M件中一樣),應(yīng)將其用于創(chuàng)建Cipher實(shí)例。
轉(zhuǎn)換表示將用于加密或解密的算法,格式為:“算法/模式/填充”。
getInstance(“transformation”, "provider")這里還存在可以顯式指定Provider的Method?。但是請(qǐng)注意,您不應(yīng)將其與Cipher一起使用。
val轉(zhuǎn)換=“ RSA / ECB / PKCS1Padding” val提供程序=“ AndroidKeyStore”// API 19 val cipher:Cipher = Cipher.getInstance(transformation) cipher.provider.name // AndroidOpenSSL// API 23,24 val cipher:Cipher = Cipher.getInstance(transformation) cipher.provider.name // AndroidKeyStoreBCWorkaroundval cipher:Cipher = Cipher.getInstance(transformation,provider) //拋出java.security.NoSuchAlgorithmException: //提供者AndroidKeyStore不提供RSA / ECB / PKCS1Padding// API 19 val cipher:Cipher = Cipher.getInstance(transformation) cipher.provider.name // AndroidOpenSSL// API 23,24 val cipher:Cipher = Cipher.getInstance(transformation) cipher.provider.name // AndroidKeyStoreBCWorkaroundval cipher:Cipher = Cipher.getInstance(transformation,provider) //拋出java.security.NoSuchAlgorithmException: //提供者AndroidKeyStore不提供RSA / ECB / PKCS1Padding如您所見,從技術(shù)上講,AndroidKeyStore提供程序不向密碼提供RSA算法。而是有AndroidOpenSSL和AndroidKeyStoreBCWorkaround提供者,他們知道如何AndroidKeyStore為該算法使用提供者密鑰。
要開始使用Cipher實(shí)例,我們需要使用Key將其初始化以進(jìn)行特定操作。使用init(mode, key)方法with對(duì)其Cipher.ENCRYPT_MODE進(jìn)行初始化以進(jìn)行加密:
或使用init(mode, key)with方法Cipher.DECRYPT_MODE來初始化用于解密的密碼:
初始化后,使用doFinal(data)方法,使用此密碼來處理加密或解密的數(shù)據(jù)。
您可以根據(jù)需要多次重新初始化創(chuàng)建的密碼實(shí)例。
完整的源代碼在這里。
使用范例
總結(jié)一下我們正在討論的所有內(nèi)容,讓我們嘗試加密和解密簡單的“ Hello World”消息:
完整的源代碼在這里。
總結(jié)
以上是生活随笔為你收集整理的【译】Android中的安全数据— Android中的加密(第2部分)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linux E325: ATTENTIO
- 下一篇: 【译】在Android中保护数据-加密大