Java、Android 密钥库 - 提供未加密的 API 密钥或加密密钥
Java, Android Keystore - supply unencrypted API key or secret for encrypting
由于我是 Android 的新手,我正在努力隐藏我的 API 密钥并找到了 Android 密钥库。但是当我看到如何使用 Android Keystore 的示例时,我不明白的一件事是如何提供未加密的原始密钥进行加密?如果我存储在代码中,那不会超出使用 Android Keystore 的目的吗?
来自一篇关于存储秘密的文章:
https://medium.com/@ericfu/securely-storing-secrets-in-an-android-application-501f030ae5a3
- Generate a random key when the app runs the first time;
- When you want to store a secret, retrieve the key from KeyStore, encrypt the data with it, and then store the encrypted data in
Preferences.
- When you want to read a secret, read the encrypted data from Preferences, get the key from KeyStore and then use the key to decrypt
the data
第二点,它说用它加密数据。如何在不暴露给 code/application 的情况下提供数据?
如果有人回答,我深表歉意。
谢谢
private static final String KEYSTORE_PROVIDER = "AndroidKeyStore";
private static final String AES_MODE = "AES/GCM/NoPadding";
private static final String KEY_ALIAS = "MyNiceKey";
加载默认的 AndroidKeyStore:
KeyStore keyStore = KeyStore.getInstance(KEYSTORE_PROVIDER);
keyStore.load(null);
在KeyStore中生成AES密钥,在最新版本android中,它是hardware-backed密钥库;这意味着很难从中提取密钥的字节:
if (!keyStore.containsAlias(KEY_ALIAS)) {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_PROVIDER);
keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setRandomizedEncryptionRequired(false)
.build());
keyGenerator.generateKey();
}
无论如何你应该使用.setRandomizedEncryptionRequired(true)。没有必要设置错误的协议。否则,如果您只需要加密几个字节(您的 API 密钥),您可以创建一个非对称 public/private 密钥并使用 RSA 加密它,这样您甚至不需要提供 IV。
Haing 说,当您从 KeyStore 中获取密钥时:
public static SecretKey getKeyStoreSecretKeyEntry(final String entryAlias)
throws GeneralSecurityException, IOException {
return ((KeyStore.SecretKeyEntry) getKeyStore().getEntry(entryAlias, null)).getSecretKey();
}
返回的 SecretKey 不包含密钥 Material(密钥的实际字节),仅包含其引用。所以你可以在 Cipher 旁边自由使用它来加密和解密你想要的东西。在任何情况下,如果您使用它直接向您的服务发出 http 请求,您的 API 密钥将以任何方式暴露。在你的情况下最好的方法是使用像 Google Firebase
这样的服务器
P.s。 google 中有一个非常简单的库,可以节省您的时间和头痛:
https://developer.android.com/jetpack/androidx/releases/security
https://developer.android.com/topic/security/data
结论:您在 android 密钥库中生成的密钥是用户的 属性,应该用于保护用户的私人数据。因此,使用用户密钥加密 API 密钥(这是开发人员的私有数据)并不是一个好习惯。使用服务器保护 API 密钥。
由于我是 Android 的新手,我正在努力隐藏我的 API 密钥并找到了 Android 密钥库。但是当我看到如何使用 Android Keystore 的示例时,我不明白的一件事是如何提供未加密的原始密钥进行加密?如果我存储在代码中,那不会超出使用 Android Keystore 的目的吗?
来自一篇关于存储秘密的文章: https://medium.com/@ericfu/securely-storing-secrets-in-an-android-application-501f030ae5a3
- Generate a random key when the app runs the first time;
- When you want to store a secret, retrieve the key from KeyStore, encrypt the data with it, and then store the encrypted data in Preferences.
- When you want to read a secret, read the encrypted data from Preferences, get the key from KeyStore and then use the key to decrypt the data
第二点,它说用它加密数据。如何在不暴露给 code/application 的情况下提供数据? 如果有人回答,我深表歉意。
谢谢
private static final String KEYSTORE_PROVIDER = "AndroidKeyStore";
private static final String AES_MODE = "AES/GCM/NoPadding";
private static final String KEY_ALIAS = "MyNiceKey";
加载默认的 AndroidKeyStore:
KeyStore keyStore = KeyStore.getInstance(KEYSTORE_PROVIDER);
keyStore.load(null);
在KeyStore中生成AES密钥,在最新版本android中,它是hardware-backed密钥库;这意味着很难从中提取密钥的字节:
if (!keyStore.containsAlias(KEY_ALIAS)) {
KeyGenerator keyGenerator = KeyGenerator.getInstance(KeyProperties.KEY_ALGORITHM_AES, KEYSTORE_PROVIDER);
keyGenerator.init(new KeyGenParameterSpec.Builder(KEY_ALIAS,
KeyProperties.PURPOSE_ENCRYPT | KeyProperties.PURPOSE_DECRYPT)
.setBlockModes(KeyProperties.BLOCK_MODE_GCM)
.setEncryptionPaddings(KeyProperties.ENCRYPTION_PADDING_NONE)
.setRandomizedEncryptionRequired(false)
.build());
keyGenerator.generateKey();
}
无论如何你应该使用.setRandomizedEncryptionRequired(true)。没有必要设置错误的协议。否则,如果您只需要加密几个字节(您的 API 密钥),您可以创建一个非对称 public/private 密钥并使用 RSA 加密它,这样您甚至不需要提供 IV。
Haing 说,当您从 KeyStore 中获取密钥时:
public static SecretKey getKeyStoreSecretKeyEntry(final String entryAlias)
throws GeneralSecurityException, IOException {
return ((KeyStore.SecretKeyEntry) getKeyStore().getEntry(entryAlias, null)).getSecretKey();
}
返回的 SecretKey 不包含密钥 Material(密钥的实际字节),仅包含其引用。所以你可以在 Cipher 旁边自由使用它来加密和解密你想要的东西。在任何情况下,如果您使用它直接向您的服务发出 http 请求,您的 API 密钥将以任何方式暴露。在你的情况下最好的方法是使用像 Google Firebase
这样的服务器P.s。 google 中有一个非常简单的库,可以节省您的时间和头痛: https://developer.android.com/jetpack/androidx/releases/security
https://developer.android.com/topic/security/data
结论:您在 android 密钥库中生成的密钥是用户的 属性,应该用于保护用户的私人数据。因此,使用用户密钥加密 API 密钥(这是开发人员的私有数据)并不是一个好习惯。使用服务器保护 API 密钥。