SecretKey を使用して、アプリケーションの機密データを暗号化します。現在、SecretKeyをBase64でエンコードされた形式でDBまたはSharedPrefsに保存していますが、これはルート化された電話にSecretを保存するのに安全な場所ではありません。したがって、SecretKeyを Android KeyStore に移動したいと思います。私が直面している問題は、Googleから このサンプルコード を試してみると、SecretKeyではなくPrivateKeyが必要になることです。 SecretKeyをKeyStoreに保存し、後で使用するためにフェッチする方法がわかりませんでした。私はこれを試しました:
private static void writeSecretKeyToKeystore(SecretKey secretKey, Context context) {
KeyStore keyStore = null;
try {
keyStore = KeyStore.getInstance("AndroidKeyStore");
keyStore.load(null);
KeyStore.SecretKeyEntry secretKeyEntry = new KeyStore.SecretKeyEntry(secretKey);
keyStore.setKeyEntry("Key", secretKeyEntry.getSecretKey().getEncoded(), null);
} catch (KeyStoreException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
上記のコードを試してみると、例外がスローされますOperation not supported because encoding is unknown
。
サンプルコードはどれも大いに役立ちます。
違う
Java.security.KeyStoreは、対称キーと非対称キーの両方を格納できます。 KeyStore.SecretKeyEntryをインスタンス化して、コンストラクターでSecretKeyを渡し、KeyStore#setEntryメソッドを使用して保存する必要があります。
keyStore.setEntry(
"key1",
new KeyStore.SecretKeyEntry(secretKey),
new KeyProtection.Builder(KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockMode(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.build());
それを元に戻すには、以下を使用します。
SecretKey keyStoreKey = (SecretKey) keyStore.getKey("key1", null);
更新
調査の結果、AndroidKeyStoreが対称鍵をサポートしていないことに驚きました。 (ディスカッションを参照してください: https://groups.google.com/forum/#!topic/Android-developers/gbmIRKRbfq8 )
回避策は、SecretKeyを暗号化し、SharedPreferencesに保存することです。次に、キーを格納して、キーを復号化します。 scytale を使用した実装を次に示します。
public static String getBase64EncodedSecretKey(){
Store store = new Store(context);
Crypto crypto = new Crypto(Options.TRANSFORMATION_SYMMETRIC);
SecretKey key = store.getSymmetricKey("key_alias", null);
String encryptedData = PreferenceManager.getDefaultSharedPreferences(context).getString("myEncryptedSecretKey", "");
return crypto.decrypt(encryptedData, key);
}
public static void storeKey(String base64EncodedSecretKey){
Store store = new Store(context);
if (store.hasKey("key_alias")) {
store.deleteKey("key_alias");
}
SecretKey key = store.generateSymmetricKey("key_alias", null);
Crypto crypto = new Crypto(Options.TRANSFORMATION_SYMMETRIC);
String encryptedData = crypto.encrypt(base64EncodedSecretKey, key);
PreferenceManager.getDefaultSharedPreferences(context).edit().putString("myEncryptedSecretKey",encryptedData).apply();
}
// Usage:
//store SecretKey
byte[] encodedKey = secretKeyEntry.getSecretKey().getEncoded();
String base64EncodedKey = Base64.encodeToString(encodedKey);
storeKey(base64EncodedKey);
//get SecretKey
String base64EncodedKey = getBase64EncodedSecretKey();
byte[] encodedKey = Base64.decode(base64EncodedKey);
SecretKey originalKey = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");