Index: third_party/google-endpoints/Crypto/Hash/HMAC.py |
diff --git a/third_party/google-endpoints/Crypto/Hash/HMAC.py b/third_party/google-endpoints/Crypto/Hash/HMAC.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..6244db46f657219682f609db66b6d1f0c383207b |
--- /dev/null |
+++ b/third_party/google-endpoints/Crypto/Hash/HMAC.py |
@@ -0,0 +1,212 @@ |
+# HMAC.py - Implements the HMAC algorithm as described by RFC 2104. |
+# |
+# =================================================================== |
+# Portions Copyright (c) 2001, 2002, 2003 Python Software Foundation; |
+# All Rights Reserved |
+# |
+# This file contains code from the Python 2.2 hmac.py module (the |
+# "Original Code"), with modifications made after it was incorporated |
+# into PyCrypto (the "Modifications"). |
+# |
+# To the best of our knowledge, the Python Software Foundation is the |
+# copyright holder of the Original Code, and has licensed it under the |
+# Python 2.2 license. See the file LEGAL/copy/LICENSE.python-2.2 for |
+# details. |
+# |
+# The Modifications to this file are dedicated to the public domain. |
+# To the extent that dedication to the public domain is not available, |
+# everyone is granted a worldwide, perpetual, royalty-free, |
+# non-exclusive license to exercise all rights associated with the |
+# contents of this file for any purpose whatsoever. No rights are |
+# reserved. |
+# |
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
+# BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
+# ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
+# CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
+# SOFTWARE. |
+# =================================================================== |
+ |
+ |
+"""HMAC (Hash-based Message Authentication Code) algorithm |
+ |
+HMAC is a MAC defined in RFC2104_ and FIPS-198_ and constructed using |
+a cryptograpic hash algorithm. |
+It is usually named *HMAC-X*, where *X* is the hash algorithm; for |
+instance *HMAC-SHA1* or *HMAC-MD5*. |
+ |
+The strength of an HMAC depends on: |
+ |
+ - the strength of the hash algorithm |
+ - the length and entropy of the secret key |
+ |
+An example of possible usage is the following: |
+ |
+ >>> from Crypto.Hash import HMAC |
+ >>> |
+ >>> secret = b'Swordfish' |
+ >>> h = HMAC.new(secret) |
+ >>> h.update(b'Hello') |
+ >>> print h.hexdigest() |
+ |
+.. _RFC2104: http://www.ietf.org/rfc/rfc2104.txt |
+.. _FIPS-198: http://csrc.nist.gov/publications/fips/fips198/fips-198a.pdf |
+""" |
+ |
+# This is just a copy of the Python 2.2 HMAC module, modified to work when |
+# used on versions of Python before 2.2. |
+ |
+__revision__ = "$Id$" |
+ |
+__all__ = ['new', 'digest_size', 'HMAC' ] |
+ |
+from Crypto.Util.strxor import strxor_c |
+from Crypto.Util.py3compat import * |
+ |
+#: The size of the authentication tag produced by the MAC. |
+#: It matches the digest size on the underlying |
+#: hashing module used. |
+digest_size = None |
+ |
+class HMAC: |
+ """Class that implements HMAC""" |
+ |
+ #: The size of the authentication tag produced by the MAC. |
+ #: It matches the digest size on the underlying |
+ #: hashing module used. |
+ digest_size = None |
+ |
+ def __init__(self, key, msg = None, digestmod = None): |
+ """Create a new HMAC object. |
+ |
+ :Parameters: |
+ key : byte string |
+ secret key for the MAC object. |
+ It must be long enough to match the expected security level of the |
+ MAC. However, there is no benefit in using keys longer than the |
+ `digest_size` of the underlying hash algorithm. |
+ msg : byte string |
+ The very first chunk of the message to authenticate. |
+ It is equivalent to an early call to `update()`. Optional. |
+ :Parameter digestmod: |
+ The hash algorithm the HMAC is based on. |
+ Default is `Crypto.Hash.MD5`. |
+ :Type digestmod: |
+ A hash module or object instantiated from `Crypto.Hash` |
+ """ |
+ if digestmod is None: |
+ import MD5 |
+ digestmod = MD5 |
+ |
+ self.digestmod = digestmod |
+ self.outer = digestmod.new() |
+ self.inner = digestmod.new() |
+ try: |
+ self.digest_size = digestmod.digest_size |
+ except AttributeError: |
+ self.digest_size = len(self.outer.digest()) |
+ |
+ try: |
+ # The block size is 128 bytes for SHA384 and SHA512 and 64 bytes |
+ # for the others hash function |
+ blocksize = digestmod.block_size |
+ except AttributeError: |
+ blocksize = 64 |
+ |
+ ipad = 0x36 |
+ opad = 0x5C |
+ |
+ if len(key) > blocksize: |
+ key = digestmod.new(key).digest() |
+ |
+ key = key + bchr(0) * (blocksize - len(key)) |
+ self.outer.update(strxor_c(key, opad)) |
+ self.inner.update(strxor_c(key, ipad)) |
+ if (msg): |
+ self.update(msg) |
+ |
+ def update(self, msg): |
+ """Continue authentication of a message by consuming the next chunk of data. |
+ |
+ Repeated calls are equivalent to a single call with the concatenation |
+ of all the arguments. In other words: |
+ |
+ >>> m.update(a); m.update(b) |
+ |
+ is equivalent to: |
+ |
+ >>> m.update(a+b) |
+ |
+ :Parameters: |
+ msg : byte string |
+ The next chunk of the message being authenticated |
+ """ |
+ |
+ self.inner.update(msg) |
+ |
+ def copy(self): |
+ """Return a copy ("clone") of the MAC object. |
+ |
+ The copy will have the same internal state as the original MAC |
+ object. |
+ This can be used to efficiently compute the MAC of strings that |
+ share a common initial substring. |
+ |
+ :Returns: An `HMAC` object |
+ """ |
+ other = HMAC(b("")) |
+ other.digestmod = self.digestmod |
+ other.inner = self.inner.copy() |
+ other.outer = self.outer.copy() |
+ return other |
+ |
+ def digest(self): |
+ """Return the **binary** (non-printable) MAC of the message that has |
+ been authenticated so far. |
+ |
+ This method does not change the state of the MAC object. |
+ You can continue updating the object after calling this function. |
+ |
+ :Return: A byte string of `digest_size` bytes. It may contain non-ASCII |
+ characters, including null bytes. |
+ """ |
+ h = self.outer.copy() |
+ h.update(self.inner.digest()) |
+ return h.digest() |
+ |
+ def hexdigest(self): |
+ """Return the **printable** MAC of the message that has been |
+ authenticated so far. |
+ |
+ This method does not change the state of the MAC object. |
+ |
+ :Return: A string of 2* `digest_size` bytes. It contains only |
+ hexadecimal ASCII digits. |
+ """ |
+ return "".join(["%02x" % bord(x) |
+ for x in tuple(self.digest())]) |
+ |
+def new(key, msg = None, digestmod = None): |
+ """Create a new HMAC object. |
+ |
+ :Parameters: |
+ key : byte string |
+ key for the MAC object. |
+ It must be long enough to match the expected security level of the |
+ MAC. However, there is no benefit in using keys longer than the |
+ `digest_size` of the underlying hash algorithm. |
+ msg : byte string |
+ The very first chunk of the message to authenticate. |
+ It is equivalent to an early call to `HMAC.update()`. |
+ Optional. |
+ :Parameter digestmod: |
+ The hash to use to implement the HMAC. Default is `Crypto.Hash.MD5`. |
+ :Type digestmod: |
+ A hash module or instantiated object from `Crypto.Hash` |
+ :Returns: An `HMAC` object |
+ """ |
+ return HMAC(key, msg, digestmod) |
+ |