没有填充的Java AES

Bry*_*eld 14 java encryption aes padding

在没有自动填充的情况下,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);
Run Code Online (Sandbox Code Playgroud)

如何防止填充?该plain数据总是固定长度和包括它自己的填充.如何允许plain16个字节而不会导致encrypted32个字节?

Bry*_*eld 17

看我的评论.对不起,我可能应该第一次仔细看看.

  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"

我选择ECB是因为这是默认值.

如果您需要加密超过16个字节,请考虑使用ECB以外的其他东西,这会遇到一定的重复检测缺陷

在此位图示例中,此图像具有重复的白色块,因此您可以通过查找块变为不同的位置来推断图像的轮廓.

在加密之前 加密

如果您只加密一个块,那么它并不重要,只有当您加密多个块时,ECB才会显示出来.

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

  • 此外,您的`encrypter.getParameters()`实际上主要传输初始化向量.如果您不在同一过程中加密和解密,则应将此IV与数据一起发送. (3认同)
  • 您通常不希望将CBC与NoPadding一起使用(或仅当您的数据大小始终为16字节的倍数时).CTR,OFB和CFB模式可用于NoPadding,而不是CBC.(编辑:啊,我错过了你的数据已经是一个16字节的数组.那就没关系.) (2认同)

Dav*_*oni 6

同意@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); 
Run Code Online (Sandbox Code Playgroud)