利用 Android Keystore 系統,您能夠在容器中存儲加密密鑰,從而提升從設備中提取密鑰的難度。在密鑰進入 Keystore 後,能夠將它們用於加密操做,而密鑰材料仍不可導出。此外,它提供了密鑰使用的時間和方式限制措施,例如要求進行用戶身份驗證才能使用密鑰,或者限制爲只能在某些加密模式中使用。Keystore 系統由 KeyChain API 以及在 Android 4.3(API 級別 18)中引入的 Android Keystore 提供程序功能使用。html
以上即是Google官方對於Android Keystore系統 的一些簡單的介紹,簡單的說Keystore 系統就是能夠幫助咱們完成一些咱們應用中的一些比較私密敏感的信息的加密存儲,以及解密,防止APP的一些關鍵信息泄露。咱們在實際開發中應該如何使用呢?這裏我簡單作個介紹,主要分爲三步:第一步,密鑰的建立。第二步,對咱們的數據進行加密,而後最後固然就是咱們要使用到數據的時候再對加密後的數據進行解密了。java
在密鑰的建立以前咱們先肯定咱們這裏要使用到的加密算法,關於加密算法這一塊有興趣的同窗能夠自行Google,這裏的例子使用到的加密算法爲「AES / GCM / NoPadding」。此外咱們還須要肯定一個別名,這個別名是密鑰在加解密過程當中的一個識別鏈接,至關於咱們在傳遞數據中的鍵值對中的鍵這樣的一個做用。密鑰獲取的代碼也不復雜,具體以下:android
@NonNull
private SecretKey getSecretKey(final String alias) throws NoSuchAlgorithmException,
NoSuchProviderException, InvalidAlgorithmParameterException {
final KeyGenerator keyGenerator = KeyGenerator
.getInstance(KeyProperties.KEY_ALGORITHM_AES, "AndroidKeyStore");
keyGenerator.init(new KeyGenParameterSpec.Builder(alias,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build());
return keyGenerator.generateKey();
}
複製代碼
能夠看到,咱們首先建立獲得一個密鑰生成器 KeyGenerator 的實例,其中兩個參數的相關說明參看下圖: git
咱們加密的實際過程是經過 Cipher 類來完成的,仍是先看代碼:github
byte[] encryptText(final String alias, final String textToEncrypt)
throws NoSuchAlgorithmException,
NoSuchProviderException, NoSuchPaddingException, InvalidKeyException, IOException,
InvalidAlgorithmParameterException, BadPaddingException, IllegalBlockSizeException {
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, getSecretKey(alias));
iv = cipher.getIV();
return (encryption = cipher.doFinal(textToEncrypt.getBytes("UTF-8")));
}
複製代碼
能夠看到咱們首先獲得了 Cipher 的實例,並指定了加密的算法爲 "AES/GCM/NoPadding" ,而後直接初始化 Cipher 的實例指定爲加密模式,並傳入咱們的第一步建立的密鑰,這裏咱們存儲 Cipher 初始化向量(IV),由於咱們在解密的時候會用到。最後一步咱們便直接調用 Cipher 的 doFinal 完成對數據的加密,doFinal方法返回一個字節數組,它是實際的加密文本,咱們直接 Base64 編碼一次就好:算法
Base64.encodeToString(encryptedText, Base64.DEFAULT)
複製代碼
仍是老規矩,先上代碼:數組
String decryptData(final String alias, final byte[] encryptedData, final byte[] encryptionIv)
throws UnrecoverableEntryException, NoSuchAlgorithmException, KeyStoreException,
NoSuchPaddingException, InvalidKeyException, IOException,
BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException {
final Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
final GCMParameterSpec spec = new GCMParameterSpec(128, encryptionIv);
cipher.init(Cipher.DECRYPT_MODE, getSecretKey(alias), spec);
return new String(cipher.doFinal(encryptedData), "UTF-8");
}
複製代碼
其實加密與解密是一組對稱的操做,解密其實就是加密的一個反向操做。一樣的咱們仍是須要先得到 Cipher 的實例,而後咱們經過 GCMParameterSpec 類來賦予 Cipher 初始化向量的參數,這裏簡單的對 GCMParameterSpec 的兩個參數進行說明,簡單的塊密碼模式(例如CBC)一般只須要初始化向量(例如IvParameterSpec),但GCM須要如下參數:bash
關於 GCMParameterSpec 的更多的信息能夠自行查看文檔,這裏就不展開討論了。ide
接下來跟加密同樣的步驟,初始化 Cipher ,這裏須要注意的一點即是咱們密鑰的獲取:ui
private SecretKey getSecretKey(final String alias) throws NoSuchAlgorithmException,
UnrecoverableEntryException, KeyStoreException {
return ((KeyStore.SecretKeyEntry) keyStore.getEntry(alias, null)).getSecretKey();
}
複製代碼
咱們經過咱們最初設定的別名識別對應的密鑰,從而經過 keyStore.getEntry(alias, null)).getSecretKey();方法進行獲取獲得。
至此咱們便完成了經過Android Keystore 系統對APP中的關鍵信息進行加密以及解密的全部過程。
本文例子GitHub地址,點擊此處。