不带填充的 Java AES

2022-09-04 00:48:57

在没有自动填充的情况下,AES加密和解密16字节数组的最简单方法是什么?我已经找到了使用外部库的解决方案,但如果可能的话,我想避免这种情况。

我当前的代码是

SecretKeySpec skeySpec = new SecretKeySpec(getCryptoKeyByteArray(length=16)); // 128 bits
Cipher encryptor = Cipher.getInstance("AES");
encryptor.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = encryptor.doFinal(plain);

如何防止填充?数据始终是固定长度,并包含自己的填充。我怎样才能允许为16字节而不导致成为32字节?plainplainencrypted


答案 1

请参阅我的评论。对不起,我可能应该第一次仔细看看。

  1. 更改为"AES""AES/CBC/NoPadding"
  2. 更改为decryptor.init(Cipher.DECRYPT_MODE, skeySpec);decryptor.init(Cipher.DECRYPT_MODE, skeySpec, encryptor.gerParameters());

若要使用不需要保存初始化向量的方法,仅使用 16 字节的固定长度数据进行加密,请将更改为"AES""AES/ECB/NoPadding"

我选择欧洲央行,因为这是默认设置

如果您需要加密超过16个字节,请考虑使用ECB以外的其他方法,该ECB存在一定的重复检测缺陷

在此位图示例中,此图像具有重复的白色块,因此您只需查找块变得不同的位置即可推断出图像的轮廓。

before encryptionencrypted

如果您只加密一个区块,那并不重要,只有当您加密组合的多个区块时,ECB才会变得具有启示性。

相关: https://security.stackexchange.com/questions/15740/what-are-the-variables-of-aes


答案 2

同意@rossum,但还有更多内容:

CTR 模式需要初始化向量 (IV)。这是一个“计数器”(这就是“CTR”所指的)。如果您可以单独存储IV(它不需要受到保护),那就可以了。解密数据时,您将需要相同的 IV 值。

如果您不想存储 IV,并且可以保证不会使用相同的密钥加密两个值,则可以使用固定的 IV(甚至是 0 的数组)。

上述内容非常重要,因为使用相同的密钥/IV 组合加密多个消息会破坏安全性。请参阅此维基百科文章中的初始化向量(IV)部分:http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation

代码的 AES CTR 实现可能是:

SecretKeySpec skeySpec = new SecretKeySpec(getCryptoKeyByteArray(length=16)); 
Cipher encryptor = Cipher.getInstance("AES/CTR/NoPadding");

// Initialisation vector:
byte[] iv = new byte[encryptor.getBlockSize()];
SecureRandom.getInstance("SHA1PRNG").nextBytes(iv); // If storing separately
IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

encryptor.init(Cipher.ENCRYPT_MODE, skeySpec, ivParameterSpec); 
byte[] encrypted = encryptor.doFinal(plain); 

推荐