我有三个应用程序(.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/