如何在android中安全地存储加密密钥?

时间:2017-10-05 05:41:16

标签: java android security encryption keystore

我想知道如何在Android中安全地存储加密密钥?保护加密和密钥的最佳方案是什么?

5 个答案:

答案 0 :(得分:24)

根据您的评论,您需要使用当前Android版本和旧版本的本地密钥加密数据

Android Keystore旨在生成并保护您的密钥。但它不适用于低于18的API级别,并且在API级别23之前有一些限制。

您需要一个随机对称加密密钥,例如AES。 AES密钥用于加密和解密数据。我将总结您根据Android API级别安全生成和存储它的选项。

  • API级别< 18:Android Keystore不存在。向用户请求密码,从密码中获取加密密钥,缺点是您需要在应用程序启动时提示输入密码。加密密钥不存储在设备中。每次使用密码

  • 启动应用程序时计算
  • API级别> = 18< 23:不支持AES的Android密钥库。使用默认加密提供程序(不使用AndroidKeystore)生成随机AES密钥。在Android Keystore中生成RSA密钥对,并使用RSA公钥加密AES密钥。将加密的AES密钥存储到Android SharedPreferences中。应用程序启动时,使用RSA私钥解密AES密钥

  • API级别> = 23:支持AES的Android密钥库。使用Android Keystore生成随机AES密钥。您可以直接使用它。

加密可以使用AES/CBC/PKCS7Padding算法。它还需要一个随机初始化向量(IV)来加密您的数据,但它可以是公共的。

替代方案:

  • API级别> 14:Android密钥链:KeyChain是一个系统范围的凭据存储。您可以使用可供应用程序使用的私钥安装证书。使用预安装的密钥加密/解密您的AES密钥,如上面的第二种情况所示。

  • 外部令牌:受保护的密钥未存储在设备中。您可以使用包含私钥/公钥对的外部令牌,该令牌允许您加密AES密钥。可以使用蓝牙或NFC

  • 来加入令牌

答案 1 :(得分:3)

您不能将加密密钥放在apk文件中。您可能希望将其保留在远程服务器中并使用服务器进行解密。或者通过对密钥进行编码并将其保存在非显而易见的位置,可能会使其他人难以理解。但是没有针对此的防弹解决方案。

答案 2 :(得分:1)

无法将私人API密钥安全地保存到代码中。但你可以使用 NDK可以安全地保存私钥。从NDK获取密钥并非易事。 Secue Key With NDK Example

答案 3 :(得分:1)

听起来像您想要EncryptedSharedPreferencesEncryptedFile。这两个都使用AndroidKeyStore。下面的代码段实际上回答了“如何使用AndroidKeystore加密文件或存储加密密钥?”这个问题。

请确保在您的应用implementation "androidx.security:security-crypto:1.0.0-rc02"文件中包含build.gradle

来自EncryptedSharedPreferences

SharedPreferences的实现,用于加密键和值。

String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);

SharedPreferences sharedPreferences = EncryptedSharedPreferences.create(
  "secret_shared_prefs",
  masterKeyAlias,
  context,
  EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
  EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
);

// use the shared preferences and editor as you normally would
SharedPreferences.Editor editor = sharedPreferences.edit();

您可以存储这样的加密密钥:

// generate random symmetric key
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256);
SecretKey symkey = keyGen.generateKey();


String alias = "your encryption key";

// store symmetric key
byte[] encodedSymmetricKey = symkey.getEncoded();
SharedPreferences.Editor edit = sharedPreferences.edit();
String base64EncodedSymmetricKey = new String(Base64.getEncoder().encode(encodedSymmetricKey));
edit.putString(alias, base64EncodedSymmetricKey);
edit.commit();

// retrieve symmetric key
String raw = sharedPreferences.getString(alias, null);
byte[] symKey = Base64.getDecoder().decode(raw);
SecretKeySpec spec = new SecretKeySpec(symKey, "AES");

assert(spec.equals(symkey));

// use your encryption key

尽管使用EncryptedFile会更好。


来自EncryptedFile

用于创建和读取加密文件的类。

String masterKeyAlias = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC);

File file = new File(context.getFilesDir(), "secret_data");
EncryptedFile encryptedFile = EncryptedFile.Builder(
  file,
  context,
  masterKeyAlias,
  EncryptedFile.FileEncryptionScheme.AES256_GCM_HKDF_4KB
).build();

// write to the encrypted file
FileOutputStream encryptedOutputStream = encryptedFile.openFileOutput();

// read the encrypted file
FileInputStream encryptedInputStream = encryptedFile.openFileInput();

注释:
主密钥一旦创建,便保持不变。因此,即使在电话重启后,您的应用仍然可以加密/解密文件。

答案 4 :(得分:0)

您可以使用Android Keystore系统存储和检索敏感信息。 阅读这篇5分钟的文章,了解它的工作原理。 Using the Android Keystore system to store and retrieve sensitive information