Authenticated Encryption
Authenticated Encryption provides both data confidentiality and data integrity assurances to the information being protected. The concept of data authentication appeared in the 1970s in the banking industry. The problem was studied in detail by the ANSI X9 committee. Banks did not want to transmit data and allow an attacker to flip a bit undetected. In this situation, the attacker would not decrypt the message, instead he or she would only flip a bit so that the encrypted message "Post $100" would be changed to "Post $800".
Many developers make the mistake of only encrypting data. For those who include integrity assurances, it can be difficult to incorporate correctly. The apparent reason for not including authentication data is that most sample code presented in technical sources only offers an example of the encryption (and perhaps decryption) function, void of any context. For those who are including authenticity assurances, the details and interaction can be tricky to implement correctly.
Data Integrity and Authenticity
In 2001, Hugo Krawczyk published The Order of Encryption and Authentication for Protecting Communications. In the paper, Krawczyk examined three commonly used methods of combining confidentiality and authenticity. Each method was used in a well known protocol. Note that the list below does not include simple encryption.
- Authenticate then Encrypt (AtE) - SSL
- Encrypt then Authenticate (EtA) - IPSec
- Encrypt and Authenticate (E&A) - SSH
The results of the paper showed that Encrypt then Authenticate (IPSec) was secure, as was Authenticate then Encrypt (SSL) under certain constructions as was Authenticate then Encrypt (SSL) when used with a stream cipher. The paper also showed that Encrypt and Authenticate (SSH) was insecure. Update: in 2014, Krawczyk revisited his results, and found that SSL with a block cipher in CBC mode was insecure due to a misunderstanding in the way the plaintext was encoded and padded.
The two provably safe Authenticate then Encrypt constructions are:
- A Block cipher operated in CBC mode
- A Stream cipher which XORs data with a pseudorandom pad
Note well: even though SSL uses a block cipher in CBC mode, it is not secure because of the way it applies padding to a message. Sapienti sat: POODLE and friends.
The operations performed by the protocols are listed below. Enc(x) is encryption, Hash(x) is a customary hash, and Auth(x) is a message authenticity code (also known as a MAC or keyed hash).
Method | Protocol | Operation | Transmit |
---|---|---|---|
HAC, 9.6† | - | h = Hash(m), C = Enc(m||h) | C |
AtE†† | SSL | a = Auth(m), C = Enc(m||a) | C |
EtA | IPSec | C = Enc(m), a = Auth(C) | C||a |
E&A | SSH | C = Enc(m), a = Auth(m) | C||a |
†Handbook of Applied Cryptography, Section 9.6
††In 2014, Krawczyk revistied TLS CBC mode encryption and determined it was not secure due to the way the padding and MAC was applied. See Re: [TLS] Last Call: <draft-ietf-tls-encrypt-then-mac-02.txt> (Encrypt-then-MAC for TLS and DTLS) to Proposed Standard
In 2000, Bellare and Rogaway introduced a fourth way of achieving confidentiality and authenticity: Encode-then-Encipher (EtE). Historically EtE has been less popular than the other schemes, but that changed with the advent of the CAESAR Competition. There paper is available at Encode-then-encipher encryption: How to exploit nonces or redundancy in plaintexts for efficient cryptography.
Semantic Authentication
In 1996, David Wagner and Bruce Schneier published Analysis of the SSL 3.0 Protocol. In the paper, Wagner and Schneier introduced the Horton Principal which is the notion of semantic authentication. Semantic authentication simply means to authenticate what was meant, and not what was said.
For example, suppose there is plain text which is to be protected. The plain text is padded to the size of the block cipher and then encrypted. The operation of padding begs the question, What should be authenticated? The plain text or plain text + padding? According to Wagner and Schneier, both the plain text and padding would be authenticated (what was meant), and not just the plain text (what was said).
Authenticated Encryption
NIST, through SP 800-38C and SP800-38D, specifies two block cipher modes of operation (CCM and GCM) which offer both confidentiality and authenticity. Additionally Crypto++ offers EAX which was a NIST candidate during the selection process. Finally the library offers both ChaCha20Poly1305 and XChaCha20Poly1305 from the RFCs.
Algorithms providing confidentiality and authenticity can be divided into two categories: authenticated encryption (AE) and authenticated encryption with additional data (AEAD). The two NIST modes, CCM and GCM, and the proposed mode, EAX are AEAD algorithms. Each encrypts and authenticates plain text data (in addition to authenticated-only data), which produces cipher text with an authentication code. If an attacker were to flip a bit, the decryption and verification routine would detect the modification using the authentication code.
The three modes offer to authenticate separate data, known as additional authenticated data or AAD. The additional authenticated data is not encrypted - it is only authenticated. The AAD can be persisted in clear text, or communicated unencrypted (for example, an IP Address and Port in a network data packet). Because the data will be authenticated, an attacker can flip a bit and the verification process will detect the modification.
Revisiting the original example, the improved version is as follows. The sample program performs authenticated encryption (not authentication over additional authenticated data). As with before, it is presumed that buffers will not be an issue. Note, however, that exception handling has been omitted for clarity.
string plaintext, ciphertext; ... GCM< AES >::Encryption enc; enc.SetKeyWithIV( key, sizeof(key), iv, sizeof(iv) ); AuthenticatedEncryptionFilter aef( enc, new StringSink( ciphertext ) ); // AuthenticatedEncryptionFilter aef.Put( plaintext.data(), plaintext.size() ); aef.MessageEnd();
After executing the sample code above, ciphertext is a concatenation of the encrypted data and the authenticator. Because the message is protected using AES and GCM, it will be safe for a very long time. To decrypt the data, the following would be performed.
string ciphertext, plaintext; ... GCM< AES >::Decryption dec; dec.SetKeyWithIV( key, sizeof(key), iv, sizeof(iv) ); AuthenticatedDecryptionFilter adf( dec, new StringSink( plaintext ) ); // AuthenticatedDecryptionFilter adf.Put( ciphertext.data(), ciphertext.size() ); adf.MessageEnd();
The two samples demonstrate all that is required to ensure both data confidentiality and data authenticity. The implementation is orders of magnitude stronger than encryption alone. Full details of using Crypto++ objects such as EAX, CCM, GCM, AuthenticatedEncryptionFilter, AuthenticatedDecryptionFilter, and StringSink can be found through out the wiki.
Combining Primitives
The following demonstrates combining confidentiality and authenticity using a block cipher in CBC mode and an HMAC. Its the same Encrypt-then-Authenticate used by IPSec. The data is first encrypted, and then its authenticated. The authentication tag is placed at the end of the message. Its available for download at cryptopp-authenc.zip.
string password = "Super secret password"; if(argc >= 2 && argv[1] != NULL) password = string(argv[1]); string message = "Now is the time for all good men to come to the aide of their country"; if(argc >= 3 && argv[2] != NULL) message = string(argv[2]); string cipher, recover; SecByteBlock ekey(16), iv(16), akey(16); // Derive keys an IV from the password DeriveKeyAndIV(password, 100, ekey, ekey.size(), iv, iv.size(), akey, akey.size()); // Create and key objects CBC_Mode<AES>::Encryption encryptor; encryptor.SetKeyWithIV(ekey, ekey.size(), iv, iv.size()); CBC_Mode<AES>::Decryption decryptor; decryptor.SetKeyWithIV(ekey, ekey.size(), iv, iv.size()); HMAC< SHA256> hmac; hmac.SetKey(akey, akey.size()); // Encrypt and authenticate data StringSource ss1(message, true /*pumpAll*/, new StreamTransformationFilter(encryptor, new HashFilter(hmac, new StringSink(cipher), true /*putMessage*/))); // Authenticate and decrypt data StringSource ss2(cipher, true /*pumpAll*/, new HashVerificationFilter(hmac, new StreamTransformationFilter(decryptor, new StringSink(recover)), HASH_AT_END | PUT_MESSAGE | THROW_EXCEPTION)); // Print stuff PrintKeyAndIV(ekey, iv, akey); ...
The program produces results similar to:
$ ./cryptopp-authenc.exe "Super secret password" "Super secret message" Password: Super secret password AES key: C08126FBECA7E2BE71B69FE92570A991 AES IV: BCEB5407D68912C266B9045A5DD007CB HMAC key: EBBECB1D0A5B52F306B0F328877E057A Message: Super secret message Ciphertext+MAC: 16A44D862EA1AD96B8860B8DA5EC3C7B5DBF16E90BD35123DE3F005BF6924506 868013D740936D10CBC2A6F4192E4B0FA162507479625289E0105A49505533AC Recovered: Super secret message
If you use the code in the authenticated encryption example, be sure each message gets a unique IV. The DeriveKeyAndIV
produces predictable IVs for demonstration purposes, but it violates semantic security because two messages under the same key will produce the same ciphertext.
If you choose to generate a random IV and append it to the message, be sure to authenticate the {IV,Ciphertext} pair.
Integrated Encryption Scheme
Authenticated encryption is a good step towards data security. Integrated Encryption Schemes (IES) provide even more security assurances than authenticated encryption. In general, you should prefer an Integrated Encryption Scheme over Authenticated Encryption since IES has a stronger notion of security.
Crypto++ provides two common IES schemes. The first is Elliptic Curve Integrated Encryption Scheme by Shoup, and the second is Discrete Logarithm Integrated Encryption Scheme by Abdalla, Bellare and Rogaway.
Downloads
CCMTest.zip - Authenticated encryption and decryption using AES operated in CCM mode
GCM-AEAD-Test.zip - Authenticated encryption and decryption using AES operated in GCM mode
Blowfish-EAX-Filter.zip - Authenticated encryption and decryption using Blowfish in EAX mode with filters
Twofish-EAX-Filter.zip - Authenticated encryption and decryption using Twofish in EAX mode with filters
IDEA-EAX-Filter.zip - Authenticated encryption and decryption using IDEA in EAX mode with filters
Serpent-EAX-Filter.zip - Authenticated encryption and decryption using Serpent in EAX mode with filters
Camellia-EAX-Filter.zip - Authenticated encryption and decryption using Camellia in EAX mode with filters
Twofish-GCM-Filter.zip - Authenticated encryption and decryption using Twofish in GCM mode with filters
Serpent-GCM-Filter.zip - Authenticated encryption and decryption using Serpent in GCM mode with filters
Camellia-GCM-Filter.zip - Authenticated encryption and decryption using Camellia in GCM mode with filters
AES-GCM-Filter.zip - Authenticated encryption and decryption using AES in GCM mode with filters
cryptopp-authenc.zip - Authenticated encryption and decryption using a block cipher in CBC mode and a HMAC.