| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
|
|
| """ |
| 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, |
| c_uint8_ptr) |
|
|
| _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 |
| """ |
|
|
| |
| digest_size = 16 |
| |
| block_size = 64 |
| |
| 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/byte array/memoryview |
| The next chunk of the message being hashed. |
| """ |
|
|
| result = _raw_md4_lib.md4_update(self._state.get(), |
| c_uint8_ptr(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/byte array/memoryview |
| 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) |
|
|
| |
| digest_size = MD4Hash.digest_size |
|
|
| |
| block_size = MD4Hash.block_size |
|
|