我使用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
。
任何示例代码都会有很大的帮助。
答案 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");