【问题标题】:Android and Java key generation return different resultsAndroid 和 Java 密钥生成返回不同的结果
【发布时间】:2018-04-09 07:41:40
【问题描述】:

我遇到了以下问题。我的应用程序分为两个不同的部分:1)第一部分使用 AES/CBC(Java)加密一些数据,2)第二部分必须检索数据并解密(Android)。 要生成密钥,我使用以下代码

SecureRandom saltRand = new SecureRandom(new byte[] { 1, 2, 3, 4 });
byte[] salt = new byte[16];
saltRand.nextBytes(salt);

SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
KeySpec spec = new PBEKeySpec("password".toCharArray(), salt, 1024, 128);
SecretKey key = factory.generateSecret(spec);

SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
sr.setSeed(key.getEncoded());
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128, sr);
sksCrypt = new SecretKeySpec((kg.generateKey()).getEncoded(), "AES");

我的程序不需要不同的“源密钥”(字符串密码),但是只要源密钥相同,它就需要计算相同的密钥。不幸的是,程序的两部分生成的密钥不同,解密阶段失败。 有关如何解决此问题的任何建议?

【问题讨论】:

  • 盐必须相同。

标签: java android encryption aes


【解决方案1】:

您正在使用随机密钥生成器从给定的输入密钥材料生成密钥。 密钥派生函数是从秘密中派生密钥的函数。有基于密码的密钥派生函数,例如 PBKDF2,它使用密码(加上盐和特定的迭代次数)作为秘密输入。还有一些基于密钥的密钥派生函数,例如 HKDF,它使用密钥和可能的标签或其他输出密钥特定信息作为输入材料。

Java 确实为您提供了一组 PBKDF,PBKDF1 和 PBKDF2,其中 PBKDF2 是您当前使用的较新的。不幸的是,它没有提供开箱即用的 KBKDF。您需要使用(轻量级)Bouncy Castle API 来提供这种功能。我知道是因为我为 Bouncy 提供了各种 KBKDF 的初始实现。

不幸的是,使用SecureRandom 作为替换 KBKDF 不起作用,正如您所发现的那样。 SHA1PRNG算法没有指定好;它是一个依赖于 SHA-1 安全散列函数的函数,仅此而已。因此,实现可以并且确实有所不同,例如在 Android(松散地基于 GNU 类路径)和 Oracle 的 Java 之间。 SHA1PRNG 可能会也可能不会完全依赖种子。在较新的 Android 版本中,它甚至可能被完全不同的东西所取代。

由于您只从输入的密钥材料中派生一个密钥,您不妨直接将key.getEncoded()SecretKeySpec 包装起来,并将其用作密钥。根本不需要执行额外的密钥生成;您已经使用 PBKDF2 派生了一个密钥。额外的包装对密钥材料没有任何作用。 可能只需将算法设置为例如"AES"

【讨论】:

  • 感谢您的回答!既然你知道 Bouncy Castle 包,你能建议我一些链接、文档或任何东西来开始使用它的 API 编程吗?我在互联网上搜索了很多,但我没有找到任何可以清楚地解释它的用法。
猜你喜欢
  • 1970-01-01
  • 2017-10-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-02
相关资源
最近更新 更多