简体   繁体   English

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

[英]how to securely store encryption keys in android?

I want to know how to securely store encryption key in Android?我想知道如何在 Android 中安全地存储加密密钥 What is the best scenario to protect encryption and secrete keys?保护加密和秘密密钥的最佳方案是什么?

From your comments, you need to encrypt data using a local key for current Android versions and the old ones根据您的评论,您需要使用当前 Android 版本和旧版本的本地密钥加密数据

Android Keystore is designed to generate and protect your keys. Android Keystore旨在生成和保护您的密钥。 But it is not available for API level below 18 and it has some limitations until API level 23.但是它不适用于低于 18 的 API 级别,并且在 API 级别 23 之前它有一些限制。

You will need a random symmetric encryption key, for example AES.您将需要一个随机对称加密密钥,例如 AES。 The AES key is used to encrypt and decrypt you data. AES 密钥用于加密和解密您的数据。 I'm going to summarize your options to generate and store it safely depending on Android API level.我将总结您根据 Android API 级别安全生成和存储它的选项。

  • API Level < 18: Android Keystore not present . API 级别 < 18:Android 密钥库不存在 Request a password to the user, derive an encryption key from the password, The drawback is that you need to prompt for the password when application starts.向用户请求密码,从密码推导出加密密钥,缺点是需要在应用程序启动时提示输入密码。 The encryption key it is not stored in the device.加密密钥不存储在设备中。 It is calculated each time when the application is started using the password每次启动应用程序时使用密码计算

  • API Level >=18 <23: Android Keystore available without AES support . API 级别 >=18 <23:Android Keystore 可用,无需 AES 支持 Generate a random AES key using the default cryptographic provider (not using AndroidKeystore).使用默认加密提供程序(不使用 AndroidKeystore)生成随机 AES 密钥。 Generate a RSA key pair into Android Keystore, and encrypt the AES key using RSA public key.生成 RSA 密钥对到 Android Keystore 中,并使用 RSA 公钥加密 AES 密钥。 Store encrypted AES key into Android SharedPreferences.将加密的 AES 密钥存储到 Android SharedPreferences 中。 When application starts, decrypt the AES key using RSA private key应用程序启动时,使用 RSA 私钥解密 AES 密钥

  • API Level >=23: Android Keystore available with AES support . API 级别 >=23:支持 AES 的 Android 密钥库 Generate a random AES key using into Android Keystore.使用到 Android Keystore 生成随机 AES 密钥。 You can use it directly.您可以直接使用它。

To encrypt to can use AES/CBC/PKCS7Padding algorithm.加密可以使用AES/CBC/PKCS7Padding算法。 It requires also a random initialization vector (IV) to encrypt your data, but it can be public.它还需要一个随机初始化向量 (IV) 来加密您的数据,但它可以是公开的。

Alternatives:替代品:

  • API level >14: Android Key Chain : KeyChain is a system-wide credential storage. API 级别 >14:Android Key Chain :KeyChain 是系统范围的凭证存储。 You can install certificates with private keys that can be used by applications.您可以使用可由应用程序使用的私钥安装证书。 Use a preinstalled key to encrypt/decrypt your AES key as shown in the second case above.使用预先安装的密钥来加密/解密您的 AES 密钥,如上面的第二种情况所示。

  • External token : The protected keys are not stored in the device.外部令牌:受保护的密钥不存储在设备中。 You can use an external token containing a private/public key pair that allows you to encrypt the AES key.您可以使用包含私钥/公钥对的外部令牌来加密 AES 密钥。 The token can be accesed using bluetooth or NFC可以使用蓝牙或 NFC 访问令牌

You cannot place the encryption key inside your apk file.您不能将加密密钥放在您的 apk 文件中。 You may want to keep it in a remote server and decrypt using server.您可能希望将其保存在远程服务器中并使用服务器解密。 Or you may make it difficult for others by encoding the key and keeping it in non-obvious places.或者,您可能会通过对密钥进行编码并将其保存在不明显的地方而让其他人感到困难。 But there's no bullet proof solution for this.但是对此没有防弹解决方案。

There is no way to securely save your private api keys into code.没有办法将您的私有 api 密钥安全地保存到代码中。 But you can use NDK to securely save private keys.但是您可以使用 NDK 来安全地保存私钥。 It is not trivial to get key from NDK.从 NDK 获取密钥并非易事。 Secue Key With NDK Example 使用 NDK 示例保护密钥

It sounds like you want EncryptedSharedPreferences or EncryptedFile .听起来您想要EncryptedSharedPreferencesEncryptedFile Both of these use the AndroidKeyStore .这两个都使用AndroidKeyStore The code snippets below actually answer the question "How do I use the AndroidKeystore to encrypt a file or store a cryptographic key?"下面的代码片段实际上回答了“如何使用 AndroidKeystore 加密文件或存储加密密钥?”的问题。

Make sure to include implementation "androidx.security:security-crypto:1.0.0-rc02" in your app build.gradle file.确保在您的应用build.gradle文件中包含implementation "androidx.security:security-crypto:1.0.0-rc02"

from EncryptedSharedPreferences :来自EncryptedSharedPreferences

An implementation of SharedPreferences that encrypts keys and values.加密密钥和值的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();

You could store an encryption key like this:您可以像这样存储加密密钥:

// 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

Although it would be much better to use EncryptedFile .虽然使用EncryptedFile会好得多。


from EncryptedFile :来自EncryptedFile

Class used to create and read encrypted files.用于创建和读取加密文件的类。

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

note:注意:
The master key, once created, is constant.主密钥一旦创建,就是恒定的。 So even after a phone reboot your app will still be able to encrypt/decrypt the file.因此,即使在手机重启后,您的应用程序仍然能够加密/解密文件。

You can use Android Keystore system to store and retrieve sensitive information.您可以使用 Android Keystore 系统来存储和检索敏感信息。 Read this 5 minute article to understand how it works.阅读这篇 5 分钟的文章,了解它是如何工作的。 Using the Android Keystore system to store and retrieve sensitive information 使用 Android Keystore 系统存储和检索敏感信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM