例如,我想传入一个字符串"abc",然后输出加密字符串应该是 32 字节,当我想传递"abcdef"时,输出也应该是 32 字节。换句话说,我想要固定长度加密输出。我知道我的上限。就像我知道我的字符串永远不会超过 8 个字符一样。它最多为 8 个字符或少于 8 个字符。它永远不会超过 8。
如果有人在java Cipher中共享代码,那就太好了。
这取决于加密算法、模式和块大小。
例如,AES使用128位(16字节(的固定块大小,CBC和ECB模式将返回固定长度,该长度将是128的倍数。
如果您使用 ECB 模式并且输入字节数组长度为 10,则必须添加 6 个字节的填充才能完成该块。
填充块的方法有很多种,可以使用 PKCS5 或 PKCS7。
在java中,你可以使用Bouncy Castle的库 https://www.bouncycastle.org/确保使用安全的 IV 和派生的加密密钥
在以下示例中,填充由库处理
public byte[] genIV() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return iv;
}
public byte[] encrypt(byte[] plaintext, byte[] secretKey, byte[] iv) throws NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, BadPaddingException, IllegalBlockSizeException, InvalidAlgorithmParameterException, InvalidKeyException {
Cipher in = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
Key key = new SecretKeySpec(secretKey, "AES");
in.init(Cipher.ENCRYPT_MODE, key, new IvParameterSpec(iv));
return in.doFinal(plaintext);
}
public byte[] decrypt(byte[] ciphertext, byte[] secretKey, byte[] iv) throws InvalidAlgorithmParameterException, InvalidKeyException, NoSuchPaddingException, NoSuchAlgorithmException, NoSuchProviderException, BadPaddingException, IllegalBlockSizeException {
Key key = new SecretKeySpec(secretKey, "AES");
Cipher out = Cipher.getInstance("AES/ECB/PKCS5Padding", "BC");
out.init(Cipher.DECRYPT_MODE, key, new IvParameterSpec(iv));
return out.doFinal(ciphertext);
}
请记住,字符串中的每个字符(取决于字符集(长度至少为 8 位,在您的示例中,"abcdef"至少为 6 个字节长
您应该应用填充方案。填充方案旨在完成明文,以便它们可以适应分组密码的块大小。
您询问了 32 字节,这意味着 AES 两个加密块。您没有指定哪种类型的安全性,因此,我将考虑需要IV传输的CTR操作模式。
让 XX XX XX XX XX XX XX- XX 表示您的 8 字节字符串
例如 ANSI X.923 填充方案,附加 0 并在消息末尾附加消息的长度。然后
XX XX XX XX XX XX XX XX 00 00 00 00 00 00 00 08
将是您的明文。08 是明文的字节长度。
例如,PKCS#5 和 PKCS#7 填充方案,在消息的长度后附加重复,然后
XX XX XX XX XX XX XX XX 08 08 08 08 08 08 08 08
将是您的明文。
这些填充设计用于一个块。如果块已经满,它们会扩展下一个块。
解决 方案;
- 重新填充填充消息,您将获得两个块。
- 加密 CTR 中的加密消息,计数器递增。
- 为自己设计一个填充。