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

Java 如何在android中安全地存储加密密钥?,java,android,security,encryption,keystore,Java,Android,Security,Encryption,Keystore,我想知道如何在Android中安全地存储加密密钥?保护加密和秘密密钥的最佳方案是什么 无法将加密密钥放入apk文件中。您可能希望将其保存在远程服务器中,并使用服务器进行解密。或者,您可能会对密钥进行编码并将其保存在不明显的位置,从而给其他人带来困难。但是没有防弹的解决方案。没有办法将您的私有api密钥安全地保存到代码中。但是你可以用 NDK安全地保存私钥。从NDK获取密钥并不是件小事 您可以使用Android密钥库系统来存储和检索敏感信息。 阅读这篇5分钟的文章,了解它是如何工作的。 根据您的评

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

无法将加密密钥放入apk文件中。您可能希望将其保存在远程服务器中,并使用服务器进行解密。或者,您可能会对密钥进行编码并将其保存在不明显的位置,从而给其他人带来困难。但是没有防弹的解决方案。

没有办法将您的私有api密钥安全地保存到代码中。但是你可以用
NDK安全地保存私钥。从NDK获取密钥并不是件小事

您可以使用Android密钥库系统来存储和检索敏感信息。 阅读这篇5分钟的文章,了解它是如何工作的。

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

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

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

  • API级别<18:Android密钥库不存在。向用户请求密码,从密码派生加密密钥,缺点是在应用程序启动时需要提示输入密码。加密密钥未存储在设备中。每次使用密码启动应用程序时都会计算该值

  • API级别>=18=23:Android密钥库提供AES支持。在Android密钥库中使用生成随机AES密钥。你可以直接使用它

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

备选方案:

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

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

听起来你想要或想要。这两种方法都使用。下面的代码片段实际上回答了“如何使用AndroidKeystore加密文件或存储加密密钥?”

确保在你的应用程序
build.gradle
文件中包含
实现“androidx.security:security crypto:1.0.0-rc02”

发件人:

加密密钥和值的一种实现

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

// 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
尽管使用它会更好


发件人:

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

注意:

主密钥一经创建,即为常量。因此,即使在手机重新启动后,您的应用程序仍然能够对文件进行加密/解密。

您是打算对磁盘上的内容进行加密,还是将加密文件存储在应用程序中?在第一种情况下,在运行时创建密钥并将其放入密钥库。在第二种情况下-不要将密钥放入应用程序中。最好的办法是从服务器上下载,但这样做仍然会留下截获的窗口。真的,两个人都是,如果有人足够努力,他们会得到它。最好不要在客户端手机上放置任何您不希望用户看到的信息。请给我一个在密钥中存储密钥的示例。如果您询问加密密钥以向服务器或其他用户发送数据(然后您可以在apk中安全地存储或下载非对称公钥),本地加密密钥,用于加密/解密设备中的数据,还是要加密与服务器的通信通道?我要求使用本地数据加密密钥。然后使用。它就是为此而设计的。你的问题是什么?教程?一些例子?androidKeyStore呢?如果加密密钥可以是运行时生成的随机字符串,那么可以使用KeyStore。但是,如果它是持久存取的,则可以从根存取设备读取。另一方面,C++不能被反编译,但可以被分解,这比java稍微不那么简单。它也不安全:(感谢分享有用的android加密信息。感谢你详尽的回答!谈到API级别“>=18<23”通过简单地将RSA私钥部分用作对称密钥,我们可以避免将AES密钥存储在SharedReferences中吗?@southerton,我认为您可以将HKDF之类的密钥派生函数应用于RSA密钥或对其进行散列(SHA256将提供32个随机字节)来获得足够安全的AES密钥。查看@pedrofb这篇文章的讨论,查看文档,我们可以看到“AES/CBC/PKCS7Padding”API 23下不支持,那么我们如何在API 23下使用它?@Rahussahni,
AndroidKeyStore
提供程序不支持它,但您仍然可以将AES与默认的加密提供程序一起使用,我可以在其中保存IV?根据我的经验,您需要使用相同的IV进行解密。因此,当加密完成时,您将使用IV,Convert将其rt到Base64编码,并通过放置一些分隔符和存储最终加密文本来附加加密数据,所以当您解密时,您将使用Base64编码IV附加您加密的文本,使用加密期间放置的分隔符将其拆分,您将获得Base64编码形式的IV,对其进行解码并用于解密。
// 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
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();