Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bpo-33729: Fix issues with arguments parsing in hashlib. #8346

Merged
merged 5 commits into from
Jul 31, 2018
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
bpo-33729: Fix issues with arguments parsing in hashlib.
  • Loading branch information
serhiy-storchaka committed Jul 20, 2018
commit 9a735456b28cc1813e79c56cb96e7dcb4fbd83ee
27 changes: 14 additions & 13 deletions Doc/library/hashlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ More condensed:

.. function:: new(name[, data])

Is a generic constructor that takes the string name of the desired
Is a generic constructor that takes the string *name* of the desired
algorithm as its first parameter. It also exists to allow access to the
above listed hashes as well as any other algorithms that your OpenSSL
library may offer. The named constructors are much faster than :func:`new`
Expand Down Expand Up @@ -162,10 +162,10 @@ A hash object has the following attributes:
A hash object has the following methods:


.. method:: hash.update(arg)
.. method:: hash.update(data)

Update the hash object with the object *arg*, which must be interpretable as
a buffer of bytes. Repeated calls are equivalent to a single call with the
Update the hash object with the :term:`bytes-like object`.
Repeated calls are equivalent to a single call with the
concatenation of all the arguments: ``m.update(a); m.update(b)`` is
equivalent to ``m.update(a+b)``.

Expand Down Expand Up @@ -206,7 +206,7 @@ by the SHAKE algorithm.
.. method:: shake.digest(length)

Return the digest of the data passed to the :meth:`update` method so far.
This is a bytes object of size ``length`` which may contain bytes in
This is a bytes object of size *length* which may contain bytes in
the whole range from 0 to 255.


Expand Down Expand Up @@ -262,9 +262,10 @@ include a `salt <https://en.wikipedia.org/wiki/Salt_%28cryptography%29>`_.
The function provides scrypt password-based key derivation function as
defined in :rfc:`7914`.

*password* and *salt* must be bytes-like objects. Applications and
libraries should limit *password* to a sensible length (e.g. 1024). *salt*
should be about 16 or more bytes from a proper source, e.g. :func:`os.urandom`.
*password* and *salt* must be :term:`bytes-like objects
<bytes-like object>`. Applications and libraries should limit *password*
to a sensible length (e.g. 1024). *salt* should be about 16 or more
bytes from a proper source, e.g. :func:`os.urandom`.

*n* is the CPU/Memory cost factor, *r* the block size, *p* parallelization
factor and *maxmem* limits memory (OpenSSL 1.1.0 defaults to 32 MiB).
Expand Down Expand Up @@ -305,20 +306,20 @@ Creating hash objects
New hash objects are created by calling constructor functions:


