服务器无法解密Android 4.2发送的邮件

时间:2014-05-26 23:38:41

标签: java android encryption cryptography

在查看Android 4.2及更高版本中的加密问题后,我们会查看许多问题和答案(具体来说,4.2之前加密的事情不能再在4.2中解密)但是没有一个答案似乎适合我的情况。

我们有一个服务器端系统,它接受来自我们各种设备客户端(无论是Javascript,iOS,Android还是Windows)的AES加密有效负载,解密数据,然后......做任何需要的事情。在我们最近将我们的Android客户端升级到API级别19之前,这一直工作正常。现在服务器(用C#编写并使用标准的.NET加密库)无法再解密消息,因为PKCS5Padding已损坏。所有其他客户端继续使用服务器就好了。

这是我们的加密方法:

private static String encryptString(String plainText, byte[] key, byte[] salt, byte[] iv) {
    try{
        SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");

        KeySpec keyspec = new PBEKeySpec(keyToCharArray(key), salt,
                getEncryptionKeyIterations(), 256);
        SecretKey secretKey = factory.generateSecret(keyspec);

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(secretKey.getEncoded(), "AES")
                , new IvParameterSpec(iv));

        return Base64.encodeToString(cipher.doFinal(plainText.getBytes()), Base64.NO_WRAP);
    } catch(Exception ex) {
        Log.e(TAG, "Unable to encrypt message", ex);
        throw new InvalidDataException("Unable to encrypt message");
    }
}

使用以下方法生成IV:

public static byte[] getRandomIv() throws InvalidDataException {
    try {
        KeyGenerator kgen = KeyGenerator.getInstance("AES");
        SecureRandom sr = SecureRandom.getInstance("SHA1PRNG");
        kgen.init(128, sr);
        return kgen.generateKey().getEncoded();
    } catch(Exception ex) {
        Log.e(TAG, "Unable to create random IV", ex);
        throw new InvalidDataException("Unable to create random IV");
    }
}

我在这里看到的一些帖子说用SecureRandom.getInstance替换SecureRandom.getInstance(" SHA1PRNG")(" SHA1PRNG"," Crypto" )使用Java Crypto而不是OpenSSL。对我们来说,这对另一端的解密没有任何影响。

我也尝试过切换到SpongyCastle,但这并没有解决问题。

我们提供的密钥是用户密码,用已知的盐腌制,然后SHA256散列。这也是服务器上的已知数量,其中密钥在解密之前使用相同的算法加强。

修改

看来它可能确实是IV代。听起来很奇怪,只需使用SecureRandom切换到更简单的IV代似乎"修复"问题。

1 个答案:

答案 0 :(得分:1)

似乎问题是IV代。虽然原始代码生成128位密钥(带KeyGenerator的AES输出128位密钥,按照http://docs.oracle.com/javase/7/docs/api/javax/crypto/KeyGenerator.html),但它似乎不再正常工作。

将代码更改为:

public static byte[] getRandomIv() throws InvalidDataException {
    try {
        SecureRandom sr = new SecureRandom();
        byte[] output = new byte[16];
        sr.nextBytes(output);
        return output;
    } catch(Exception ex) {
        Log.e(TAG, "Unable to create random IV", ex);
        throw new InvalidDataException("Unable to create random IV");
    }
}

让库解密来自服务器的消息并成功登录。我们在一系列API级别上测试了这个,返回到API级别10,它运行良好。谢谢你的帮助。