AES / CFB / PKCS5Padding在不同的Android版本上表现不同

时间:2016-09-08 23:17:41

标签: android encryption

我有这个加密功能:

String Encrypt(String text, byte[] keyBytes) throws Exception {
    Cipher cipher = Cipher.getInstance("AES/CFB/PKCS5Padding");
    SecretKeySpec keySpec = new SecretKeySpec(keyBytes, "AES");
    IvParameterSpec ivSpec = new IvParameterSpec("AAAAAAAAAAAAAAAA".getBytes("UTF-8"));
    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);

    byte[] results = cipher.doFinal(text.getBytes("UTF-8"));
    return Base64.encodeToString(results, Base64.URL_SAFE);
}

在大多数Android设备上,它都能正常运行。但是,在某些旧设备上(注3,LG G2,Android 4.4),它不会加密。

这是两个设备之间的比较。 Note3加密错误,Nexus 6没问题。

Note 3
---------
String to encrypt: Hello, world
Encryption key: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
Encryption result bytes: [108, -63, -66, 117, 62, -78, -108, 22, 12, -128, 119, 22]
Encryption result Base64: bMG-dT6ylBYMgHcW

Nexus 6
---------
String to encrypt: Hello, world
Encryption key: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
Encryption result bytes: [108, -63, -66, 117, 62, -78, -108, 22, 12, -128, 119, 22, 89, -73, -23, 114]
Encryption result Base64: bMG-dT6ylBYMgHcWWbfpcg==

这是一个已知的错误吗?我可以做些什么来解决这个问题?

2 个答案:

答案 0 :(得分:1)

CFB mode of operation是一种流模式,这意味着它不需要填充。因此,旧版本似乎只是忽略了您对PKCS#7填充的请求(与PKCS#5填充相同)。

您有两种选择:

  • Cipher.getInstance("AES/CFB/PKCS5Padding")更改为Cipher.getInstance("AES/CFB/NoPadding"),以便所有版本都生成缩短的输出。
  • 如果您确实需要填充,可以使用Cipher.getInstance("AES/CFB/NoPadding")并在加密前手动添加填充,并在解密后将其删除。所有padding bytes都有一个值,表示有多少填充字节。

当然,如果你已经有一个版本,你真的不应该改变任何东西,因为这只会给那些使用"行为不端的用户带来错误。设备

答案 1 :(得分:0)

在此处看到上一篇文章:StackOverflow

立即开始想知道你的缓冲区大小以及你如何转换。

Note3和Nexus6在16位字符的Base64字符串中显示相同的结果,但Note3的“结果字节”不包含那么多字节!

你能验证字节数组的长度是否相同,而Note3实际上是否截断了丢失的4个字节?或者,以固定长度16创建两者并在加密后检查。