Updated DB_Helper by adding firebase methods.

This commit is contained in:
Batuhan Berk Başoğlu 2020-10-05 16:53:40 -04:00
parent 485cc3bbba
commit c82121d036
1810 changed files with 537281 additions and 1 deletions

View file

@ -0,0 +1,273 @@
# ===================================================================
#
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
"""BLAKE2b cryptographic hash algorithm.
`BLAKE2b`_ is an optimized variant of BLAKE, one of the SHA-3 candidates that
made it to the final round of the NIST hash competition.
The algorithm uses 64 bit words, and it therefore works best on
64-bit platforms. The digest size ranges from 8 to 512 bits.
>>> from Crypto.Hash import BLAKE2b
>>>
>>> h_obj = BLAKE2b.new(digest_bits=512)
>>> h_obj.update(b'Some data')
>>> print h_obj.hexdigest()
Optionally, BLAKE2b can work as a cryptographic MAC when initialized
with a secret key.
>>> from Crypto.Hash import BLAKE2b
>>>
>>> mac = BLAKE2b.new(digest_bits=256, key=b'secret')
>>> mac.update(b'Some data')
>>> print mac.hexdigest()
:undocumented: __package__
.. _BLAKE2b: https://blake2.net/
"""
from binascii import unhexlify
from Crypto.Util.py3compat import b, bord, tobytes
from Crypto.Random import get_random_bytes
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
_raw_blake2b_lib = load_pycryptodome_raw_lib("Crypto.Hash._BLAKE2b",
"""
int blake2b_init(void **state,
const uint8_t *key,
size_t key_size,
size_t digest_size);
int blake2b_destroy(void *state);
int blake2b_update(void *state,
const uint8_t *buf,
size_t len);
int blake2b_digest(const void *state,
uint8_t digest[64]);
int blake2b_copy(const void *src, void *dst);
""")
class BLAKE2b_Hash(object):
"""Class that implements a BLAKE2b hash
"""
#: The internal block size of the hash algorithm in bytes.
block_size = 64
def __init__(self, data, key, digest_bytes, update_after_digest):
"""
Initialize a BLAKE2b hash object.
"""
#: The size of the resulting hash in bytes.
self.digest_size = digest_bytes
self._update_after_digest = update_after_digest
self._digest_done = False
# See https://tools.ietf.org/html/draft-saarinen-blake2-02
if digest_bytes in (20, 32, 48, 64) and not key:
self.oid = "1.3.6.1.4.1.1722.12.2.1." + str(digest_bytes)
expect_byte_string(key)
state = VoidPointer()
result = _raw_blake2b_lib.blake2b_init(state.address_of(),
key,
c_size_t(len(key)),
c_size_t(digest_bytes)
)
if result:
raise ValueError("Error %d while instantiating BLAKE2b" % result)
self._state = SmartPointer(state.get(),
_raw_blake2b_lib.blake2b_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
if self._digest_done and not self._update_after_digest:
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
expect_byte_string(data)
result = _raw_blake2b_lib.blake2b_update(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while hashing BLAKE2b data" % result)
return self
def digest(self):
"""Return the **binary** (non-printable) digest of the message that
has been hashed so far.
You cannot update the hash anymore after the first call to ``digest``
(or ``hexdigest``).
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
characters, including null bytes.
"""
bfr = create_string_buffer(64)
result = _raw_blake2b_lib.blake2b_digest(self._state.get(),
bfr)
if result:
raise ValueError("Error %d while creating BLAKE2b digest" % result)
self._digest_done = True
return get_raw_buffer(bfr)[:self.digest_size]
def hexdigest(self):
"""Return the **printable** digest of the message that has been
hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in tuple(self.digest())])
def verify(self, mac_tag):
"""Verify that a given **binary** MAC (computed by another party)
is valid.
:Parameters:
mac_tag : byte string
The expected MAC of the message.
:Raises ValueError:
if the MAC does not match. It means that the message
has been tampered with or that the MAC key is incorrect.
"""
secret = get_random_bytes(16)
mac1 = new(digest_bits=160, key=secret, data=mac_tag)
mac2 = new(digest_bits=160, key=secret, data=self.digest())
if mac1.digest() != mac2.digest():
raise ValueError("MAC check failed")
def hexverify(self, hex_mac_tag):
"""Verify that a given **printable** MAC (computed by another party)
is valid.
:Parameters:
hex_mac_tag : string
The expected MAC of the message, as a hexadecimal string.
:Raises ValueError:
if the MAC does not match. It means that the message
has been tampered with or that the MAC key is incorrect.
"""
self.verify(unhexlify(tobytes(hex_mac_tag)))
def new(self, **kwargs):
"""Return a new instance of a BLAKE2b hash object."""
if "digest_bytes" not in kwargs and "digest_bits" not in kwargs:
kwargs["digest_bytes"] = self.digest_size
return new(**kwargs)
def new(**kwargs):
"""Return a new instance of a BLAKE2b hash object.
:Keywords:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to `BLAKE2b_Hash.update()`.
digest_bytes : integer
The size of the digest, in bytes (1 to 64).
digest_bits : integer
The size of the digest, in bits (8 to 512, in steps of 8).
key : byte string
The key to use to compute the MAC (1 to 64 bytes).
If not specified, no key will be used.
update_after_digest : boolean
Optional. By default, a hash object cannot be updated anymore after
the digest is computed. When this flag is ``True``, such check
is no longer enforced.
:Return: A `BLAKE2b_Hash` object
"""
data = kwargs.pop("data", None)
update_after_digest = kwargs.pop("update_after_digest", False)
digest_bytes = kwargs.pop("digest_bytes", None)
digest_bits = kwargs.pop("digest_bits", None)
if None not in (digest_bytes, digest_bits):
raise TypeError("Only one digest parameter must be provided")
if (None, None) == (digest_bytes, digest_bits):
raise TypeError("Digest size (bits, bytes) not provided")
if digest_bytes is not None:
if not (1 <= digest_bytes <= 64):
raise ValueError("'digest_bytes' not in range 1..64")
else:
if not (8 <= digest_bits <= 512) or (digest_bits % 8):
raise ValueError("'digest_bytes' not in range 8..512, "
"with steps of 8")
digest_bytes = digest_bits // 8
key = kwargs.pop("key", b(""))
if len(key) > 64:
raise ValueError("BLAKE2s key cannot exceed 64 bytes")
if kwargs:
raise TypeError("Unknown parameters: " + str(kwargs))
return BLAKE2b_Hash(data, key, digest_bytes, update_after_digest)

View file

@ -0,0 +1,273 @@
# ===================================================================
#
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
"""BLAKE2s cryptographic hash algorithm.
`BLAKE2s`_ is an optimized variant of BLAKE, one of the SHA-3 candidates that
made it to the final round of the NIST hash competition.
The algorithm uses 32 bit words, and it therefore works best
on 32-bit platforms. The digest size ranges from 8 to 256 bits.
>>> from Crypto.Hash import BLAKE2s
>>>
>>> h_obj = BLAKE2s.new(digest_bits=256)
>>> h_obj.update(b'Some data')
>>> print h_obj.hexdigest()
Optionally, BLAKE2s can work as a cryptographic MAC when initialized
with a secret key.
>>> from Crypto.Hash import BLAKE2s
>>>
>>> mac = BLAKE2s.new(digest_bits=128, key=b'secret')
>>> mac.update(b'Some data')
>>> print mac.hexdigest()
:undocumented: __package__
.. _BLAKE2s: https://blake2.net/
"""
from binascii import unhexlify
from Crypto.Util.py3compat import b, bord, tobytes
from Crypto.Random import get_random_bytes
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
_raw_blake2s_lib = load_pycryptodome_raw_lib("Crypto.Hash._BLAKE2s",
"""
int blake2s_init(void **state,
const uint8_t *key,
size_t key_size,
size_t digest_size);
int blake2s_destroy(void *state);
int blake2s_update(void *state,
const uint8_t *buf,
size_t len);
int blake2s_digest(const void *state,
uint8_t digest[32]);
int blake2s_copy(const void *src, void *dst);
""")
class BLAKE2s_Hash(object):
"""Class that implements a BLAKE2s hash
"""
#: The internal block size of the hash algorithm in bytes.
block_size = 32
def __init__(self, data, key, digest_bytes, update_after_digest):
"""
Initialize a BLAKE2s hash object.
"""
#: The size of the resulting hash in bytes.
self.digest_size = digest_bytes
self._update_after_digest = update_after_digest
self._digest_done = False
# See https://tools.ietf.org/html/draft-saarinen-blake2-02
if digest_bytes in (16, 20, 28, 32) and not key:
self.oid = "1.3.6.1.4.1.1722.12.2.2." + str(digest_bytes)
expect_byte_string(key)
state = VoidPointer()
result = _raw_blake2s_lib.blake2s_init(state.address_of(),
key,
c_size_t(len(key)),
c_size_t(digest_bytes)
)
if result:
raise ValueError("Error %d while instantiating BLAKE2s" % result)
self._state = SmartPointer(state.get(),
_raw_blake2s_lib.blake2s_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
if self._digest_done and not self._update_after_digest:
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
expect_byte_string(data)
result = _raw_blake2s_lib.blake2s_update(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while hashing BLAKE2s data" % result)
return self
def digest(self):
"""Return the **binary** (non-printable) digest of the message that
has been hashed so far.
You cannot update the hash anymore after the first call to ``digest``
(or ``hexdigest``).
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
characters, including null bytes.
"""
bfr = create_string_buffer(32)
result = _raw_blake2s_lib.blake2s_digest(self._state.get(),
bfr)
if result:
raise ValueError("Error %d while creating BLAKE2s digest" % result)
self._digest_done = True
return get_raw_buffer(bfr)[:self.digest_size]
def hexdigest(self):
"""Return the **printable** digest of the message that has been hashed
so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in tuple(self.digest())])
def verify(self, mac_tag):
"""Verify that a given **binary** MAC (computed by another party)
is valid.
:Parameters:
mac_tag : byte string
The expected MAC of the message.
:Raises ValueError:
if the MAC does not match. It means that the message
has been tampered with or that the MAC key is incorrect.
"""
secret = get_random_bytes(16)
mac1 = new(digest_bits=160, key=secret, data=mac_tag)
mac2 = new(digest_bits=160, key=secret, data=self.digest())
if mac1.digest() != mac2.digest():
raise ValueError("MAC check failed")
def hexverify(self, hex_mac_tag):
"""Verify that a given **printable** MAC (computed by another party)
is valid.
:Parameters:
hex_mac_tag : string
The expected MAC of the message, as a hexadecimal string.
:Raises ValueError:
if the MAC does not match. It means that the message
has been tampered with or that the MAC key is incorrect.
"""
self.verify(unhexlify(tobytes(hex_mac_tag)))
def new(self, **kwargs):
"""Return a new instance of a BLAKE2s hash object."""
if "digest_bytes" not in kwargs and "digest_bits" not in kwargs:
kwargs["digest_bytes"] = self.digest_size
return new(**kwargs)
def new(**kwargs):
"""Return a new instance of a BLAKE2s hash object.
:Keywords:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to `BLAKE2s_Hash.update()`.
digest_bytes : integer
The size of the digest, in bytes (1 to 32).
digest_bits : integer
The size of the digest, in bits (8 to 256, in steps of 8).
key : byte string
The key to use to compute the MAC (1 to 32 bytes).
If not specified, no key will be used.
update_after_digest : boolean
Optional. By default, a hash object cannot be updated anymore after
the digest is computed. When this flag is ``True``, such check
is no longer enforced.
:Return: A `BLAKE2s_Hash` object
"""
data = kwargs.pop("data", None)
update_after_digest = kwargs.pop("update_after_digest", False)
digest_bytes = kwargs.pop("digest_bytes", None)
digest_bits = kwargs.pop("digest_bits", None)
if None not in (digest_bytes, digest_bits):
raise TypeError("Only one digest parameter must be provided")
if (None, None) == (digest_bytes, digest_bits):
raise TypeError("Digest size (bits, bytes) not provided")
if digest_bytes is not None:
if not (1 <= digest_bytes <= 32):
raise ValueError("'digest_bytes' not in range 1..32")
else:
if not (8 <= digest_bits <= 256) or (digest_bits % 8):
raise ValueError("'digest_bytes' not in range 8..256, "
"with steps of 8")
digest_bytes = digest_bits // 8
key = kwargs.pop("key", b(""))
if len(key) > 32:
raise ValueError("BLAKE2s key cannot exceed 32 bytes")
if kwargs:
raise TypeError("Unknown parameters: " + str(kwargs))
return BLAKE2s_Hash(data, key, digest_bytes, update_after_digest)

