AES/CCM 加密和明文长度超过最大消息长度

AES/CCM Encryption and Plaintext Length Exceeds Maximum Message Length

我正在尝试使用 AES128 密码和 CCM 操作模式在 Crypto++ 库中执行加密和解密。当我尝试加密长度超过 16777215 字节的字符串时遇到问题。

我的代码:

const int TAG_SIZE = 8;
CCM< AES, TAG_SIZE >::Encryption e;
CCM< AES, TAG_SIZE >::Decryption d;

e.SetKeyWithIV( key, sizeof(key), iv, sizeof(iv) );
e.SpecifyDataLengths( 0, plain.size(), 0 );

//Encryption
StringSource ss1(
  plain,
  true,
  new AuthenticatedEncryptionFilter(
    e,
    new StringSink(cipher)
   )
);

d.SetKeyWithIV( key, sizeof(key), iv, sizeof(iv) );
d.SpecifyDataLengths( 0, plain.size(), 0 );

//Decryption
AuthenticatedDecryptionFilter df( d,
  new StringSink(recovered)
);
StringSource ss2(
  cipher,
  true,
  new Redirector(df)
);

当我尝试 encrypt/decrypt 一张 CD (737280000) 大小的明文时,出现以下错误:

"terminate called after throwing an instance of 'CryptoPP::InvalidArgument' what(): AES/CCM: message length 737280000 exceeds the maximum of 16777215"

我的问题是,如何 encrypt/decrypt 一个超过 16777215 字节的明文?

My question is, how do I encrypt/decrypt a plaintext which is longer than 16777215 bytes?

CCM 模式在 NIST SP800-38c 中指定。 A.1 节,长度要求,讨论安全上下文下的最大纯文本。安全上下文是 {key, iv} 组合(需要一些手)。

我相信你有三个选择。首先,您可以增加 IV 的长度。 iv 越大,可以加密的明文越多。最大 iv 长度为 13,因此它不会永远扩展。

其次,您必须re-key或在达到上下文下的最大纯文本之前更改iv。您可以使用 MaxMessageLength(). Crypto++ tracks the number of bytes processed via m_totalMessageLength 找到最大纯文本长度,但它不会暴露给用户程序。你将不得不自己跟踪它。

第三,你可以改变算法。像 ChaCha20Poly1305 这样的算法允许您加密 2^38-1 个 64 字节块。这不到 2^44 字节或大约 256 GB。使用 ChaCha20Poly1305 应该是安全的。


Crypto++ 通过 MaxMessageLength() 告诉您最大字节数。在 CCM 的情况下,它基于 iv 长度,并通过下面代码中的 m_L 进行跟踪。

lword MaxMessageLength() const
    {return m_L<8 ? (W64LIT(1)<<(8*m_L))-1 : W64LIT(0)-1;}

MaxMessageLength()用于authenc.cppProcessData() 达到限制时抛出异常:

if (m_state >= State_IVSet && length > MaxMessageLength()-m_totalMessageLength)
    throw InvalidArgument(AlgorithmName() + ": message length exceeds maximum");
m_totalMessageLength += length;

const int TAG_SIZE = 8;
CCM< AES, TAG_SIZE >::Encryption e;
CCM< AES, TAG_SIZE >::Decryption d;

您的标签尺寸有点偏小。如果您的协议允许,您可能希望使用最大尺寸。


我建议你切换算法。 CCM 是一种混蛋模式,在 2000 年代初期通过某个无线工作组实现了标准化。然后,NIST 采纳了它,因为它已经标准化了。

在 CCM 标准化时,有更好的 Authenticated Encryption 模式可用,例如 CWC、OCB、EAX 和 GCM。不幸的是,损坏已经造成。现在你有了 Bernstein 的 ChaChaPoly1305 这样的算法。

您可能还想在 Crypto++ wiki 上查看 AEAD Comparison。比较显示 CCM 是最差的经过身份验证的加密模式。