Android:在KeyStore中存储SecretKey

时间:2016-04-19 06:26:57

标签: android encryption keystore android-keystore secret-key

我使用SecretKey加密应用程序中的敏感数据。目前我将我的SecretKey以Base64编码格式存储在DB或SharedPrefs中,这不是在根电话上存储Secret的安全位置。因此,我想将我的SecretKey移动到Android KeyStore。我面临的问题是当我从Google尝试this sample code时,它需要一个PrivateKey而不是SecretKey。我无法找到一种方法将我的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

任何示例代码都会有很大的帮助。

2 个答案:

答案 0 :(得分:5)

WRONG
java.security.KeyStore可以存储对称和非对称密钥。您只需要实例化KeyStore.SecretKeyEntry,在构造函数中传递SecretKey,然后使用KeyStore #setEntry方法保存它:

ftp.setFileType(FTP.BINARY_FILE_TYPE);

要将其恢复使用:

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());

更新
经过一些研究后,我惊讶地发现,AndroidKeyStore并不支持对称密钥。 (参见讨论:https://groups.google.com/forum/#!topic/android-developers/gbmIRKRbfq8

答案 1 :(得分:0)

解决方法是加密您的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");