View file

@ -0,0 +1,352 @@
# -*- coding: utf-8 -*-
#
# Hash/CMAC.py - Implements the CMAC algorithm
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""CMAC (Cipher-based Message Authentication Code) algorithm
CMAC is a MAC defined in `NIST SP 800-38B`_ and in RFC4493_ (for AES only)
and constructed using a block cipher. It was originally known as `OMAC1`_.
The algorithm is sometimes named *X-CMAC* where *X* is the name
of the cipher (e.g. AES-CMAC).
This is an example showing how to *create* an AES-CMAC:
>>> from Crypto.Hash import CMAC
>>> from Crypto.Cipher import AES
>>>
>>> secret = b'Sixteen byte key'
>>> cobj = CMAC.new(secret, ciphermod=AES)
>>> cobj.update(b'Hello')
>>> print cobj.hexdigest()
And this is an example showing how to *check* an AES-CMAC:
>>> from Crypto.Hash import CMAC
>>> from Crypto.Cipher import AES
>>>
>>> # We have received a message 'msg' together
>>> # with its MAC 'mac'
>>>
>>> secret = b'Sixteen byte key'
>>> cobj = CMAC.new(secret, ciphermod=AES)
>>> cobj.update(msg)
>>> try:
>>> cobj.verify(mac)
>>> print "The message '%s' is authentic" % msg
>>> except ValueError:
>>> print "The message or the key is wrong"
A cipher block size of 128 bits (like for AES) guarantees that the risk
of MAC collisions remains negligeable even when the same CMAC key is
used to authenticate a large amount of data (2^22 Gbytes).
This implementation allows also usage of ciphers with a 64 bits block size
(like TDES) for legacy purposes only.
However, the risk is much higher and one CMAC key should be rotated
after as little as 16 MBytes (in total) have been authenticated.
.. _`NIST SP 800-38B`: http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
.. _RFC4493: http://www.ietf.org/rfc/rfc4493.txt
.. _OMAC1: http://www.nuee.nagoya-u.ac.jp/labs/tiwata/omac/omac.html
"""
from Crypto.Util.py3compat import b, bchr, bord, tobytes
from binascii import unhexlify
from Crypto.Hash import BLAKE2s
from Crypto.Util.strxor import strxor
from Crypto.Util.number import long_to_bytes, bytes_to_long
from Crypto.Random import get_random_bytes
#: The size of the authentication tag produced by the MAC.
digest_size = None
def _shift_bytes(bs, xor_lsb=0):
num = (bytes_to_long(bs) << 1) ^ xor_lsb
return long_to_bytes(num, len(bs))[-len(bs):]
class CMAC(object):
"""Class that implements CMAC"""
#: The size of the authentication tag produced by the MAC.
digest_size = None
def __init__(self, key, msg=None, ciphermod=None, cipher_params=None):
"""Create a new CMAC object.
:Parameters:
key : byte string
secret key for the CMAC object.
The key must be valid for the underlying cipher algorithm.
For instance, it must be 16 bytes long for AES-128.
msg : byte string
The very first chunk of the message to authenticate.
It is equivalent to an early call to `update`. Optional.
ciphermod : module
A cipher module from `Crypto.Cipher`.
The cipher's block size has to be 128 bits.
It is recommended to use `Crypto.Cipher.AES`.
cipher_params : dictionary
Extra keywords to use when creating a new cipher.
"""
if ciphermod is None:
raise TypeError("ciphermod must be specified (try AES)")
self._key = key
self._factory = ciphermod
if cipher_params is None:
self._cipher_params = {}
else:
self._cipher_params = dict(cipher_params)
# Section 5.3 of NIST SP 800 38B and Appendix B
if ciphermod.block_size == 8:
const_Rb = 0x1B
self._max_size = 8 * (2 ** 21)
elif ciphermod.block_size == 16:
const_Rb = 0x87
self._max_size = 16 * (2 ** 48)
else:
raise TypeError("CMAC requires a cipher with a block size"
"of 8 or 16 bytes, not %d" %
(ciphermod.block_size,))
# Size of the final MAC tag, in bytes
self.digest_size = ciphermod.block_size
self._mac_tag = None
# Compute sub-keys
zero_block = bchr(0) * ciphermod.block_size
cipher = ciphermod.new(key,
ciphermod.MODE_ECB,
**self._cipher_params)
l = cipher.encrypt(zero_block)
if bord(l[0]) & 0x80:
self._k1 = _shift_bytes(l, const_Rb)
else:
self._k1 = _shift_bytes(l)
if bord(self._k1[0]) & 0x80:
self._k2 = _shift_bytes(self._k1, const_Rb)
else:
self._k2 = _shift_bytes(self._k1)
# Initialize CBC cipher with zero IV
self._cbc = ciphermod.new(key,
ciphermod.MODE_CBC,
zero_block,
**self._cipher_params)
# Cache for outstanding data to authenticate
self._cache = b("")
# Last two pieces of ciphertext produced
self._last_ct = self._last_pt = zero_block
self._before_last_ct = None
# Counter for total message size
self._data_size = 0
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._data_size += len(msg)
if len(self._cache) > 0:
filler = min(self.digest_size - len(self._cache), len(msg))
self._cache += msg[:filler]
if len(self._cache) < self.digest_size:
return self
msg = msg[filler:]
self._update(self._cache)
self._cache = b("")
update_len, remain = divmod(len(msg), self.digest_size)
update_len *= self.digest_size
if remain > 0:
self._update(msg[:update_len])
self._cache = msg[update_len:]
else:
self._update(msg)
self._cache = b("")
return self
def _update(self, data_block):
"""Update a block aligned to the block boundary"""
if len(data_block) == 0:
return
assert len(data_block) % self.digest_size == 0
ct = self._cbc.encrypt(data_block)
if len(data_block) == self.digest_size:
self._before_last_ct = self._last_ct
else:
self._before_last_ct = ct[-self.digest_size * 2:-self.digest_size]
self._last_ct = ct[-self.digest_size:]
self._last_pt = data_block[-self.digest_size:]
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: A `CMAC` object
"""
obj = CMAC(self._key,
ciphermod=self._factory,
cipher_params=self._cipher_params)
obj._cbc = self._factory.new(self._key,
self._factory.MODE_CBC,
self._last_ct,
**self._cipher_params)
for m in ['_mac_tag', '_last_ct', '_before_last_ct', '_cache',
'_data_size', '_max_size']:
setattr(obj, m, getattr(self, m))
return obj
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.
"""
if self._mac_tag is not None:
return self._mac_tag
if self._data_size > self._max_size:
raise ValueError("MAC is unsafe for this message")
if len(self._cache) == 0 and self._before_last_ct is not None:
## Last block was full
pt = strxor(strxor(self._before_last_ct, self._k1), self._last_pt)
else:
## Last block is partial (or message length is zero)
ext = self._cache + bchr(0x80) +\
bchr(0) * (self.digest_size - len(self._cache) - 1)
pt = strxor(strxor(self._last_ct, self._k2), ext)
cipher = self._factory.new(self._key,
self._factory.MODE_ECB,
**self._cipher_params)
self._mac_tag = cipher.encrypt(pt)
return self._mac_tag
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 verify(self, mac_tag):
"""Verify that a given **binary** MAC (computed by another party)
is valid.
:Parameters:
mac_tag : byte string
The expected MAC of the message.
:Raises ValueError:
if the MAC does not match. It means that the message
has been tampered with or that the MAC key is incorrect.
"""
secret = get_random_bytes(16)
mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag)
mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest())
if mac1.digest() != mac2.digest():
raise ValueError("MAC check failed")
def hexverify(self, hex_mac_tag):
"""Verify that a given **printable** MAC (computed by another party)
is valid.
:Parameters:
hex_mac_tag : string
The expected MAC of the message, as a hexadecimal string.
:Raises ValueError:
if the MAC does not match. It means that the message
has been tampered with or that the MAC key is incorrect.
"""
self.verify(unhexlify(tobytes(hex_mac_tag)))
def new(key, msg=None, ciphermod=None, cipher_params=None):
"""Create a new CMAC object.
:Parameters:
key : byte string
secret key for the CMAC object.
The key must be valid for the underlying cipher algorithm.
For instance, it must be 16 bytes long for AES-128.
msg : byte string
The very first chunk of the message to authenticate.
It is equivalent to an early call to `CMAC.update`. Optional.
ciphermod : module
A cipher module from `Crypto.Cipher`.
The cipher's block size has to be 128 bits,
like `Crypto.Cipher.AES`, to reduce the probability of collisions.
:Returns: A `CMAC` object
"""
return CMAC(key, msg, ciphermod, cipher_params)

View file

@ -0,0 +1,264 @@
#
# HMAC.py - Implements the HMAC algorithm as described by RFC 2104.
#
# ===================================================================
#
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
"""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
This is an example showing how to *create* a MAC:
>>> from Crypto.Hash import HMAC
>>>
>>> secret = b'Swordfish'
>>> h = HMAC.new(secret)
>>> h.update(b'Hello')
>>> print h.hexdigest()
This is an example showing how to *check* a MAC:
>>> from Crypto.Hash import HMAC
>>>
>>> # We have received a message 'msg' together
>>> # with its MAC 'mac'
>>>
>>> secret = b'Swordfish'
>>> h = HMAC.new(secret)
>>> h.update(msg)
>>> try:
>>> h.verify(mac)
>>> print "The message '%s' is authentic" % msg
>>> except ValueError:
>>> print "The message or the key is wrong"
.. _RFC2104: http://www.ietf.org/rfc/rfc2104.txt
.. _FIPS-198: http://csrc.nist.gov/publications/fips/fips198/fips-198-1_final.pdf
"""
__all__ = ['new', 'HMAC']
from Crypto.Util.py3compat import b, bchr, bord, tobytes
from binascii import unhexlify
from . import MD5, BLAKE2s
from Crypto.Util.strxor import strxor
from Crypto.Random import get_random_bytes
class HMAC:
"""Class that implements HMAC"""
def __init__(self, key, msg=b(""), 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:
digestmod = MD5
if msg is None:
msg = b("")
#: Size of the MAC tag
self.digest_size = digestmod.digest_size
self._digestmod = digestmod
try:
if len(key) <= digestmod.block_size:
# Step 1 or 2
key_0 = key + bchr(0) * (digestmod.block_size - len(key))
else:
# Step 3
hash_k = digestmod.new(key).digest()
key_0 = hash_k + bchr(0) * (digestmod.block_size - len(hash_k))
except AttributeError:
# Not all hash types have "block_size"
raise ValueError("Hash type incompatible to HMAC")
# Step 4
key_0_ipad = strxor(key_0, bchr(0x36) * len(key_0))
# Start step 5 and 6
self._inner = digestmod.new(key_0_ipad)
self._inner.update(msg)
# Step 7
key_0_opad = strxor(key_0, bchr(0x5c) * len(key_0))
# Start step 8 and 9
self._outer = digestmod.new(key_0_opad)
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
"""
new_hmac = HMAC(b("fake key"), digestmod=self._digestmod)
# Syncronize the state
new_hmac._inner = self._inner.copy()
new_hmac._outer = self._outer.copy()
return new_hmac
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.
"""
frozen_outer_hash = self._outer.copy()
frozen_outer_hash.update(self._inner.digest())
return frozen_outer_hash.digest()
def verify(self, mac_tag):
"""Verify that a given **binary** MAC (computed by another party)
is valid.
:Parameters:
mac_tag : byte string
The expected MAC of the message.
:Raises ValueError:
if the MAC does not match. It means that the message
has been tampered with or that the MAC key is incorrect.
"""
secret = get_random_bytes(16)
mac1 = BLAKE2s.new(digest_bits=160, key=secret, data=mac_tag)
mac2 = BLAKE2s.new(digest_bits=160, key=secret, data=self.digest())
if mac1.digest() != mac2.digest():
raise ValueError("MAC check failed")
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 hexverify(self, hex_mac_tag):
"""Verify that a given **printable** MAC (computed by another party)
is valid.
:Parameters:
hex_mac_tag : string
The expected MAC of the message, as a hexadecimal string.
:Raises ValueError:
if the MAC does not match. It means that the message
has been tampered with or that the MAC key is incorrect.
"""
self.verify(unhexlify(tobytes(hex_mac_tag)))
def new(key, msg=b(""), 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)

View file

@ -0,0 +1,188 @@
# ===================================================================
#
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
"""
MD2 cryptographic hash algorithm.
MD2 is specified in RFC1319_ and it produces the 128 bit digest of a message.
>>> from Crypto.Hash import MD2
>>>
>>> h = MD2.new()
>>> h.update(b'Hello')
>>> print h.hexdigest()
MD2 stand for Message Digest version 2, and it was invented by Rivest in 1989.
This algorithm is both slow and insecure. Do not use it for new designs.
.. _RFC1319: http://tools.ietf.org/html/rfc1319
"""
from Crypto.Util.py3compat import bord
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
_raw_md2_lib = load_pycryptodome_raw_lib(
"Crypto.Hash._MD2",
"""
int md2_init(void **shaState);
int md2_destroy(void *shaState);
int md2_update(void *hs,
const uint8_t *buf,
size_t len);
int md2_digest(const void *shaState,
uint8_t digest[20]);
int md2_copy(const void *src, void *dst);
""")
class MD2Hash(object):
"""Class that implements an MD2 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 16
#: The internal block size of the hash algorithm in bytes.
block_size = 64
#: ASN.1 Object ID
oid = "1.2.840.113549.2.2"
def __init__(self, data=None):
state = VoidPointer()
result = _raw_md2_lib.md2_init(state.address_of())
if result:
raise ValueError("Error %d while instantiating MD2"
% result)
self._state = SmartPointer(state.get(),
_raw_md2_lib.md2_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
expect_byte_string(data)
result = _raw_md2_lib.md2_update(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while instantiating MD2"
% result)
def digest(self):
"""Return the **binary** (non-printable) digest of the message that
has been hashed so far.
This method does not change the state of the hash 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.
"""
bfr = create_string_buffer(self.digest_size)
result = _raw_md2_lib.md2_digest(self._state.get(),
bfr)
if result:
raise ValueError("Error %d while instantiating MD2"
% result)
return get_raw_buffer(bfr)
def hexdigest(self):
"""Return the **printable** digest of the message that has been
hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def copy(self):
"""Return a copy ("clone") of the hash object.
The copy will have the same internal state as the original hash
object.
This can be used to efficiently compute the digests of strings that
share a common initial substring.
:Return: A hash object of the same type
"""
clone = MD2Hash()
result = _raw_md2_lib.md2_copy(self._state.get(),
clone._state.get())
if result:
raise ValueError("Error %d while copying MD2" % result)
return clone
def new(self, data=None):
return MD2Hash(data)
def new(data=None):
"""Return a fresh instance of the hash object.
:Parameters:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to `MD2Hash.update()`.
Optional.
:Return: A `MD2Hash` object
"""
return MD2Hash().new(data)
#: The size of the resulting hash in bytes.
digest_size = MD2Hash.digest_size
#: The internal block size of the hash algorithm in bytes.
block_size = MD2Hash.block_size

View file

@ -0,0 +1,186 @@
# ===================================================================
#
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
"""
MD4 is specified in RFC1320_ and produces the 128 bit digest of a message.
>>> from Crypto.Hash import MD4
>>>
>>> h = MD4.new()
>>> h.update(b'Hello')
>>> print h.hexdigest()
MD4 stand for Message Digest version 4, and it was invented by Rivest in 1990.
This algorithm is insecure. Do not use it for new designs.
.. _RFC1320: http://tools.ietf.org/html/rfc1320
"""
from Crypto.Util.py3compat import bord
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
_raw_md4_lib = load_pycryptodome_raw_lib(
"Crypto.Hash._MD4",
"""
int md4_init(void **shaState);
int md4_destroy(void *shaState);
int md4_update(void *hs,
const uint8_t *buf,
size_t len);
int md4_digest(const void *shaState,
uint8_t digest[20]);
int md4_copy(const void *src, void *dst);
""")
class MD4Hash(object):
"""Class that implements an MD4 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 16
#: The internal block size of the hash algorithm in bytes.
block_size = 64
#: ASN.1 Object ID
oid = "1.2.840.113549.2.4"
def __init__(self, data=None):
state = VoidPointer()
result = _raw_md4_lib.md4_init(state.address_of())
if result:
raise ValueError("Error %d while instantiating MD4"
% result)
self._state = SmartPointer(state.get(),
_raw_md4_lib.md4_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
expect_byte_string(data)
result = _raw_md4_lib.md4_update(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while instantiating MD4"
% result)
def digest(self):
"""Return the **binary** (non-printable) digest of the message that
has been hashed so far.
This method does not change the state of the hash 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.
"""
bfr = create_string_buffer(self.digest_size)
result = _raw_md4_lib.md4_digest(self._state.get(),
bfr)
if result:
raise ValueError("Error %d while instantiating MD4"
% result)
return get_raw_buffer(bfr)
def hexdigest(self):
"""Return the **printable** digest of the message that has been
hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def copy(self):
"""Return a copy ("clone") of the hash object.
The copy will have the same internal state as the original hash
object.
This can be used to efficiently compute the digests of strings that
share a common initial substring.
:Return: A hash object of the same type
"""
clone = MD4Hash()
result = _raw_md4_lib.md4_copy(self._state.get(),
clone._state.get())
if result:
raise ValueError("Error %d while copying MD4" % result)
return clone
def new(self, data=None):
return MD4Hash(data)
def new(data=None):
"""Return a fresh instance of the hash object.
:Parameters:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to `MD4Hash.update()`.
Optional.
:Return: A `MD4Hash` object
"""
return MD4Hash().new(data)
#: The size of the resulting hash in bytes.
digest_size = MD4Hash.digest_size
#: The internal block size of the hash algorithm in bytes.
block_size = MD4Hash.block_size

View file

@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""MD5 cryptographic hash algorithm.
MD5 is specified in RFC1321_ and produces the 128 bit digest of a message.
>>> from Crypto.Hash import MD5
>>>
>>> h = MD5.new()
>>> h.update(b'Hello')
>>> print h.hexdigest()
MD5 stand for Message Digest version 5, and it was invented by Rivest in 1991.
This algorithm is insecure. Do not use it for new designs.
.. _RFC1321: http://tools.ietf.org/html/rfc1321
"""
__all__ = ['new', 'block_size', 'digest_size']
from Crypto.Util.py3compat import *
def __make_constructor():
try:
# The md5 module is deprecated in Python 2.6, so use hashlib when possible.
from hashlib import md5 as _hash_new
except ImportError:
from .md5 import new as _hash_new
h = _hash_new()
if hasattr(h, 'new') and hasattr(h, 'name') and hasattr(h, 'digest_size') and hasattr(h, 'block_size'):
# The module from stdlib has the API that we need. Just use it.
return _hash_new
else:
# Wrap the hash object in something that gives us the expected API.
_copy_sentinel = object()
class _MD5(object):
digest_size = 16
block_size = 64
oid = "1.2.840.113549.2.5"
def __init__(self, *args):
if args and args[0] is _copy_sentinel:
self._h = args[1]
else:
self._h = _hash_new(*args)
def copy(self):
return _MD5(_copy_sentinel, self._h.copy())
def update(self, *args):
f = self.update = self._h.update
f(*args)
def digest(self):
f = self.digest = self._h.digest
return f()
def hexdigest(self):
f = self.hexdigest = self._h.hexdigest
return f()
_MD5.new = _MD5
return _MD5
new = __make_constructor()
del __make_constructor
#: The size of the resulting hash in bytes.
digest_size = new().digest_size
#: The internal block size of the hash algorithm in bytes.
block_size = new().block_size

View file

@ -0,0 +1,26 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
# This file exists for backward compatibility with old code that refers to
# Crypto.Hash.RIPEMD
"""Deprecated alias for `Crypto.Hash.RIPEMD160`"""
from Crypto.Hash.RIPEMD160 import new, block_size, digest_size

View file

@ -0,0 +1,191 @@
# ===================================================================
#
# Copyright (c) 2014, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
"""RIPEMD-160 cryptographic hash algorithm.
RIPEMD-160_ produces the 160 bit digest of a message.
>>> from Crypto.Hash import RIPEMD160
>>>
>>> h = RIPEMD160.new()
>>> h.update(b'Hello')
>>> print h.hexdigest()
RIPEMD-160 stands for RACE Integrity Primitives Evaluation Message Digest
with a 160 bit digest. It was invented by Dobbertin, Bosselaers, and Preneel.
This algorithm is considered secure, although it has not been scrutinized as
extensively as SHA-1. Moreover, it provides an informal security level of just
80bits.
.. _RIPEMD-160: http://homes.esat.kuleuven.be/~bosselae/ripemd160.html
"""
from Crypto.Util.py3compat import bord
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
_raw_ripemd160_lib = load_pycryptodome_raw_lib(
"Crypto.Hash._RIPEMD160",
"""
int ripemd160_init(void **shaState);
int ripemd160_destroy(void *shaState);
int ripemd160_update(void *hs,
const uint8_t *buf,
size_t len);
int ripemd160_digest(const void *shaState,
uint8_t digest[20]);
int ripemd160_copy(const void *src, void *dst);
""")
class RIPEMD160Hash(object):
"""Class that implements a RIPEMD-160 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 20
#: The internal block size of the hash algorithm in bytes.
block_size = 64
#: ASN.1 Object ID
oid = "1.3.36.3.2.1"
def __init__(self, data=None):
state = VoidPointer()
result = _raw_ripemd160_lib.ripemd160_init(state.address_of())
if result:
raise ValueError("Error %d while instantiating RIPEMD160"
% result)
self._state = SmartPointer(state.get(),
_raw_ripemd160_lib.ripemd160_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
expect_byte_string(data)
result = _raw_ripemd160_lib.ripemd160_update(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while instantiating ripemd160"
% result)
def digest(self):
"""Return the **binary** (non-printable) digest of the message that
has been hashed so far.
This method does not change the state of the hash 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.
"""
bfr = create_string_buffer(self.digest_size)
result = _raw_ripemd160_lib.ripemd160_digest(self._state.get(),
bfr)
if result:
raise ValueError("Error %d while instantiating ripemd160"
% result)
return get_raw_buffer(bfr)
def hexdigest(self):
"""Return the **printable** digest of the message that has been
hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def copy(self):
"""Return a copy ("clone") of the hash object.
The copy will have the same internal state as the original hash
object.
This can be used to efficiently compute the digests of strings that
share a common initial substring.
:Return: A hash object of the same type
"""
clone = RIPEMD160Hash()
result = _raw_ripemd160_lib.ripemd160_copy(self._state.get(),
clone._state.get())
if result:
raise ValueError("Error %d while copying ripemd160" % result)
return clone
def new(self, data=None):
return RIPEMD160Hash(data)
def new(data=None):
"""Return a fresh instance of the hash object.
:Parameters:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to `RIPEMD160Hash.update()`.
Optional.
:Return: A `RIPEMD160Hash` object
"""
return RIPEMD160Hash().new(data)
#: The size of the resulting hash in bytes.
digest_size = RIPEMD160Hash.digest_size
#: The internal block size of the hash algorithm in bytes.
block_size = RIPEMD160Hash.block_size

View file

@ -0,0 +1,24 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
# This file exists for backward compatibility with old code that refers to
# Crypto.Hash.SHA
from Crypto.Hash.SHA1 import __doc__, new, block_size, digest_size

View file

@ -0,0 +1,86 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""SHA-1 cryptographic hash algorithm.
SHA-1_ produces the 160 bit digest of a message.
>>> from Crypto.Hash import SHA1
>>>
>>> h = SHA1.new()
>>> h.update(b'Hello')
>>> print h.hexdigest()
*SHA* stands for Secure Hash Algorithm.
This algorithm is not considered secure. Do not use it for new designs.
.. _SHA-1: http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
"""
__all__ = ['new', 'block_size', 'digest_size']
from Crypto.Util.py3compat import *
def __make_constructor():
try:
# The sha module is deprecated in Python 2.6, so use hashlib when possible.
from hashlib import sha1 as _hash_new
except ImportError:
from .sha import new as _hash_new
h = _hash_new()
if hasattr(h, 'new') and hasattr(h, 'name') and hasattr(h, 'digest_size') and hasattr(h, 'block_size'):
# The module from stdlib has the API that we need. Just use it.
return _hash_new
else:
# Wrap the hash object in something that gives us the expected API.
_copy_sentinel = object()
class _SHA1(object):
digest_size = 20
block_size = 64
oid = "1.3.14.3.2.26"
def __init__(self, *args):
if args and args[0] is _copy_sentinel:
self._h = args[1]
else:
self._h = _hash_new(*args)
def copy(self):
return _SHA1(_copy_sentinel, self._h.copy())
def update(self, *args):
f = self.update = self._h.update
f(*args)
def digest(self):
f = self.digest = self._h.digest
return f()
def hexdigest(self):
f = self.hexdigest = self._h.hexdigest
return f()
_SHA1.new = _SHA1
return _SHA1
new = __make_constructor()
del __make_constructor
#: The size of the resulting hash in bytes.
digest_size = new().digest_size
#: The internal block size of the hash algorithm in bytes.
block_size = new().block_size

View file

@ -0,0 +1,173 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""SHA-224 cryptographic hash algorithm.
SHA-224 belongs to the SHA-2_ family of cryptographic hashes.
It produces the 224 bit digest of a message.
>>> from Crypto.Hash import SHA224
>>>
>>> h = SHA224.new()
>>> h.update(b'Hello')
>>> print h.hexdigest()
*SHA* stands for Secure Hash Algorithm.
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-4.pdf
"""
from Crypto.Util.py3compat import *
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
_raw_sha224_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA224",
"""
int SHA224_init(void **shaState);
int SHA224_destroy(void *shaState);
int SHA224_update(void *hs,
const uint8_t *buf,
size_t len);
int SHA224_digest(const void *shaState,
uint8_t digest[16]);
int SHA224_copy(const void *src, void *dst);
""")
class SHA224Hash(object):
"""Class that implements a SHA-224 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 28
#: The internal block size of the hash algorithm in bytes.
block_size = 64
#: ASN.1 Object ID
oid = '2.16.840.1.101.3.4.2.4'
def __init__(self, data=None):
state = VoidPointer()
result = _raw_sha224_lib.SHA224_init(state.address_of())
if result:
raise ValueError("Error %d while instantiating SHA224"
% result)
self._state = SmartPointer(state.get(),
_raw_sha224_lib.SHA224_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
expect_byte_string(data)
result = _raw_sha224_lib.SHA224_update(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while instantiating SHA224"
% result)
def digest(self):
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
This method does not change the state of the hash 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.
"""
bfr = create_string_buffer(self.digest_size)
result = _raw_sha224_lib.SHA224_digest(self._state.get(),
bfr)
if result:
raise ValueError("Error %d while instantiating SHA224"
% result)
return get_raw_buffer(bfr)
def hexdigest(self):
"""Return the **printable** digest of the message that has been hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def copy(self):
"""Return a copy ("clone") of the hash object.
The copy will have the same internal state as the original hash
object.
This can be used to efficiently compute the digests of strings that
share a common initial substring.
:Return: A hash object of the same type
"""
clone = SHA224Hash()
result = _raw_sha224_lib.SHA224_copy(self._state.get(),
clone._state.get())
if result:
raise ValueError("Error %d while copying SHA224" % result)
return clone
def new(self, data=None):
return SHA224Hash(data)
def new(data=None):
"""Return a fresh instance of the hash object.
:Parameters:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to `SHA224Hash.update()`.
Optional.
:Return: A `SHA224Hash` object
"""
return SHA224Hash().new(data)
#: The size of the resulting hash in bytes.
digest_size = SHA224Hash.digest_size
#: The internal block size of the hash algorithm in bytes.
block_size = SHA224Hash.block_size

View file

@ -0,0 +1,173 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""SHA-256 cryptographic hash algorithm.
SHA-256 belongs to the SHA-2_ family of cryptographic hashes.
It produces the 256 bit digest of a message.
>>> from Crypto.Hash import SHA256
>>>
>>> h = SHA256.new()
>>> h.update(b'Hello')
>>> print h.hexdigest()
*SHA* stands for Secure Hash Algorithm.
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-4.pdf
"""
from Crypto.Util.py3compat import *
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
_raw_sha256_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA256",
"""
int SHA256_init(void **shaState);
int SHA256_destroy(void *shaState);
int SHA256_update(void *hs,
const uint8_t *buf,
size_t len);
int SHA256_digest(const void *shaState,
uint8_t digest[32]);
int SHA256_copy(const void *src, void *dst);
""")
class SHA256Hash(object):
"""Class that implements a SHA-256 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 32
#: The internal block size of the hash algorithm in bytes.
block_size = 64
#: ASN.1 Object ID
oid = "2.16.840.1.101.3.4.2.1"
def __init__(self, data=None):
state = VoidPointer()
result = _raw_sha256_lib.SHA256_init(state.address_of())
if result:
raise ValueError("Error %d while instantiating SHA256"
% result)
self._state = SmartPointer(state.get(),
_raw_sha256_lib.SHA256_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
expect_byte_string(data)
result = _raw_sha256_lib.SHA256_update(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while instantiating SHA256"
% result)
def digest(self):
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
This method does not change the state of the hash 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.
"""
bfr = create_string_buffer(self.digest_size)
result = _raw_sha256_lib.SHA256_digest(self._state.get(),
bfr)
if result:
raise ValueError("Error %d while instantiating SHA256"
% result)
return get_raw_buffer(bfr)
def hexdigest(self):
"""Return the **printable** digest of the message that has been hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def copy(self):
"""Return a copy ("clone") of the hash object.
The copy will have the same internal state as the original hash
object.
This can be used to efficiently compute the digests of strings that
share a common initial substring.
:Return: A hash object of the same type
"""
clone = SHA256Hash()
result = _raw_sha256_lib.SHA256_copy(self._state.get(),
clone._state.get())
if result:
raise ValueError("Error %d while copying SHA256" % result)
return clone
def new(self, data=None):
return SHA256Hash(data)
def new(data=None):
"""Return a fresh instance of the hash object.
:Parameters:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to `SHA256Hash.update()`.
Optional.
:Return: A `SHA256Hash` object
"""
return SHA256Hash().new(data)
#: The size of the resulting hash in bytes.
digest_size = SHA256Hash.digest_size
#: The internal block size of the hash algorithm in bytes.
block_size = SHA256Hash.block_size

View file

@ -0,0 +1,173 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""SHA-384 cryptographic hash algorithm.
SHA-384 belongs to the SHA-2_ family of cryptographic hashes.
It produces the 384 bit digest of a message.
>>> from Crypto.Hash import SHA384
>>>
>>> h = SHA384.new()
>>> h.update(b'Hello')
>>> print h.hexdigest()
*SHA* stands for Secure Hash Algorithm.
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-4.pdf
"""
from Crypto.Util.py3compat import *
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
_raw_sha384_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA384",
"""
int SHA384_init(void **shaState);
int SHA384_destroy(void *shaState);
int SHA384_update(void *hs,
const uint8_t *buf,
size_t len);
int SHA384_digest(const void *shaState,
uint8_t digest[48]);
int SHA384_copy(const void *src, void *dst);
""")
class SHA384Hash(object):
"""Class that implements a SHA-384 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 48
#: The internal block size of the hash algorithm in bytes.
block_size = 128
#: ASN.1 Object ID
oid = '2.16.840.1.101.3.4.2.2'
def __init__(self, data=None):
state = VoidPointer()
result = _raw_sha384_lib.SHA384_init(state.address_of())
if result:
raise ValueError("Error %d while instantiating SHA384"
% result)
self._state = SmartPointer(state.get(),
_raw_sha384_lib.SHA384_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
expect_byte_string(data)
result = _raw_sha384_lib.SHA384_update(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while instantiating SHA384"
% result)
def digest(self):
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
This method does not change the state of the hash 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.
"""
bfr = create_string_buffer(self.digest_size)
result = _raw_sha384_lib.SHA384_digest(self._state.get(),
bfr)
if result:
raise ValueError("Error %d while instantiating SHA384"
% result)
return get_raw_buffer(bfr)
def hexdigest(self):
"""Return the **printable** digest of the message that has been hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def copy(self):
"""Return a copy ("clone") of the hash object.
The copy will have the same internal state as the original hash
object.
This can be used to efficiently compute the digests of strings that
share a common initial substring.
:Return: A hash object of the same type
"""
clone = SHA384Hash()
result = _raw_sha384_lib.SHA384_copy(self._state.get(),
clone._state.get())
if result:
raise ValueError("Error %d while copying SHA384" % result)
return clone
def new(self, data=None):
return SHA384Hash(data)
def new(data=None):
"""Return a fresh instance of the hash object.
:Parameters:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to `SHA384Hash.update()`.
Optional.
:Return: A `SHA384Hash` object
"""
return SHA384Hash().new(data)
#: The size of the resulting hash in bytes.
digest_size = SHA384Hash.digest_size
#: The internal block size of the hash algorithm in bytes.
block_size = SHA384Hash.block_size

View file

@ -0,0 +1,168 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""SHA-3/224 cryptographic hash algorithm.
SHA-3/224 belongs to the SHA-3 family of cryptographic hashes, as specified
in `FIPS 202`__.
The hash function produces the 224 bit digest of a message.
>>> from Crypto.Hash import SHA3_224
>>>
>>> h_obj = SHA3_224.new()
>>> h_obj.update(b'Some data')
>>> print h_obj.hexdigest()
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
"""
from Crypto.Util.py3compat import bord
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
from Crypto.Hash.keccak import _raw_keccak_lib
class SHA3_224_Hash(object):
"""Class that implements a SHA-3/224 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 28
#: ASN.1 Object ID
oid = "2.16.840.1.101.3.4.2.7"
def __init__(self, data, update_after_digest):
self._update_after_digest = update_after_digest
self._digest_done = False
state = VoidPointer()
result = _raw_keccak_lib.keccak_init(state.address_of(),
c_size_t(self.digest_size * 2),
0x06)
if result:
raise ValueError("Error %d while instantiating SHA-3/224"
% result)
self._state = SmartPointer(state.get(),
_raw_keccak_lib.keccak_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
if self._digest_done and not self._update_after_digest:
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
expect_byte_string(data)
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while updating SHA-3/224"
% result)
return self
def digest(self):
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
You cannot update the hash anymore after the first call to ``digest``
(or ``hexdigest``).
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
characters, including null bytes.
"""
self._digest_done = True
bfr = create_string_buffer(self.digest_size)
result = _raw_keccak_lib.keccak_digest(self._state.get(),
bfr,
c_size_t(self.digest_size))
if result:
raise ValueError("Error %d while instantiating SHA-3/224"
% result)
self._digest_value = get_raw_buffer(bfr)
return self._digest_value
def hexdigest(self):
"""Return the **printable** digest of the message that has been hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def new(self):
return type(self)(None, self._update_after_digest)
def new(*args, **kwargs):
"""Return a fresh instance of the hash object.
:Keywords:
data : byte string
Optional. The very first chunk of the message to hash.
It is equivalent to an early call to ``update()``.
update_after_digest : boolean
Optional. By default, a hash object cannot be updated anymore after
the digest is computed. When this flag is ``True``, such check
is no longer enforced.
:Return: A `SHA3_224_Hash` object
"""
data = kwargs.pop("data", None)
update_after_digest = kwargs.pop("update_after_digest", False)
if len(args) == 1:
if data:
raise ValueError("Initial data for hash specified twice")
data = args[0]
if kwargs:
raise TypeError("Unknown parameters: " + str(kwargs))
return SHA3_224_Hash(data, update_after_digest)
#: The size of the resulting hash in bytes.
digest_size = SHA3_224_Hash.digest_size

View file

@ -0,0 +1,168 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""SHA-3/256 cryptographic hash algorithm.
SHA-3/256 belongs to the SHA-3 family of cryptographic hashes, as specified
in `FIPS 202`__.
The hash function produces the 256 bit digest of a message.
>>> from Crypto.Hash import SHA3_256
>>>
>>> h_obj = SHA3_256.new()
>>> h_obj.update(b'Some data')
>>> print h_obj.hexdigest()
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
"""
from Crypto.Util.py3compat import bord
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
from Crypto.Hash.keccak import _raw_keccak_lib
class SHA3_256_Hash(object):
"""Class that implements a SHA-3/256 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 32
#: ASN.1 Object ID
oid = "2.16.840.1.101.3.4.2.8"
def __init__(self, data, update_after_digest):
self._update_after_digest = update_after_digest
self._digest_done = False
state = VoidPointer()
result = _raw_keccak_lib.keccak_init(state.address_of(),
c_size_t(self.digest_size * 2),
0x06)
if result:
raise ValueError("Error %d while instantiating SHA-3/256"
% result)
self._state = SmartPointer(state.get(),
_raw_keccak_lib.keccak_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
if self._digest_done and not self._update_after_digest:
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
expect_byte_string(data)
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while updating SHA-3/256"
% result)
return self
def digest(self):
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
You cannot update the hash anymore after the first call to ``digest``
(or ``hexdigest``).
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
characters, including null bytes.
"""
self._digest_done = True
bfr = create_string_buffer(self.digest_size)
result = _raw_keccak_lib.keccak_digest(self._state.get(),
bfr,
c_size_t(self.digest_size))
if result:
raise ValueError("Error %d while instantiating SHA-3/256"
% result)
self._digest_value = get_raw_buffer(bfr)
return self._digest_value
def hexdigest(self):
"""Return the **printable** digest of the message that has been hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def new(self):
return type(self)(None, self._update_after_digest)
def new(*args, **kwargs):
"""Return a fresh instance of the hash object.
:Keywords:
data : byte string
Optional. The very first chunk of the message to hash.
It is equivalent to an early call to ``update()``.
update_after_digest : boolean
Optional. By default, a hash object cannot be updated anymore after
the digest is computed. When this flag is ``True``, such check
is no longer enforced.
:Return: A `SHA3_256_Hash` object
"""
data = kwargs.pop("data", None)
update_after_digest = kwargs.pop("update_after_digest", False)
if len(args) == 1:
if data:
raise ValueError("Initial data for hash specified twice")
data = args[0]
if kwargs:
raise TypeError("Unknown parameters: " + str(kwargs))
return SHA3_256_Hash(data, update_after_digest)
#: The size of the resulting hash in bytes.
digest_size = SHA3_256_Hash.digest_size

View file

@ -0,0 +1,168 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""SHA-3/384 cryptographic hash algorithm.
SHA-3/384 belongs to the SHA-3 family of cryptographic hashes, as specified
in `FIPS 202`__.
The hash function produces the 384 bit digest of a message.
>>> from Crypto.Hash import SHA3_384
>>>
>>> h_obj = SHA3_384.new()
>>> h_obj.update(b'Some data')
>>> print h_obj.hexdigest()
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
"""
from Crypto.Util.py3compat import bord
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
from Crypto.Hash.keccak import _raw_keccak_lib
class SHA3_384_Hash(object):
"""Class that implements a SHA-3/384 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 48
#: ASN.1 Object ID
oid = "2.16.840.1.101.3.4.2.9"
def __init__(self, data, update_after_digest):
self._update_after_digest = update_after_digest
self._digest_done = False
state = VoidPointer()
result = _raw_keccak_lib.keccak_init(state.address_of(),
c_size_t(self.digest_size * 2),
0x06)
if result:
raise ValueError("Error %d while instantiating SHA-3/384"
% result)
self._state = SmartPointer(state.get(),
_raw_keccak_lib.keccak_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
if self._digest_done and not self._update_after_digest:
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
expect_byte_string(data)
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while updating SHA-3/384"
% result)
return self
def digest(self):
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
You cannot update the hash anymore after the first call to ``digest``
(or ``hexdigest``).
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
characters, including null bytes.
"""
self._digest_done = True
bfr = create_string_buffer(self.digest_size)
result = _raw_keccak_lib.keccak_digest(self._state.get(),
bfr,
c_size_t(self.digest_size))
if result:
raise ValueError("Error %d while instantiating SHA-3/384"
% result)
self._digest_value = get_raw_buffer(bfr)
return self._digest_value
def hexdigest(self):
"""Return the **printable** digest of the message that has been hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def new(self):
return type(self)(None, self._update_after_digest)
def new(*args, **kwargs):
"""Return a fresh instance of the hash object.
:Keywords:
data : byte string
Optional. The very first chunk of the message to hash.
It is equivalent to an early call to ``update()``.
update_after_digest : boolean
Optional. By default, a hash object cannot be updated anymore after
the digest is computed. When this flag is ``True``, such check
is no longer enforced.
:Return: A `SHA3_384_Hash` object
"""
data = kwargs.pop("data", None)
update_after_digest = kwargs.pop("update_after_digest", False)
if len(args) == 1:
if data:
raise ValueError("Initial data for hash specified twice")
data = args[0]
if kwargs:
raise TypeError("Unknown parameters: " + str(kwargs))
return SHA3_384_Hash(data, update_after_digest)
#: The size of the resulting hash in bytes.
digest_size = SHA3_384_Hash.digest_size

View file

@ -0,0 +1,168 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""SHA-3/512 cryptographic hash algorithm.
SHA-3/512 belongs to the SHA-3 family of cryptographic hashes, as specified
in `FIPS 202`__.
The hash function produces the 512 bit digest of a message.
>>> from Crypto.Hash import SHA3_512
>>>
>>> h_obj = SHA3_512.new()
>>> h_obj.update(b'Some data')
>>> print h_obj.hexdigest()
.. __: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
"""
from Crypto.Util.py3compat import bord
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
from Crypto.Hash.keccak import _raw_keccak_lib
class SHA3_512_Hash(object):
"""Class that implements a SHA-3/512 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 64
#: ASN.1 Object ID
oid = "2.16.840.1.101.3.4.2.10"
def __init__(self, data, update_after_digest):
self._update_after_digest = update_after_digest
self._digest_done = False
state = VoidPointer()
result = _raw_keccak_lib.keccak_init(state.address_of(),
c_size_t(self.digest_size * 2),
0x06)
if result:
raise ValueError("Error %d while instantiating SHA-3/512"
% result)
self._state = SmartPointer(state.get(),
_raw_keccak_lib.keccak_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
if self._digest_done and not self._update_after_digest:
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
expect_byte_string(data)
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while updating SHA-3/512"
% result)
return self
def digest(self):
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
You cannot update the hash anymore after the first call to ``digest``
(or ``hexdigest``).
:Return: A byte string of `digest_size` bytes. It may contain non-ASCII
characters, including null bytes.
"""
self._digest_done = True
bfr = create_string_buffer(self.digest_size)
result = _raw_keccak_lib.keccak_digest(self._state.get(),
bfr,
c_size_t(self.digest_size))
if result:
raise ValueError("Error %d while instantiating SHA-3/512"
% result)
self._digest_value = get_raw_buffer(bfr)
return self._digest_value
def hexdigest(self):
"""Return the **printable** digest of the message that has been hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def new(self):
return type(self)(None, self._update_after_digest)
def new(*args, **kwargs):
"""Return a fresh instance of the hash object.
:Keywords:
data : byte string
Optional. The very first chunk of the message to hash.
It is equivalent to an early call to ``update()``.
update_after_digest : boolean
Optional. By default, a hash object cannot be updated anymore after
the digest is computed. When this flag is ``True``, such check
is no longer enforced.
:Return: A `SHA3_512_Hash` object
"""
data = kwargs.pop("data", None)
update_after_digest = kwargs.pop("update_after_digest", False)
if len(args) == 1:
if data:
raise ValueError("Initial data for hash specified twice")
data = args[0]
if kwargs:
raise TypeError("Unknown parameters: " + str(kwargs))
return SHA3_512_Hash(data, update_after_digest)
#: The size of the resulting hash in bytes.
digest_size = SHA3_512_Hash.digest_size

View file

@ -0,0 +1,173 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""SHA-512 cryptographic hash algorithm.
SHA-512 belongs to the SHA-2_ family of cryptographic hashes.
It produces the 512 bit digest of a message.
>>> from Crypto.Hash import SHA512
>>>
>>> h = SHA512.new()
>>> h.update(b'Hello')
>>> print h.hexdigest()
*SHA* stands for Secure Hash Algorithm.
.. _SHA-2: http://csrc.nist.gov/publications/fips/fips180-2/fips180-4.pdf
"""
from Crypto.Util.py3compat import *
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
_raw_sha512_lib = load_pycryptodome_raw_lib("Crypto.Hash._SHA512",
"""
int SHA512_init(void **shaState);
int SHA512_destroy(void *shaState);
int SHA512_update(void *hs,
const uint8_t *buf,
size_t len);
int SHA512_digest(const void *shaState,
uint8_t digest[64]);
int SHA512_copy(const void *src, void *dst);
""")
class SHA512Hash(object):
"""Class that implements a SHA-512 hash
"""
#: The size of the resulting hash in bytes.
digest_size = 64
#: The internal block size of the hash algorithm in bytes.
block_size = 128
#: ASN.1 Object ID
oid = "2.16.840.1.101.3.4.2.3"
def __init__(self, data=None):
state = VoidPointer()
result = _raw_sha512_lib.SHA512_init(state.address_of())
if result:
raise ValueError("Error %d while instantiating SHA512"
% result)
self._state = SmartPointer(state.get(),
_raw_sha512_lib.SHA512_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
expect_byte_string(data)
result = _raw_sha512_lib.SHA512_update(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while instantiating SHA512"
% result)
def digest(self):
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
This method does not change the state of the hash 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.
"""
bfr = create_string_buffer(self.digest_size)
result = _raw_sha512_lib.SHA512_digest(self._state.get(),
bfr)
if result:
raise ValueError("Error %d while instantiating SHA512"
% result)
return get_raw_buffer(bfr)
def hexdigest(self):
"""Return the **printable** digest of the message that has been hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def copy(self):
"""Return a copy ("clone") of the hash object.
The copy will have the same internal state as the original hash
object.
This can be used to efficiently compute the digests of strings that
share a common initial substring.
:Return: A hash object of the same type
"""
clone = SHA512Hash()
result = _raw_sha512_lib.SHA512_copy(self._state.get(),
clone._state.get())
if result:
raise ValueError("Error %d while copying SHA512" % result)
return clone
def new(self, data=None):
return SHA512Hash(data)
def new(data=None):
"""Return a fresh instance of the hash object.
:Parameters:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to `SHA512Hash.update()`.
Optional.
:Return: A `SHA512Hash` object
"""
return SHA512Hash().new(data)
#: The size of the resulting hash in bytes.
digest_size = SHA512Hash.digest_size
#: The internal block size of the hash algorithm in bytes.
block_size = SHA512Hash.block_size

View file

@ -0,0 +1,151 @@
# ===================================================================
#
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
"""SHAKE128 extendable-output function (XOF).
SHAKE128 belongs to the SHA-3 family, as specified in `FIPS 202`_.
As a XOF, SHAKE128 is a generalization of a cryptographic hash function.
Instead of having a fixed-length output (e.g. 32 bytes like SHA-2/256),
the output length for a XOF is unlimited.
The *128* in its name indicates its maximum security level (in bits),
as described in Section A.2 of `FIPS 202`_.
For instance:
>>> from Crypto.Hash import SHAKE128
>>> from binascii import hexlify
>>>
>>> shake = SHAKE128.new()
>>> shake.update(b'Some data')
>>> print hexlify(shake.read(26))
.. _FIPS 202: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
"""
from Crypto.Util.py3compat import bord
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
from Crypto.Hash.keccak import _raw_keccak_lib
class SHAKE128_XOF(object):
"""Class that implements a SHAKE128 XOF
"""
#: ASN.1 Object ID
oid = "2.16.840.1.101.3.4.2.11"
def __init__(self, data=None):
state = VoidPointer()
result = _raw_keccak_lib.keccak_init(state.address_of(),
c_size_t(32),
0x1F)
if result:
raise ValueError("Error %d while instantiating SHAKE128"
% result)
self._state = SmartPointer(state.get(),
_raw_keccak_lib.keccak_destroy)
self._is_squeezing = False
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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)
You cannot use ``update`` anymore after the first call to ``read``.
:Parameters:
data : byte string
The next chunk of the message being hashed.
"""
if self._is_squeezing:
raise TypeError("You cannot call 'update' after the first 'read'")
expect_byte_string(data)
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while updating SHAKE128 state"
% result)
return self
def read(self, length):
"""Return the next ``length`` bytes of **binary** (non-printable)
digest for the message.
You cannot use ``update`` anymore after the first call to ``read``.
:Return: A byte string of `length` bytes.
"""
self._is_squeezing = True
bfr = create_string_buffer(length)
result = _raw_keccak_lib.keccak_squeeze(self._state.get(),
bfr,
c_size_t(length))
if result:
raise ValueError("Error %d while extracting from SHAKE128"
% result)
return get_raw_buffer(bfr)
def new(self, data=None):
return type(self)(data=data)
def new(data=None):
"""Return a fresh instance of a SHAKE128 object.
:Parameters:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to ``update()``.
Optional.
:Return: A `SHAKE128_XOF` object
"""
return SHAKE128_XOF(data=data)

View file

@ -0,0 +1,151 @@
# ===================================================================
#
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
"""SHAKE256 extendable-output function.
SHAKE256 belongs to the SHA-3 family, as specified in `FIPS 202`_.
As a XOF, SHAKE256 is a generalization of a cryptographic hash function.
Instead of having a fixed-length output (e.g. 32 bytes like SHA-2/256),
the output length for a XOF is unlimited.
The *256* in its name indicates its maximum security level (in bits),
as described in Section A.2 of `FIPS 202`_.
For instance:
>>> from Crypto.Hash import SHAKE256
>>> from binascii import hexlify
>>>
>>> shake = SHAKE256.new()
>>> shake.update(b'Some data')
>>> print hexlify(shake.read(26))
.. _FIPS 202: http://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.202.pdf
"""
from Crypto.Util.py3compat import bord
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
from Crypto.Hash.keccak import _raw_keccak_lib
class SHAKE256_XOF(object):
"""Class that implements a SHAKE256 XOF
"""
#: ASN.1 Object ID
oid = "2.16.840.1.101.3.4.2.12"
def __init__(self, data=None):
state = VoidPointer()
result = _raw_keccak_lib.keccak_init(state.address_of(),
c_size_t(64),
0x1F)
if result:
raise ValueError("Error %d while instantiating SHAKE256"
% result)
self._state = SmartPointer(state.get(),
_raw_keccak_lib.keccak_destroy)
self._is_squeezing = False
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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)
You cannot use ``update`` anymore after the first call to ``read``.
:Parameters:
data : byte string
The next chunk of the message being hashed.
"""
if self._is_squeezing:
raise TypeError("You cannot call 'update' after the first 'read'")
expect_byte_string(data)
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while updating SHAKE256 state"
% result)
return self
def read(self, length):
"""Return the next ``length`` bytes of **binary** (non-printable)
digest for the message.
You cannot use ``update`` anymore after the first call to ``read``.
:Return: A byte string of `length` bytes.
"""
self._is_squeezing = True
bfr = create_string_buffer(length)
result = _raw_keccak_lib.keccak_squeeze(self._state.get(),
bfr,
c_size_t(length))
if result:
raise ValueError("Error %d while extracting from SHAKE256"
% result)
return get_raw_buffer(bfr)
def new(self, data=None):
return type(self)(data=data)
def new(data=None):
"""Return a fresh instance of a SHAKE256 object.
:Parameters:
data : byte string
The very first chunk of the message to hash.
It is equivalent to an early call to ``update()``.
Optional.
:Return: A `SHAKE256_XOF` object
"""
return SHAKE256_XOF(data=data)

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,48 @@
# -*- coding: utf-8 -*-
#
# ===================================================================
# The contents of 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.
# ===================================================================
"""Hashing algorithms
Hash functions take arbitrary binary strings as input, and produce a random-like output
of fixed size that is dependent on the input; it should be practically infeasible
to derive the original input data given only the hash function's
output. In other words, the hash function is *one-way*.
It should also not be practically feasible to find a second piece of data
(a *second pre-image*) whose hash is the same as the original message
(*weak collision resistance*).
Finally, it should not be feasible to find two arbitrary messages with the
same hash (*strong collision resistance*).
The output of the hash function is called the *digest* of the input message.
In general, the security of a hash function is related to the length of the
digest. If the digest is *n* bits long, its security level is roughly comparable
to the the one offered by an *n/2* bit encryption algorithm.
Hash functions can be used simply as a integrity check, or, in
association with a public-key algorithm, can be used to implement
digital signatures.
:undocumented: _MD2, _MD4, _RIPEMD160, _SHA224, _SHA256, _SHA384, _SHA512, _RIPEMD
"""
__all__ = ['HMAC', 'MD2', 'MD4', 'MD5', 'RIPEMD160', 'SHA1',
'SHA224', 'SHA256', 'SHA384', 'SHA512', 'CMAC']

