Java PBKDF2WithHmacSHA1 问题

标签 java android .net cryptography bouncycastle

我有三个应用程序(.NET、Android、Java)。所涉及的加密包括生成消息的三个应用程序之一以及 key 、IV 和盐以传递给其他两个。 .Net <-> Android 非常适合非对称和对称加密/解密,以及输出相同值的 key 生成函数。普通的 Java 版本给我带来了问题。

key 、iv 和盐是使用 RNG 生成的,例如

KeyGenerator kg = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
kg.init(len * 8, sr);
return kg.generateKey().getEncoded();

然后将其转换为要传递的十六进制字符串。当我在 Android 或 Java 上进行解密时,我将 key 的十六进制表示形式转换回 byte[] 并将其传递给如下所示的 SecretKey 函数。

public void SecretKey(byte[] key) {
    char[] ca = null;
    PBEKeySpec keySpec = null;
    SecretKeyFactory factory = null;

    _secretKey = null;
    try {
            ca = new char[key.length];  
            for (int x = 0; x < key.length; x++) {
                    ca[x] = (char)(key[x]);
            }
            keySpec = new PBEKeySpec(ca, _salt, 1024, 256);
            factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
            _secretKey = factory.generateSecret(keySpec);
    .
    .
    .

现在,在非 Android Java 版本上,我可以验证密码和 salt 是逐字节地与 .NET 和 Android 版本相同的,因此似乎不存在转换问题。但是,getEncoded() 键输出不同。

.Net
PW: 228 24 51 237 189 94 87 183 124 144 173 217 195 24 106 199 55 30 74 93 7 206 159 156 245 51 6 131 123 230 255 21 
Salt: 87 241 248 158 129 101 47 36 255 31 30 26 211 50 204 156 
Key: 204 26 176 226 255 40 25 163 60 85 75 208 230 192 214 150 136 5 155 55 228 199 98 36 230 84 210 6 164 113 48 128 

Java:
PW: 228 24 51 237 189 94 87 183 124 144 173 217 195 24 106 199 55 30 74 93 7 206 159 156 245 51 6 131 123 230 255 21 
Salt: 87 -15 -8 -98 -127 101 47 36 -1 31 30 26 -45 50 -52 -100 
Key: -55 6 -4 80 96 9 85 18 72 -43 24 -48 -48 94 17 -113 74 108 -124 -118 -42 -29 -83 -88 -70 11 47 -4 4 -108 11 17 

我正在使用 JDK1.7.0_45,安装了非限制性策略文件,并将 BouncyCaSTLe 1.50 设置为同时使用策略和代码路径的首选提供程序。

在 Android 上,我使用的是 SpongyCaSTLe,而 .Net 仅使用标准的 Microsoft CryptAPI。

如有任何帮助,我们将不胜感激。谢谢。

最佳答案

问题源于 PBKDF2 旨在用于密码(文本)而不是 key (不构成有效文本编码的随机字节序列)这一事实。

根据 PKCS #5 中的建议, key 派生的第一步应该是使用 UTF-8 编码将密码文本转换为字节。 Java 就是这样做的,并且使用帖子中给出的特定 key ,编码是一个 48 字节的序列。但是,旧版本的 Android(可能还有 .NET)不使用 UTF-8 编码;他们只是丢弃每个字符的低 8 位以外的所有内容,从而为您提供帖子中提供的 32 字节序列。

最新的 Android 版本(如 Java)使用 UTF-8 执行字符到字节的转换,并且需要使用不同的 key 派生算法才能与旧的 Android 版本互操作。

这些问题可以通过不尝试在这里使用 PBKDF2 来避免。它并没有提高安全性,它使您的代码难以编写和阅读,并且引入了许多互操作性缺陷。一切都没有好处。

关于Java PBKDF2WithHmacSHA1 问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20644570/

相关文章:

java - 结束调用此方法的方法

java - 找不到 java.nio.file.Path 的类文件

javascript - 从 API 获取数据时如何存储数据

c# - 如何在 UWP 中散列文件(MD5、SHA..v.v..)

c# - 为重负载任务设置低线程优先级

Java 8 Streams 多重分组依据

java - 当我调用 repaint() 方法时,屏幕上没有显示任何内容

android - 如何设置软键盘到EditText的距离?

android - 在应用程序/任务级别获取 onPause 和 onResume 类事件

.net - .net 中的 PostgreSQL 提供程序,支持 TransactionScope