【发布时间】:2014-01-05 19:55:15
【问题描述】:
我有三个应用程序(.NET、Android、Java)。所涉及的加密由三个应用程序之一生成消息以及密钥、IV 和盐,以传递给其他两个。 .Net Android 完美适用于非对称和对称加密/解密,以及输出相同值的密钥生成函数。普通的 Java 版本给我带来了问题。
密钥、iv 和 salt 是使用 RNG 生成的,例如
KeyGenerator kg = KeyGenerator.getInstance("AES");
SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
kg.init(len * 8, sr);
return kg.generateKey().getEncoded();
然后将其转换为要传递的十六进制字符串。当我在 Android 或 Java 上进行解密时,我将密钥的十六进制表示转换回 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。
任何帮助将不胜感激。谢谢。
【问题讨论】:
-
您可以使用
new BigInteger(1, bytes).toString(16);或org.bouncycastle.util.encoders.Hex之类的东西来提高字节数组的可读性。 -
问题在于 Java 中的 PBKDF 功能并不是真正为处理字节而设计的。这实际上很愚蠢,因为它使您无法使用自己的字符编码。要使上述代码正常工作(我不知道它应该做什么),请确保密码库 KDF 的输入使用相同的密码。
-
密钥派生函数主要用于基于密码的加密。您正在使用随机生成的密钥——在这种情况下,通过 PBKDF2 运行它们并不会真正添加任何内容。
-
@owlstead - 同意不处理字节的愚蠢。但就像我的帖子所说的那样,我已经验证了输入以确保它们是相同的。
-
通过散列函数运行输入不会增加任何熵 (crypto.stackexchange.com/questions/4037/…)。昂贵的密钥派生函数的目的是使某些暴力攻击更加困难。这种攻击对随机生成的密钥是不合理的。我还想指出,SecureRandom 很可能对此“足够随机”,您不必担心。
标签: java android .net cryptography bouncycastle