OLD | NEW |
(Empty) | |
| 1 # HMAC.py - Implements the HMAC algorithm as described by RFC 2104. |
| 2 # |
| 3 # =================================================================== |
| 4 # Portions Copyright (c) 2001, 2002, 2003 Python Software Foundation; |
| 5 # All Rights Reserved |
| 6 # |
| 7 # This file contains code from the Python 2.2 hmac.py module (the |
| 8 # "Original Code"), with modifications made after it was incorporated |
| 9 # into PyCrypto (the "Modifications"). |
| 10 # |
| 11 # To the best of our knowledge, the Python Software Foundation is the |
| 12 # copyright holder of the Original Code, and has licensed it under the |
| 13 # Python 2.2 license. See the file LEGAL/copy/LICENSE.python-2.2 for |
| 14 # details. |
| 15 # |
| 16 # The Modifications to this file are dedicated to the public domain. |
| 17 # To the extent that dedication to the public domain is not available, |
| 18 # everyone is granted a worldwide, perpetual, royalty-free, |
| 19 # non-exclusive license to exercise all rights associated with the |
| 20 # contents of this file for any purpose whatsoever. No rights are |
| 21 # reserved. |
| 22 # |
| 23 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 24 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 25 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 26 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 27 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 28 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 29 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 30 # SOFTWARE. |
| 31 # =================================================================== |
| 32 |
| 33 |
| 34 """HMAC (Hash-based Message Authentication Code) algorithm |
| 35 |
| 36 HMAC is a MAC defined in RFC2104_ and FIPS-198_ and constructed using |
| 37 a cryptograpic hash algorithm. |
| 38 It is usually named *HMAC-X*, where *X* is the hash algorithm; for |
| 39 instance *HMAC-SHA1* or *HMAC-MD5*. |
| 40 |
| 41 The strength of an HMAC depends on: |
| 42 |
| 43 - the strength of the hash algorithm |
| 44 - the length and entropy of the secret key |
| 45 |
| 46 An example of possible usage is the following: |
| 47 |
| 48 >>> from Crypto.Hash import HMAC |
| 49 >>> |
| 50 >>> secret = b'Swordfish' |
| 51 >>> h = HMAC.new(secret) |
| 52 >>> h.update(b'Hello') |
| 53 >>> print h.hexdigest() |
| 54 |
| 55 .. _RFC2104: http://www.ietf.org/rfc/rfc2104.txt |
| 56 .. _FIPS-198: http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf |
| 57 """ |
| 58 |
| 59 # This is just a copy of the Python 2.2 HMAC module, modified to work when |
| 60 # used on versions of Python before 2.2. |
| 61 |
| 62 __revision__ = "$Id$" |
| 63 |
| 64 __all__ = ['new', 'digest_size', 'HMAC' ] |
| 65 |
| 66 from Crypto.Util.strxor import strxor_c |
| 67 from Crypto.Util.py3compat import * |
| 68 |
| 69 #: The size of the authentication tag produced by the MAC. |
| 70 #: It matches the digest size on the underlying |
| 71 #: hashing module used. |
| 72 digest_size = None |
| 73 |
| 74 class HMAC: |
| 75 """Class that implements HMAC""" |
| 76 |
| 77 #: The size of the authentication tag produced by the MAC. |
| 78 #: It matches the digest size on the underlying |
| 79 #: hashing module used. |
| 80 digest_size = None |
| 81 |
| 82 def __init__(self, key, msg = None, digestmod = None): |
| 83 """Create a new HMAC object. |
| 84 |
| 85 :Parameters: |
| 86 key : byte string |
| 87 secret key for the MAC object. |
| 88 It must be long enough to match the expected security level of the |
| 89 MAC. However, there is no benefit in using keys longer than the |
| 90 `digest_size` of the underlying hash algorithm. |
| 91 msg : byte string |
| 92 The very first chunk of the message to authenticate. |
| 93 It is equivalent to an early call to `update()`. Optional. |
| 94 :Parameter digestmod: |
| 95 The hash algorithm the HMAC is based on. |
| 96 Default is `Crypto.Hash.MD5`. |
| 97 :Type digestmod: |
| 98 A hash module or object instantiated from `Crypto.Hash` |
| 99 """ |
| 100 if digestmod is None: |
| 101 import MD5 |
| 102 digestmod = MD5 |
| 103 |
| 104 self.digestmod = digestmod |
| 105 self.outer = digestmod.new() |
| 106 self.inner = digestmod.new() |
| 107 try: |
| 108 self.digest_size = digestmod.digest_size |
| 109 except AttributeError: |
| 110 self.digest_size = len(self.outer.digest()) |
| 111 |
| 112 try: |
| 113 # The block size is 128 bytes for SHA384 and SHA512 and 64 bytes |
| 114 # for the others hash function |
| 115 blocksize = digestmod.block_size |
| 116 except AttributeError: |
| 117 blocksize = 64 |
| 118 |
| 119 ipad = 0x36 |
| 120 opad = 0x5C |
| 121 |
| 122 if len(key) > blocksize: |
| 123 key = digestmod.new(key).digest() |
| 124 |
| 125 key = key + bchr(0) * (blocksize - len(key)) |
| 126 self.outer.update(strxor_c(key, opad)) |
| 127 self.inner.update(strxor_c(key, ipad)) |
| 128 if (msg): |
| 129 self.update(msg) |
| 130 |
| 131 def update(self, msg): |
| 132 """Continue authentication of a message by consuming the next chunk of d
ata. |
| 133 |
| 134 Repeated calls are equivalent to a single call with the concatenation |
| 135 of all the arguments. In other words: |
| 136 |
| 137 >>> m.update(a); m.update(b) |
| 138 |
| 139 is equivalent to: |
| 140 |
| 141 >>> m.update(a+b) |
| 142 |
| 143 :Parameters: |
| 144 msg : byte string |
| 145 The next chunk of the message being authenticated |
| 146 """ |
| 147 |
| 148 self.inner.update(msg) |
| 149 |
| 150 def copy(self): |
| 151 """Return a copy ("clone") of the MAC object. |
| 152 |
| 153 The copy will have the same internal state as the original MAC |
| 154 object. |
| 155 This can be used to efficiently compute the MAC of strings that |
| 156 share a common initial substring. |
| 157 |
| 158 :Returns: An `HMAC` object |
| 159 """ |
| 160 other = HMAC(b("")) |
| 161 other.digestmod = self.digestmod |
| 162 other.inner = self.inner.copy() |
| 163 other.outer = self.outer.copy() |
| 164 return other |
| 165 |
| 166 def digest(self): |
| 167 """Return the **binary** (non-printable) MAC of the message that has |
| 168 been authenticated so far. |
| 169 |
| 170 This method does not change the state of the MAC object. |
| 171 You can continue updating the object after calling this function. |
| 172 |
| 173 :Return: A byte string of `digest_size` bytes. It may contain non-ASCII |
| 174 characters, including null bytes. |
| 175 """ |
| 176 h = self.outer.copy() |
| 177 h.update(self.inner.digest()) |
| 178 return h.digest() |
| 179 |
| 180 def hexdigest(self): |
| 181 """Return the **printable** MAC of the message that has been |
| 182 authenticated so far. |
| 183 |
| 184 This method does not change the state of the MAC object. |
| 185 |
| 186 :Return: A string of 2* `digest_size` bytes. It contains only |
| 187 hexadecimal ASCII digits. |
| 188 """ |
| 189 return "".join(["%02x" % bord(x) |
| 190 for x in tuple(self.digest())]) |
| 191 |
| 192 def new(key, msg = None, digestmod = None): |
| 193 """Create a new HMAC object. |
| 194 |
| 195 :Parameters: |
| 196 key : byte string |
| 197 key for the MAC object. |
| 198 It must be long enough to match the expected security level of the |
| 199 MAC. However, there is no benefit in using keys longer than the |
| 200 `digest_size` of the underlying hash algorithm. |
| 201 msg : byte string |
| 202 The very first chunk of the message to authenticate. |
| 203 It is equivalent to an early call to `HMAC.update()`. |
| 204 Optional. |
| 205 :Parameter digestmod: |
| 206 The hash to use to implement the HMAC. Default is `Crypto.Hash.MD5`. |
| 207 :Type digestmod: |
| 208 A hash module or instantiated object from `Crypto.Hash` |
| 209 :Returns: An `HMAC` object |
| 210 """ |
| 211 return HMAC(key, msg, digestmod) |
| 212 |
OLD | NEW |