View file

@ -0,0 +1,203 @@
# ===================================================================
#
# Copyright (c) 2015, Legrandin <helderijs@gmail.com>
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
# ===================================================================
"""Keccak family of cryptographic hash algorithms.
`Keccak`_ is the winning algorithm of the SHA-3 competition organized by NIST.
What eventually became SHA-3 is a variant incompatible to Keccak,
even though the security principles and margins remain the same.
If you are interested in writing SHA-3 compliant code, you must use
the modules ``SHA3_224``, ``SHA3_256``, ``SHA3_384`` or ``SHA3_512``.
This module implements the Keccak hash functions for the 64 bit word
length (b=1600) and the fixed digest sizes of 224, 256, 384 and 512 bits.
>>> from Crypto.Hash import keccak
>>>
>>> keccak_hash = keccak.new(digest_bits=512)
>>> keccak_hash.update(b'Some data')
>>> print keccak_hash.hexdigest()
.. _Keccak: http://www.keccak.noekeon.org/Keccak-specifications.pdf
"""
from Crypto.Util.py3compat import bord
from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
VoidPointer, SmartPointer,
create_string_buffer,
get_raw_buffer, c_size_t,
expect_byte_string)
_raw_keccak_lib = load_pycryptodome_raw_lib("Crypto.Hash._keccak",
"""
int keccak_init(void **state,
size_t capacity_bytes,
uint8_t padding_byte);
int keccak_destroy(void *state);
int keccak_absorb(void *state,
const uint8_t *in,
size_t len);
int keccak_squeeze(const void *state,
uint8_t *out,
size_t len);
int keccak_digest(void *state, uint8_t *digest, size_t len);
""")
class Keccak_Hash(object):
"""Class that implements a Keccak hash
"""
def __init__(self, data, digest_bytes, update_after_digest):
#: The size of the resulting hash in bytes.
self.digest_size = digest_bytes
self._update_after_digest = update_after_digest
self._digest_done = False
state = VoidPointer()
result = _raw_keccak_lib.keccak_init(state.address_of(),
c_size_t(self.digest_size * 2),
0x01)
if result:
raise ValueError("Error %d while instantiating keccak" % result)
self._state = SmartPointer(state.get(),
_raw_keccak_lib.keccak_destroy)
if data:
self.update(data)
def update(self, data):
"""Continue hashing 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:
data : byte string
The next chunk of the message being hashed.
"""
if self._digest_done and not self._update_after_digest:
raise TypeError("You can only call 'digest' or 'hexdigest' on this object")
expect_byte_string(data)
result = _raw_keccak_lib.keccak_absorb(self._state.get(),
data,
c_size_t(len(data)))
if result:
raise ValueError("Error %d while updating keccak" % result)
return self
def digest(self):
"""Return the **binary** (non-printable) digest of the message that has been hashed so far.
You cannot update the hash anymore after the first call to ``digest``
(or ``hexdigest``).
:Return: A byte string of `digest_size` bytes.
It may contain non-ASCII characters, including null bytes.
"""
self._digest_done = True
bfr = create_string_buffer(self.digest_size)
result = _raw_keccak_lib.keccak_digest(self._state.get(),
bfr,
c_size_t(self.digest_size))
if result:
raise ValueError("Error %d while squeezing keccak" % result)
return get_raw_buffer(bfr)
def hexdigest(self):
"""Return the **printable** digest of the message that has been hashed so far.
This method does not change the state of the hash object.
:Return: A string of 2* `digest_size` characters. It contains only
hexadecimal ASCII digits.
"""
return "".join(["%02x" % bord(x) for x in self.digest()])
def new(self, **kwargs):
if "digest_bytes" not in kwargs and "digest_bits" not in kwargs:
kwargs["digest_bytes"] = self.digest_size
return new(**kwargs)
def new(**kwargs):
"""Return a fresh instance of the hash object.
:Keywords:
data : byte string
Optional. The very first chunk of the message to hash.
It is equivalent to an early call to ``update()``.
digest_bytes : integer
The size of the digest, in bytes (28, 32, 48, 64).
digest_bits : integer
The size of the digest, in bits (224, 256, 384, 512).
update_after_digest : boolean
Optional. By default, a hash object cannot be updated anymore after
the digest is computed. When this flag is ``True``, such check
is no longer enforced.
:Return: A `Keccak_Hash` object
"""
data = kwargs.pop("data", None)
update_after_digest = kwargs.pop("update_after_digest", False)
digest_bytes = kwargs.pop("digest_bytes", None)
digest_bits = kwargs.pop("digest_bits", None)
if None not in (digest_bytes, digest_bits):
raise TypeError("Only one digest parameter must be provided")
if (None, None) == (digest_bytes, digest_bits):
raise TypeError("Digest size (bits, bytes) not provided")
if digest_bytes is not None:
if digest_bytes not in (28, 32, 48, 64):
raise ValueError("'digest_bytes' must be: 28, 32, 48 or 64")
else:
if digest_bits not in (224, 256, 384, 512):
raise ValueError("'digest_bytes' must be: 224, 256, 384 or 512")
digest_bytes = digest_bits // 8
if kwargs:
raise TypeError("Unknown parameters: " + str(kwargs))
return Keccak_Hash(data, digest_bytes, update_after_digest)