.. function:: blake2b(data=b'', digest_size=64, key=b'', salt=b'', \
.. function:: blake2b(data=b'', *, digest_size=64, key=b'', salt=b'', \
person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, \
node_depth=0, inner_size=0, last_node=False)

.. function:: blake2s(data=b'', digest_size=32, key=b'', salt=b'', \
.. function:: blake2s(data=b'', *, digest_size=32, key=b'', salt=b'', \
person=b'', fanout=1, depth=1, leaf_size=0, node_offset=0, \
node_depth=0, inner_size=0, last_node=False)


These functions return the corresponding hash objects for calculating
BLAKE2b or BLAKE2s. They optionally take these general parameters:

* *data*: initial chunk of data to hash, which must be interpretable as buffer
of bytes.
* *data*: initial chunk of data to hash, which must be
:term:`bytes-like object`. It can be passed only as positional argument.

* *digest_size*: size of output digest in bytes.

Expand Down Expand Up @@ -427,7 +428,7 @@ object, and, finally, get the digest out of the object by calling


As a shortcut, you can pass the first chunk of data to update directly to the
constructor as the first argument (or as *data* keyword argument):
constructor as the positional argument:

>>> from hashlib import blake2b
>>> blake2b(b'Hello world').hexdigest()
Expand Down
29 changes: 15 additions & 14 deletions Lib/hashlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,18 @@
sha384 and sha512 will be slow on 32 bit platforms.

Hash objects have these methods:
- update(arg): Update the hash object with the bytes in arg. Repeated calls
are equivalent to a single call with the concatenation of all
the arguments.
- digest(): Return the digest of the bytes passed to the update() method
so far.
- hexdigest(): Like digest() except the digest is returned as a unicode
object of double length, containing only hexadecimal digits.
- copy(): Return a copy (clone) of the hash object. This can be used to
efficiently compute the digests of strings that share a common
initial substring.

For example, to obtain the digest of the string 'Nobody inspects the
- update(data): Update the hash object with the bytes in data. Repeated calls
are equivalent to a single call with the concatenation of all
the arguments.
- digest(): Return the digest of the bytes passed to the update() method
so far as a bytes object.
- hexdigest(): Like digest() except the digest is returned as a string
of double length, containing only hexadecimal digits.
- copy(): Return a copy (clone) of the hash object. This can be used to
efficiently compute the digests of datas that share a common
initial substring.

For example, to obtain the digest of the byte string 'Nobody inspects the
spammish repetition':

>>> import hashlib
Expand Down Expand Up @@ -130,14 +130,15 @@ def __get_openssl_constructor(name):

def __py_new(name, data=b'', **kwargs):
"""new(name, data=b'', **kwargs) - Return a new hashing object using the
named algorithm; optionally initialized with data (which must be bytes).
named algorithm; optionally initialized with data (which must be
a bytes-like object).
"""
return __get_builtin_constructor(name)(data, **kwargs)


def __hash_new(name, data=b'', **kwargs):
"""new(name, data=b'') - Return a new hashing object using the named algorithm;
optionally initialized with data (which must be bytes).
optionally initialized with data (which must be a bytes-like object).
"""
if name in {'blake2b', 'blake2s'}:
# Prefer our blake2 implementation.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed issues with arguments parsing in :mod:`hashlib`.
65 changes: 33 additions & 32 deletions Modules/_blake2/blake2b_impl.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,10 @@ typedef struct {
#include "clinic/blake2b_impl.c.h"

/*[clinic input]
module _blake2b
class _blake2b.blake2b "BLAKE2bObject *" "&PyBlake2_BLAKE2bType"
module _blake2
class _blake2.blake2b "BLAKE2bObject *" "&PyBlake2_BLAKE2bType"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=6893358c6622aecf]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d47b0527b39c673f]*/


static BLAKE2bObject *
Expand All @@ -66,17 +66,18 @@ new_BLAKE2bObject(PyTypeObject *type)

/*[clinic input]
@classmethod
_blake2b.blake2b.__new__ as py_blake2b_new
string as data: object = NULL
_blake2.blake2b.__new__ as py_blake2b_new
data: object(c_default="NULL") = b''
/
*
digest_size: int(c_default="BLAKE2B_OUTBYTES") = _blake2b.blake2b.MAX_DIGEST_SIZE
key: Py_buffer = None
salt: Py_buffer = None
person: Py_buffer = None
digest_size: int(c_default="BLAKE2B_OUTBYTES") = _blake2.blake2b.MAX_DIGEST_SIZE
key: Py_buffer(c_default="NULL", py_default="b''") = None
salt: Py_buffer(c_default="NULL", py_default="b''") = None
person: Py_buffer(c_default="NULL", py_default="b''") = None
fanout: int = 1
depth: int = 1
leaf_size as leaf_size_obj: object = NULL
node_offset as node_offset_obj: object = NULL
leaf_size as leaf_size_obj: object(c_default="NULL") = 0
node_offset as node_offset_obj: object(c_default="NULL") = 0
node_depth: int = 0
inner_size: int = 0
last_node: bool = False
Expand All @@ -90,7 +91,7 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
int fanout, int depth, PyObject *leaf_size_obj,
PyObject *node_offset_obj, int node_depth,
int inner_size, int last_node)
/*[clinic end generated code: output=7506d8d890e5f13b input=e41548dfa0866031]*/
/*[clinic end generated code: output=7506d8d890e5f13b input=aca35b33c5612b4b]*/
{
BLAKE2bObject *self = NULL;
Py_buffer buf;
Expand Down Expand Up @@ -252,14 +253,14 @@ py_blake2b_new_impl(PyTypeObject *type, PyObject *data, int digest_size,
}

/*[clinic input]
_blake2b.blake2b.copy
_blake2.blake2b.copy

Return a copy of the hash object.
[clinic start generated code]*/

static PyObject *
_blake2b_blake2b_copy_impl(BLAKE2bObject *self)
/*[clinic end generated code: output=c89cd33550ab1543 input=4c9c319f18f10747]*/
_blake2_blake2b_copy_impl(BLAKE2bObject *self)
/*[clinic end generated code: output=ff6acee5f93656ae input=e383c2d199fd8a2e]*/
{
BLAKE2bObject *cpy;

Expand All @@ -274,21 +275,21 @@ _blake2b_blake2b_copy_impl(BLAKE2bObject *self)
}

/*[clinic input]
_blake2b.blake2b.update
_blake2.blake2b.update

obj: object
data: object
/

Update this hash object's state with the provided string.
Update this hash object's state with the provided bytes-like object.
[clinic start generated code]*/

static PyObject *
_blake2b_blake2b_update(BLAKE2bObject *self, PyObject *obj)
/*[clinic end generated code: output=a888f07c4cddbe94 input=3ecb8c13ee4260f2]*/
_blake2_blake2b_update(BLAKE2bObject *self, PyObject *data)
/*[clinic end generated code: output=010dfcbe22654359 input=ffc4aa6a6a225d31]*/
{
Py_buffer buf;

GET_BUFFER_VIEW_OR_ERROUT(obj, &buf);
GET_BUFFER_VIEW_OR_ERROUT(data, &buf);

if (self->lock == NULL && buf.len >= HASHLIB_GIL_MINSIZE)
self->lock = PyThread_allocate_lock();
Expand All @@ -308,14 +309,14 @@ _blake2b_blake2b_update(BLAKE2bObject *self, PyObject *obj)
}

/*[clinic input]
_blake2b.blake2b.digest
_blake2.blake2b.digest

Return the digest value as a string of binary data.
Return the digest value as a bytes object.
[clinic start generated code]*/

static PyObject *
_blake2b_blake2b_digest_impl(BLAKE2bObject *self)
/*[clinic end generated code: output=b13a79360d984740 input=ac2fa462ebb1b9c7]*/
_blake2_blake2b_digest_impl(BLAKE2bObject *self)
/*[clinic end generated code: output=a5864660f4bfc61a input=7d21659e9c5fff02]*/
{
uint8_t digest[BLAKE2B_OUTBYTES];
blake2b_state state_cpy;
Expand All @@ -329,14 +330,14 @@ _blake2b_blake2b_digest_impl(BLAKE2bObject *self)
}

/*[clinic input]
_blake2b.blake2b.hexdigest
_blake2.blake2b.hexdigest

Return the digest value as a string of hexadecimal digits.
[clinic start generated code]*/

static PyObject *
_blake2b_blake2b_hexdigest_impl(BLAKE2bObject *self)
/*[clinic end generated code: output=6a503611715b24bd input=d58f0b2f37812e33]*/
_blake2_blake2b_hexdigest_impl(BLAKE2bObject *self)
/*[clinic end generated code: output=b5598a87d8794a60 input=76930f6946351f56]*/
{
uint8_t digest[BLAKE2B_OUTBYTES];
blake2b_state state_cpy;
Expand All @@ -350,10 +351,10 @@ _blake2b_blake2b_hexdigest_impl(BLAKE2bObject *self)


static PyMethodDef py_blake2b_methods[] = {
_BLAKE2B_BLAKE2B_COPY_METHODDEF
_BLAKE2B_BLAKE2B_DIGEST_METHODDEF
_BLAKE2B_BLAKE2B_HEXDIGEST_METHODDEF
_BLAKE2B_BLAKE2B_UPDATE_METHODDEF
_BLAKE2_BLAKE2B_COPY_METHODDEF
_BLAKE2_BLAKE2B_DIGEST_METHODDEF
_BLAKE2_BLAKE2B_HEXDIGEST_METHODDEF
_BLAKE2_BLAKE2B_UPDATE_METHODDEF
{NULL, NULL}
};

Expand Down
Loading