我在我的Android应用程序中使用以下代码使用带有三个独立键的加密代码簿(ECB)模式加密Triple DES中的字符串(又名 3DESede < / em>),它们是一个24字节大小的密钥数组。因此我使用Java Crypto API。这很好用,但是如果我加密一个8字符的字符串,我得到一个16字节的密文,这不应该发生,因为3DES在64位(相应的8字节)的块上运行。同样适用于PKCS5 padding,因为这也适用于64位的块。所以我的问题是导致这个问题的原因是什么?
private static byte[] encryptText(String plaintext, byte[] keyBytes) throws Exception {
// Get plaintext as ASCII byte array
final byte[] plainBytes;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
plainBytes = plaintext.getBytes(StandardCharsets.US_ASCII);
} else {
plainBytes = plaintext.getBytes("US-ASCII");
}
// Generate triple DES key from byte array
final DESedeKeySpec keySpec = new DESedeKeySpec(keyBytes);
SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");
SecretKey key = keyFactory.generateSecret(keySpec);
// Setup the cipher
final Cipher c3des = Cipher.getInstance("DESede/ECB/PKCS5Padding");
c3des.init(Cipher.ENCRYPT_MODE, key);
// Return ciphertext
return c3des.doFinal(plainBytes);
}
答案 0 :(得分:1)
PKCS5Padding 在与DES一起使用时添加1-8个字节的填充。如果你加密8个字节,你将得到8个额外的填充字节,以获得偶数个块。
如果您使用Cipher.getInstance("DES/ECB/NoPadding")
并加密了8个字节,您将获得8个字节的密文。
答案 1 :(得分:1)
当使用PKCS#5填充时,它必须始终添加填充,否则在解密时将无法确定是否添加了填充。因此,即使输入数据是块大小的精确倍数,也必须添加填充,这将是8个字节。
请参阅PKCS padding:
如果原始数据是N个字节的整数倍,则添加具有值N的额外字节块。这是必要的,因此解密算法可以确定地确定最后一个块的最后一个字节是填充字节,指示添加的填充字节的数量或明文消息的一部分。考虑一个明文消息,它是N个字节的整数倍,明文的最后一个字节是01.没有附加信息,解密算法将无法确定最后一个字节是明文字节还是填充字节。但是,通过在01明文字节之后添加每个值N的N个字节,解密算法总是可以将最后一个字节作为填充字节处理,并从密文的末尾剥去适当数量的填充字节;所述要根据最后一个字节的值去掉的字节数。
PKCS#5填充与PKCS#7填充相同,只是它仅为使用64位(8字节)块大小的块密码定义。在实践中,这两者可以互换使用。