1 2.. _mac: 3 4Message Authentication Codes (MAC) 5=================================== 6 7A Message Authentication Code algorithm computes a tag over a message utilizing 8a shared secret key. Thus a valid tag confirms the authenticity and integrity of 9the message. Only entities in possession of the shared secret key are able to 10verify the tag. 11 12.. note:: 13 14 When combining a MAC with unauthenticated encryption mode, prefer to first 15 encrypt the message and then MAC the ciphertext. The alternative is to MAC 16 the plaintext, which depending on exact usage can suffer serious security 17 issues. For a detailed discussion of this issue see the paper "The Order of 18 Encryption and Authentication for Protecting Communications" by Hugo 19 Krawczyk 20 21The Botan MAC computation is split into five stages. 22 23#. Instantiate the MAC algorithm. 24#. Set the secret key. 25#. Process IV. 26#. Process data. 27#. Finalize the MAC computation. 28 29.. cpp:class:: MessageAuthenticationCode 30 31 .. cpp:function:: std::string name() const 32 33 Returns a human-readable string of the name of this algorithm. 34 35 .. cpp:function:: void clear() 36 37 Clear the key. 38 39 .. cpp:function:: MessageAuthenticationCode* clone() const 40 41 Return a newly allocated object of the same type as this one. 42 43 .. cpp:function:: void set_key(const uint8_t* key, size_t length) 44 45 Set the shared MAC key for the calculation. This function has to be called before the data is processed. 46 47 .. cpp:function:: bool valid_keylength(size_t length) const 48 49 This function returns true if and only if *length* is a valid 50 keylength for the algorithm. 51 52 .. cpp:function:: size_t minimum_keylength() const 53 54 Return the smallest key length (in bytes) that is acceptable for the 55 algorithm. 56 57 .. cpp:function:: size_t maximum_keylength() const 58 59 Return the largest key length (in bytes) that is acceptable for the 60 algorithm. 61 62 .. cpp:function:: void start(const uint8_t* nonce, size_t nonce_len) 63 64 Set the IV for the MAC calculation. Note that not all MAC algorithms require an IV. 65 If an IV is required, the function has to be called before the data is processed. 66 For algorithms that don't require it, the call can be omitted, or else called 67 with ``nonce_len`` of zero. 68 69 .. cpp:function:: void update(const uint8_t* input, size_t length) 70 71 Process the passed data. 72 73 .. cpp:function:: void update(const secure_vector<uint8_t>& in) 74 75 Process the passed data. 76 77 .. cpp:function:: void update(uint8_t in) 78 79 Process a single byte. 80 81 .. cpp:function:: void final(uint8_t* out) 82 83 Complete the MAC computation and write the calculated tag to the passed byte array. 84 85 .. cpp:function:: secure_vector<uint8_t> final() 86 87 Complete the MAC computation and return the calculated tag. 88 89 .. cpp:function:: bool verify_mac(const uint8_t* mac, size_t length) 90 91 Finalize the current MAC computation and compare the result to the passed 92 ``mac``. Returns ``true``, if the verification is successful and false 93 otherwise. 94 95 96Code Examples 97------------------------ 98 99The following example computes an HMAC with a random key then verifies the tag. 100 101 #include <botan/mac.h> 102 #include <botan/hex.h> 103 #include <botan/system_rng.h> 104 #include <assert.h> 105 106 std::string compute_mac(const std::string& msg, const Botan::secure_vector<uint8_t>& key) 107 { 108 auto hmac = Botan::MessageAuthenticationCode::create_or_throw("HMAC(SHA-256)"); 109 110 hmac->set_key(key); 111 hmac->update(msg); 112 113 return Botan::hex_encode(hmac->final()); 114 } 115 116 int main() 117 { 118 Botan::System_RNG rng; 119 120 const auto key = rng.random_vec(32); // 256 bit random key 121 122 // "Message" != "Mussage" so tags will also not match 123 std::string tag1 = compute_mac("Message", key); 124 std::string tag2 = compute_mac("Mussage", key); 125 assert(tag1 != tag2); 126 127 // Recomputing with original input message results in identical tag 128 std::string tag3 = compute_mac("Message", key); 129 assert(tag1 == tag3); 130 } 131 132 133The following example code computes a AES-256 GMAC and subsequently verifies the 134tag. Unlike most other MACs, GMAC requires a nonce *which must not repeat or 135all security is lost*. 136 137.. code-block:: cpp 138 139 #include <botan/mac.h> 140 #include <botan/hex.h> 141 #include <iostream> 142 143 int main() 144 { 145 const std::vector<uint8_t> key = Botan::hex_decode("1337133713371337133713371337133713371337133713371337133713371337"); 146 const std::vector<uint8_t> nonce = Botan::hex_decode("FFFFFFFFFFFFFFFFFFFFFFFF"); 147 const std::vector<uint8_t> data = Botan::hex_decode("6BC1BEE22E409F96E93D7E117393172A"); 148 std::unique_ptr<Botan::MessageAuthenticationCode> mac(Botan::MessageAuthenticationCode::create("GMAC(AES-256)")); 149 if(!mac) 150 return 1; 151 mac->set_key(key); 152 mac->start(nonce); 153 mac->update(data); 154 Botan::secure_vector<uint8_t> tag = mac->final(); 155 std::cout << mac->name() << ": " << Botan::hex_encode(tag) << std::endl; 156 157 //Verify created MAC 158 mac->start(nonce); 159 mac->update(data); 160 std::cout << "Verification: " << (mac->verify_mac(tag) ? "success" : "failure"); 161 return 0; 162 } 163 164The following example code computes a valid AES-128 CMAC tag and modifies the 165data to demonstrate a MAC verification failure. 166 167.. code-block:: cpp 168 169 #include <botan/mac.h> 170 #include <botan/hex.h> 171 #include <iostream> 172 173 int main() 174 { 175 const std::vector<uint8_t> key = Botan::hex_decode("2B7E151628AED2A6ABF7158809CF4F3C"); 176 std::vector<uint8_t> data = Botan::hex_decode("6BC1BEE22E409F96E93D7E117393172A"); 177 std::unique_ptr<Botan::MessageAuthenticationCode> mac(Botan::MessageAuthenticationCode::create("CMAC(AES-128)")); 178 if(!mac) 179 return 1; 180 mac->set_key(key); 181 mac->update(data); 182 Botan::secure_vector<uint8_t> tag = mac->final(); 183 //Corrupting data 184 data.back()++; 185 //Verify with corrupted data 186 mac->update(data); 187 std::cout << "Verification with malformed data: " << (mac->verify_mac(tag) ? "success" : "failure"); 188 return 0; 189 } 190 191Available MACs 192------------------------------------------ 193 194Currently the following MAC algorithms are available in Botan. In new code, 195default to HMAC with a strong hash like SHA-256 or SHA-384. 196 197CBC-MAC 198~~~~~~~~~~~~ 199 200An older authentication code based on a block cipher. Serious security problems, 201in particular **insecure** if messages of several different lengths are 202authenticated. Avoid unless required for compatibility. 203 204Available if ``BOTAN_HAS_CBC_MAC`` is defined. 205 206.. warning:: 207 CBC-MAC support is deprecated and will be removed in a future major release. 208 209CMAC 210~~~~~~~~~~~~ 211 212A modern CBC-MAC variant that avoids the security problems of plain CBC-MAC. 213Approved by NIST. Also sometimes called OMAC. 214 215Available if ``BOTAN_HAS_CMAC`` is defined. 216 217GMAC 218~~~~~~~~~~~~ 219 220GMAC is related to the GCM authenticated cipher mode. It is quite slow unless 221hardware support for carryless multiplications is available. A new nonce 222must be used with **each** message authenticated, or otherwise all security is 223lost. 224 225Available if ``BOTAN_HAS_GMAC`` is defined. 226 227.. warning:: 228 Due to the nonce requirement, GMAC is exceptionally fragile. Avoid it unless 229 absolutely required. 230 231HMAC 232~~~~~~~~~~~~ 233 234A message authentication code based on a hash function. Very commonly used. 235 236Available if ``BOTAN_HAS_HMAC`` is defined. 237 238Poly1305 239~~~~~~~~~~~~ 240 241A polynomial mac (similar to GMAC). Very fast, but tricky to use safely. Forms 242part of the ChaCha20Poly1305 AEAD mode. A new key must be used for **each** 243message, or all security is lost. 244 245Available if ``BOTAN_HAS_POLY1305`` is defined. 246 247.. warning:: 248 Due to the nonce requirement, Poly1305 is exceptionally fragile. Avoid it unless 249 absolutely required. 250 251SipHash 252~~~~~~~~~~~~ 253 254A modern and very fast PRF. Produces only a 64-bit output. Defaults to 255"SipHash(2,4)" which is the recommended configuration, using 2 rounds for each 256input block and 4 rounds for finalization. 257 258Available if ``BOTAN_HAS_SIPHASH`` is defined. 259 260X9.19-MAC 261~~~~~~~~~~~~ 262 263A CBC-MAC variant sometimes used in finance. Always uses DES. 264Sometimes called the "DES retail MAC", also standardized in ISO 9797-1. 265 266It is slow and has known attacks. Avoid unless required. 267 268Available if ``BOTAN_HAS_X919_MAC`` is defined. 269