例如,我想传入一个字符串“abc”,然后输出加密字符串应该是 32 字节,当我想传递“abcdef”时,输出也应该是 32 字节。换句话说,我想要固定长度的加密输出。我知道我的上限。就像我知道我的字符串永远不会超过 8 个字符。最多 8 个字符或少于 8 个字符。它永远不会超过 8 个。
如果有人在 java Cipher 中共享代码,那就太好了。
例如,我想传入一个字符串“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 Bytes 这意味着用于 AES 两个加密块。您没有指定什么类型的安全性,所以我会考虑需要 IV 传输的 C TR 操作模式。
例如 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
将是您的明文。
这些填充设计用于一个块。如果块已满,它们会扩展下一个块。
解决方案;