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
|
test_mac.doctest - test various mac schemes
Copyright (C) 2017 Arthur de Jong
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
02110-1301 USA
>>> from binascii import a2b_hex, b2a_hex
>>> def tostr(x):
... return str(x.decode())
>>> def decode(f):
... return lambda x: tostr(f(x))
>>> b2a_hex = decode(b2a_hex)
>>> import hashlib
>>> from pskc.mac import mac, mac_key_length
The module supports a wide variety of HMAC algorithms.
Some test cases from RFC 2202 for HMAC-MD5 and HMAC-SHA-1.
>>> key = a2b_hex('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')
>>> b2a_hex(mac('HMAC-MD5', key, b'Hi There'))
'9294727a3638bb1c13f48ef8158bfc9d'
>>> b2a_hex(mac('HMAC-MD5', b'Jefe', b'what do ya want for nothing?'))
'750c783e6ab0b503eaa86e310a5db738'
>>> key = a2b_hex('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')
>>> b2a_hex(mac('HMAC-SHA-1', key, b'Hi There'))
'b617318655057264e28bc0b6fb378c8ef146be00'
>>> b2a_hex(mac('HMAC-SHA-1', b'Jefe', b'what do ya want for nothing?'))
'effcdf6ae5eb2fa2d27416d5f184df9c259a7c79'
Some test cases from RFC 4231 for HMAC-SHA-224, HMAC-SHA-256, HMAC-SHA-384
and HMAC-SHA-512.
>>> key = a2b_hex('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')
>>> data = b'Hi There'
>>> b2a_hex(mac('HMAC-SHA-224', key, data))
'896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22'
>>> b2a_hex(mac('HMAC-SHA-256', key, data))
'b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7'
>>> b2a_hex(mac('HMAC-SHA-384', key, data))
'afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6'
>>> b2a_hex(mac('HMAC-SHA-512', key, data))
'87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854'
>>> key = b'Jefe'
>>> data = b'what do ya want for nothing?'
>>> b2a_hex(mac('HMAC-SHA-224', key, data))
'a30e01098bc6dbbf45690f3a7e9e6d0f8bbea2a39e6148008fd05e44'
>>> b2a_hex(mac('HMAC-SHA-256', key, data))
'5bdcc146bf60754e6a042426089575c75a003f089d2739839dec58b964ec3843'
>>> b2a_hex(mac('HMAC-SHA-384', key, data))
'af45d2e376484031617f78d2b58a6b1b9c7ef464f5a01b47e42ec3736322445e8e2240ca5e69e2c78b3239ecfab21649'
>>> b2a_hex(mac('HMAC-SHA-512', key, data))
'164b7a7bfcf819e2e395fbe73b56e0a387bd64222e831fd610270cd7ea2505549758bf75c05a994a6d034f65f8f0e6fdcaeab1a34d4a6b4b636e070a38bce737'
Some test cases from RFC 2857 for HMAC-RIPEMD160 but not all versions of
hashlib have RIPEMD-160.
>>> hashlib_algorithms = (
... getattr(hashlib, 'algorithms_available', None) or
... getattr(hashlib, 'algorithms', None))
>>> if 'ripemd160' in hashlib_algorithms:
... key = a2b_hex('0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b')
... b2a_hex(mac('HMAC-RIPEMD160', key, b'Hi There')) == \
... '24cb4bd67d20fc1a5d2ed7732dcc39377f0a5668'
... b2a_hex(mac('HMAC-RIPEMD160', b'Jefe', b'what do ya want for nothing?')) == \
... 'dda6c0213a485a9e24f4742064a7f033b43c4069'
... else:
... True # some hashlib implementations
... True # do not have RIPEMD-160
True
True
Some recommended minimal key lengths for some algorithms.
>>> mac_key_length('HMAC-MD5')
16
>>> mac_key_length('HMAC-SHA-1')
20
>>> mac_key_length('HMAC-SHA-224')
28
>>> mac_key_length('HMAC-SHA-256')
32
>>> mac_key_length('HMAC-SHA-384')
48
>>> mac_key_length('HMAC-SHA-512')
64
Unknown algorithms should raise an exception for the mac() function.
>>> mac('unknown', b'FOO', b'BAR') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
DecryptionError: Unsupported MAC algorithm: 'unknown'
>>> mac('hmac-unknown', b'FOO', b'BAR') # doctest: +IGNORE_EXCEPTION_DETAIL
Traceback (most recent call last):
...
DecryptionError: Unsupported MAC algorithm: 'hmac-unknown'
The mac_key_length() function should return a default value for unknown
MACs.
>>> mac_key_length('unknown')
16
>>> mac_key_length('hmac-unknown')
16
|