Fast inline implementation of HMAC. key: bytes or buffer, The key for the keyed hash object. msg: bytes or buffer, Input message. digest: A hash name suitable for hashlib.new() for best performance. *OR* A hashlib constructor returning a new hash object. *OR*
(key, msg, digest)
| 185 | |
| 186 | |
| 187 | def digest(key, msg, digest): |
| 188 | """Fast inline implementation of HMAC. |
| 189 | |
| 190 | key: bytes or buffer, The key for the keyed hash object. |
| 191 | msg: bytes or buffer, Input message. |
| 192 | digest: A hash name suitable for hashlib.new() for best performance. *OR* |
| 193 | A hashlib constructor returning a new hash object. *OR* |
| 194 | A module supporting PEP 247. |
| 195 | """ |
| 196 | if _hashopenssl is not None and isinstance(digest, (str, _functype)): |
| 197 | try: |
| 198 | return _hashopenssl.hmac_digest(key, msg, digest) |
| 199 | except _hashopenssl.UnsupportedDigestmodError: |
| 200 | pass |
| 201 | |
| 202 | if callable(digest): |
| 203 | digest_cons = digest |
| 204 | elif isinstance(digest, str): |
| 205 | digest_cons = lambda d=b'': _hashlib.new(digest, d) |
| 206 | else: |
| 207 | digest_cons = lambda d=b'': digest.new(d) |
| 208 | |
| 209 | inner = digest_cons() |
| 210 | outer = digest_cons() |
| 211 | blocksize = getattr(inner, 'block_size', 64) |
| 212 | if len(key) > blocksize: |
| 213 | key = digest_cons(key).digest() |
| 214 | key = key + b'\x00' * (blocksize - len(key)) |
| 215 | inner.update(key.translate(trans_36)) |
| 216 | outer.update(key.translate(trans_5C)) |
| 217 | inner.update(msg) |
| 218 | outer.update(inner.digest()) |
| 219 | return outer.digest() |