Modes of Operation
Documentation |
#include <cryptopp/modes.h>
|
Modes of Operation is a method of operating a block cipher on messages larger than cipher's block size. Crypto++ offers several modes of operation, including ECB, CBC, OFB, CFB, CBC-CTS, CTR, XTS, CCM, EAX, GCM, OCB. This wiki article will discuss the block cipher modes of operation provided by the library.
Generally speaking there are two categories of modes of operation. The first category is confidentiality-only modes, and they include ECB, CBC, CTR and OFB modes. The second category is authenticated encryption (authenc) modes, and they include CCM, EAX, GCM and OCB mode. Authenc provides both confidentiality and authenticity.
The confidentiality-only modes are found in modes.h
. The Authenc modes of operation are in ccm.h
, eax.h
, gcm.h
and ocb.h
.
Note: if your project is using encryption alone to secure your data, encryption alone is usually not enough. Please take a moment to read Authenticated Encryption and understand why you should prefer to use CCM, GCM, or EAX over other modes, such as CBC or CTR.
Modes of Operation
The following examples show how to key a cipher with a mode. AES is used as an example, but any class that derives from BlockCipher
can be used. The examples also use the forward transformation specified as Encryption
. Decryption
is used the same way as Encryption
.
If you forget to specify a direction, Encryption
or Decryption
, then you will receive an error during compile. For example, the following code:
ECB_Mode<AES> encryptor; encryptor.SetKey(key, key.size());
Will result in:
error: ‘struct CryptoPP::ECB_Mode<CryptoPP::Rijndael>’ has no member named ‘SetKey’ encryptor.SetKey(key, key.size());
ECB
ECB mode does not uses an initialization vector. You should use SetKey
instead of SetKeyWithIV
. For more details on the mode see ECB on the wiki.
SecByteBlock key(AES::DEFAULT_KEYLENGTH); std::memset(key, 0, key.size()); ECB_Mode<AES>::Encryption encryptor; encryptor.SetKey(key, key.size());
CBC
CBC mode uses an initialization vector. You should use SetKeyWithIV
instead of SetKey
. For more details on the mode see CBC on the wiki.
SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE); std::memset(key, 0, key.size()); std::memset(iv, 0, iv.size()); CBC_Mode<AES>::Encryption encryptor; encryptor.SetKeyWithIV(key, key.size(), iv);
OFB
OFB mode uses an initialization vector. You should use SetKeyWithIV
instead of SetKey
. For more details on the mode see OFB on the wiki.
SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE); std::memset(key, 0, key.size()); std::memset(iv, 0, iv.size()); OFB_Mode<AES>::Encryption encryptor; encryptor.SetKeyWithIV(key, key.size(), iv);
CFB
CFB mode uses an initialization vector. You should use SetKeyWithIV
instead of SetKey
. For more details on the mode see CFB on the wiki.
SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE); std::memset(key, 0, key.size()); std::memset(iv, 0, iv.size()); OFB_Mode<AES>::Encryption encryptor; encryptor.SetKeyWithIV(key, key.size(), iv);
CBC-CTS
CBC-CTS mode uses an initialization vector. You should use SetKeyWithIV
instead of SetKey
. For more details on the mode see CBC-CTS on the wiki.
SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE); std::memset(key, 0, key.size()); std::memset(iv, 0, iv.size()); OFB_Mode<AES>::Encryption encryptor; encryptor.SetKeyWithIV(key, key.size(), iv);
XTS
XTS mode is similar to CBC-CTS in operation, but it requires twice the keying material. Twice the keying material is needed because the data and iv are encrypted under separate keys. The initialization vector is the sector number or a random string. You should use SetKeyWithIV
instead of SetKey
. For more details on the mode see XTS on the wiki.
SecByteBlock key(2*AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE); std::memset(key, 0, key.size()); std::memset(iv, 0, iv.size()); OFB_Mode<AES>::Encryption encryptor; encryptor.SetKeyWithIV(key, key.size(), iv);
CCM
CCM mode uses an initialization vector. You should use SetKeyWithIV
instead of SetKey
. For more details on the mode see CCM on the wiki.
SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE); std::memset(key, 0, key.size()); std::memset(iv, 0, iv.size()); CCM<AES>::Encryption encryptor; encryptor.SetKeyWithIV(key, key.size(), iv);
EAX
EAX mode uses an initialization vector. You should use SetKeyWithIV
instead of SetKey
. For more details on the mode see EAX on the wiki.
SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE); std::memset(key, 0, key.size()); std::memset(iv, 0, iv.size()); EAX<AES>::Encryption encryptor; encryptor.SetKeyWithIV(key, key.size(), iv);
GCM
GCM mode uses an initialization vector. You should use SetKeyWithIV
instead of SetKey
. For more details on the mode see GCM on the wiki.
SecByteBlock key(AES::DEFAULT_KEYLENGTH), iv(AES::BLOCKSIZE); std::memset(key, 0, key.size()); std::memset(iv, 0, iv.size()); GCM<AES>::Encryption encryptor; encryptor.SetKeyWithIV(key, key.size(), iv);
Internal Cipher Modes
All cipher modes in the Crypto++ library provide a mode object that takes a cipher as a template parameter. Most code uses and internal cipher object, where the cipher is part of the mode class. In the example below, the CBC_Mode
object has a AES
class member, and the internal cipher is specified through a template parameter.
// Operate the cipher in the specified mode CBC_Mode<AES>::Encryption encryptor; encryptor.SetKeyWithIV(key, key.size(), iv);
External Cipher Modes
External mode cipher objects allow you to use a separate cipher object for transformations. The library provides CFB_Mode_ExternalCipher
, CFB_FIPS_Mode_ExternalCipher
, OFB_Mode_ExternalCipher
, CTR_Mode_ExternalCipher
, ECB_Mode_ExternalCipher
, CBC_Mode_ExternalCipher
and CBC_CTS_Mode_ExternalCipher
classes.
A second way to use a mode of operation is through an external cipher. External ciphers are exactly that what the name implies. Instead of the mode having an internal cipher object, it uses a reference to an external cipher. An example of CBC mode is shown below.
// Notice no mode for cipher AES::Encryption cipher; cipher.SetKey(key, key.size()); // Attach a mode of operation CBC_Mode_ExternalCipher::Encryption encryptor(cipher, iv);
Wide Block Ciphers
Kalyna and Threefish are considered "wide block" block cipher because they use block sizes greater than 128-bits. There are pain points when using wide block ciphers, like incomplete support for some modes of operation. The problem is largely due to missing specifications for the wider block sizes, which means we don't know how to implement an algorithm in a standard way. A side effect is, no specifications lead to missing test vectors.
Examples of missing specifications include missing polynomials for CMAC and GCM modes of operation. It is not enough to simply use a low weight polynomial since there can be multiple primitive polynomials available. We are tracking the missing polynomials at Issue 423, Polynomials for CMAC and GCM mode.
Another example of a missing specification is counter mode operations. The mode could be as simple as using a larger counter, or it could use a zero-extended 128-bit counter. Sometimes the result of counter mode operation is reduced by a primitive polynomial, so it can also suffer missing polynomials detailed in CMAC and GCM.
Yet another example is CCM, EAX and GCM are authenticated encryption modes of operation. The modes produce an authentication tag and the tag has traditionally been the size of the block. In the case of AES, Camellia that's 128-bits and it is sufficient to authenticate the data. In the case of wide blocks we don't know if tags should be extended accordingly. As we understand the latest revision to OCB mode, the tags are not extended.
At this point in time we believe the status of wide block modes of operation are:
- CMAC - may work, but we don't have test vectors
- CBC - probably works, we had Kalyna test vectors
- CTR - probably works, we had Kalyna test vectors
- XTS - may work, but we don't have test vectors
- EAX - may work, but we don't have test vectors
- GCM - does not work, we don't have an implementation
- CCM - probably does not work, we don't have a specification
- OCB - in progress, not ready for production
- Others - modes like OFB and CFB probably work
In a few places we said, "probably works, we had Kalyna test vectors". There is a danger we cannot make the leap because Kalyna uses operations specified in DSTU, which is a Ukranian national standard. The standard may be different than what ISO/IEC, NESSIE, NIST or the IETF eventually produce.