Java PBKDF2WithHmacSHA1问题

时间:2013-12-17 21:01:14

标签: java android .net cryptography bouncycastle

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

使用RNG(例如

)生成密钥,iv和盐
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。

任何帮助将不胜感激。感谢。

1 个答案:

答案 0 :(得分:1)

问题源于这样的事实:PBKDF2被设计用于密码(文本)而不是密钥(随机字节序列不能形成有效的文本编码)。

遵循PKCS#5中的建议,密钥派生的第一步应该是使用UTF-8编码将密码文本转换为字节。 Java这样做,并且使用帖子中给出的特定密钥,编码是一个48字节的序列。但是,旧版本的Android(也许是.NET)不执行UTF-8编码;它们只是丢弃除了每个字符的低8位之外的所有字符,为您提供帖子中提供的32字节序列。

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

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