当前位置: 首页 > 知识库问答 >
问题:

Android和Java密钥生成返回不同的结果

温智明
2023-03-14

我有以下问题。我的应用程序分为两部分: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");

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

共有1个答案

米俊喆
2023-03-14

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

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

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

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

 类似资料:
  • 我正在尝试用Java编写一个简单的密码管理器。我想用AES 256位加密用存储的密码加密文件。此外,我希望用户能够解密的文件与密码。当阅读其他在线帖子时,他们几乎都强调简单地使用密码作为密钥是不安全的,他们提到使用随机盐来增加安全性。但我不明白如何在生成密钥时使用随机盐。如果我从用户的密码和随机的salt创建密钥,那么当他们试图解密他们的文件时,我怎么知道salt是什么呢?这让我完全糊涂了。 目前

  • 我正在尝试创建一个公钥以允许我推送到Git,但我的. ssh文件夹尚未创建。 以下是我运行的命令: $ssh-keygen-t rsa-Cemaill@me.com 生成公共/私有rsa密钥对 输入保存密钥的文件(/h/.ssh/id\u rsa): 这就是H:驱动器配置、数据、配置文件、配置文件中的全部内容。V2 我认为有一个问题,因为当我得到提示输入文件,其中保存密钥(/h//. ssh/id

  • 我一直在尝试在AWS Lambda上生成一个RSA密钥对,以取代当前在PuTTYgen上手动生成的密钥。PuTTYgen上生成的密钥是RSA类型,长度为2048,这将生成一个示例密钥(无注释),如下所示- 现在我一直在尝试用下面的代码在NodeJS lambda上复制相同的代码- 在执行此lambda时,生成的公钥如下所示- 就我对RSA密钥的理解而言,第一行和最后一行不应该有任何区别,因为它们基

  • 我在将包含RSA公钥的字符串转换为java.security公钥类型时遇到了麻烦,该RSA公钥是我在cygwin中使用SSh-keygen生成的。 那么,我假设我的问题是两个密钥之间有什么区别,以及我如何才能成功地将第一个转换为可用的PublicKey对象?

  • 问题内容: 我正在尝试使用广泛使用的SimpleCrypto Java类在Java(Android)中加密字符串,并在ColdFusion 9中解密字符串(反之亦然)。我已经将完全相同的SimpleCrypto类导入到ColdFusion中,并这样称呼它: 使用密钥“ apple”对字符串“ john”进行加密时,它将在CF中输出:9E90A36325AE4F4F7352D6469A7068A2

  • 问题内容: 我正在使用HSM和PKCS11处理密钥派生问题,目前我无法理解为什么我会看到完全不同的结果,这取决于我是否使用generateKey()方法,而不是使用crypto()方法。在这两种情况下,我都尝试将DESede / ECB / NoPadding算法用于结果,但是根据我用来生成结果的方法(deriveKey与加密),我看到了不同的结果。 退后一会儿,以给出高层次的概述…我正在使用Gl