使用 PKS5 填充 javax.crypto 的 3DESede 时密文长度错误
Wrong cipher text length when using 3DESede with PKS5 padding of javax.crypto
我在我的 android 应用程序中使用以下代码来加密 Triple DES using the Encrypted Code Book (ECB) mode with three independent keys (aka 3DESede), which are provided as a 24 byte sized key array. Therefore I use the Java Crypto API. This works pretty well, but if I encrypt an eight character string I get a 16 byte cipher text, which should not happen as 3DES operates on chunks of 64 bit (resp. 8 byte). Same holds for the 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);
}
PKCS5Padding 在与 DES 一起使用时添加 1-8 个字节的填充。如果您加密 8 个字节,您将获得 8 个额外的填充字节以获得偶数个块。
如果您使用Cipher.getInstance("DES/ECB/NoPadding")
并加密8个字节,您将得到8个字节的密文。
当使用 PKCS#5 填充时,它必须始终添加填充,否则在解密时将无法确定是否添加了填充。因此,即使输入数据是块大小的精确倍数,也必须添加填充,这将是 8 个字节。
If the original data is an integer multiple of N bytes, then an extra block of bytes with value N is added. This is necessary so the deciphering algorithm can determine with certainty whether the last byte of the last block is a pad byte indicating the number of padding bytes added or part of the plaintext message. Consider a plaintext message that is an integer multiple of N bytes with the last byte of plaintext being 01. With no additional information, the deciphering algorithm will not be able to determine whether the last byte is a plaintext byte or a pad byte. However, by adding N bytes each of value N after the 01 plaintext byte, the deciphering algorithm can always treat the last byte as a pad byte and strip the appropriate number of pad bytes off the end of the ciphertext; said number of bytes to be stripped based on the value of the last byte.
PKCS#5 padding is identical to PKCS#7 padding, except that it has only been defined for block ciphers that use a 64-bit (8 byte) block size. In practice the two can be used interchangeably.
我在我的 android 应用程序中使用以下代码来加密 Triple DES using the Encrypted Code Book (ECB) mode with three independent keys (aka 3DESede), which are provided as a 24 byte sized key array. Therefore I use the Java Crypto API. This works pretty well, but if I encrypt an eight character string I get a 16 byte cipher text, which should not happen as 3DES operates on chunks of 64 bit (resp. 8 byte). Same holds for the 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);
}
PKCS5Padding 在与 DES 一起使用时添加 1-8 个字节的填充。如果您加密 8 个字节,您将获得 8 个额外的填充字节以获得偶数个块。
如果您使用Cipher.getInstance("DES/ECB/NoPadding")
并加密8个字节,您将得到8个字节的密文。
当使用 PKCS#5 填充时,它必须始终添加填充,否则在解密时将无法确定是否添加了填充。因此,即使输入数据是块大小的精确倍数,也必须添加填充,这将是 8 个字节。
If the original data is an integer multiple of N bytes, then an extra block of bytes with value N is added. This is necessary so the deciphering algorithm can determine with certainty whether the last byte of the last block is a pad byte indicating the number of padding bytes added or part of the plaintext message. Consider a plaintext message that is an integer multiple of N bytes with the last byte of plaintext being 01. With no additional information, the deciphering algorithm will not be able to determine whether the last byte is a plaintext byte or a pad byte. However, by adding N bytes each of value N after the 01 plaintext byte, the deciphering algorithm can always treat the last byte as a pad byte and strip the appropriate number of pad bytes off the end of the ciphertext; said number of bytes to be stripped based on the value of the last byte.
PKCS#5 padding is identical to PKCS#7 padding, except that it has only been defined for block ciphers that use a 64-bit (8 byte) block size. In practice the two can be used interchangeably.