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