Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4a0270d

Browse files
committed
Issue #16113: integrade SHA-3 (Keccak) patch from http://hg.python.org/sandbox/cheimes
1 parent 8c6db45 commit 4a0270d

30 files changed

Lines changed: 7971 additions & 28 deletions

Doc/library/hashlib.rst

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,13 @@ concatenation of the data fed to it so far using the :meth:`digest` or
5151
.. index:: single: OpenSSL; (use in module hashlib)
5252

5353
Constructors for hash algorithms that are always present in this module are
54-
:func:`md5`, :func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`, and
55-
:func:`sha512`. Additional algorithms may also be available depending upon the
56-
OpenSSL library that Python uses on your platform.
54+
:func:`md5`, :func:`sha1`, :func:`sha224`, :func:`sha256`, :func:`sha384`,
55+
:func:`sha512`, :func:`sha3_224`, :func:`sha3_256`, :func:`sha3_384`, and
56+
:func:`sha3_512`. Additional algorithms may also be available depending upon
57+
the OpenSSL library that Python uses on your platform.
58+
59+
.. versionchanged:: 3.4
60+
Add sha3 family of hash algorithms.
5761

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

Doc/license.rst

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,25 @@ The :mod:`select` and contains the following notice for the kqueue interface::
658658
SUCH DAMAGE.
659659

660660

661+
SHA-3
662+
-----
663+
664+
The module :mod:`_sha3` and :mod:`hashlib` are using the reference
665+
implementation of Keccak. The files at :file:`Modules/_sha3/keccak/` contain
666+
the following note::
667+
668+
The Keccak sponge function, designed by Guido Bertoni, Joan Daemen,
669+
Michaël Peeters and Gilles Van Assche. For more information, feedback or
670+
questions, please refer to our website: http://keccak.noekeon.org/
671+
672+
Implementation by the designers,
673+
hereby denoted as "the implementer".
674+
675+
To the extent possible under law, the implementer has waived all copyright
676+
and related or neighboring rights to the source code in this file.
677+
http://creativecommons.org/publicdomain/zero/1.0/
678+
679+
661680
strtod and dtoa
662681
---------------
663682

Doc/whatsnew/3.4.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ Implementation improvements:
101101

102102
Significantly Improved Library Modules:
103103

104-
* None yet.
104+
* SHA-3 (Keccak) support for :mod:`hashlib`.
105105

106106
Security improvements:
107107

Lib/hashlib.py

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,8 @@
5454

5555
# This tuple and __get_builtin_constructor() must be modified if a new
5656
# always available algorithm is added.
57-
__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
57+
__always_supported = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512',
58+
'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512')
5859

5960
algorithms_guaranteed = set(__always_supported)
6061
algorithms_available = set(__always_supported)
@@ -85,6 +86,18 @@ def __get_builtin_constructor(name):
8586
return _sha512.sha512
8687
elif bs == '384':
8788
return _sha512.sha384
89+
elif name in {'sha3_224', 'sha3_256', 'sha3_384', 'sha3_512',
90+
'SHA3_224', 'SHA3_256', 'SHA3_384', 'SHA3_512'}:
91+
import _sha3
92+
bs = name[5:]
93+
if bs == '224':
94+
return _sha3.sha3_224
95+
elif bs == '256':
96+
return _sha3.sha3_256
97+
elif bs == '384':
98+
return _sha3.sha3_384
99+
elif bs == '512':
100+
return _sha3.sha3_512
88101
except ImportError:
89102
pass # no extension module, this hash is unsupported.
90103

Lib/test/test_hashlib.py

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,10 @@ def hexstr(s):
3636
class HashLibTestCase(unittest.TestCase):
3737
supported_hash_names = ( 'md5', 'MD5', 'sha1', 'SHA1',
3838
'sha224', 'SHA224', 'sha256', 'SHA256',
39-
'sha384', 'SHA384', 'sha512', 'SHA512' )
39+
'sha384', 'SHA384', 'sha512', 'SHA512',
40+
'sha3_224', 'sha3_256', 'sha3_384',
41+
'sha3_512', 'SHA3_224', 'SHA3_256',
42+
'SHA3_384', 'SHA3_512' )
4043

4144
# Issue #14693: fallback modules are always compiled under POSIX
4245
_warn_on_extension_import = os.name == 'posix' or COMPILED_WITH_PYDEBUG
@@ -93,6 +96,12 @@ def _test_algorithm_via_hashlib_new(data=None, _alg=algorithm):
9396
if _sha512:
9497
self.constructors_to_test['sha384'].add(_sha512.sha384)
9598
self.constructors_to_test['sha512'].add(_sha512.sha512)
99+
_sha3 = self._conditional_import_module('_sha3')
100+
if _sha3:
101+
self.constructors_to_test['sha3_224'].add(_sha3.sha3_224)
102+
self.constructors_to_test['sha3_256'].add(_sha3.sha3_256)
103+
self.constructors_to_test['sha3_384'].add(_sha3.sha3_384)
104+
self.constructors_to_test['sha3_512'].add(_sha3.sha3_512)
96105

97106
super(HashLibTestCase, self).__init__(*args, **kwargs)
98107

@@ -158,6 +167,7 @@ def test_large_update(self):
158167
self.assertEqual(m1.digest(), m2.digest())
159168

160169
def check(self, name, data, digest):
170+
digest = digest.lower()
161171
constructors = self.constructors_to_test[name]
162172
# 2 is for hashlib.name(...) and hashlib.new(name, ...)
163173
self.assertGreaterEqual(len(constructors), 2)
@@ -183,6 +193,10 @@ def test_no_unicode(self):
183193
self.check_no_unicode('sha256')
184194
self.check_no_unicode('sha384')
185195
self.check_no_unicode('sha512')
196+
self.check_no_unicode('sha3_224')
197+
self.check_no_unicode('sha3_256')
198+
self.check_no_unicode('sha3_384')
199+
self.check_no_unicode('sha3_512')
186200

187201
def test_case_md5_0(self):
188202
self.check('md5', b'', 'd41d8cd98f00b204e9800998ecf8427e')
@@ -318,11 +332,122 @@ def test_case_sha512_3(self):
318332
"e718483d0ce769644e2e42c7bc15b4638e1f98b13b2044285632a803afa973eb"+
319333
"de0ff244877ea60a4cb0432ce577c31beb009c5c2c49aa2e4eadb217ad8cc09b")
320334

335+
# SHA-3 family
336+
def test_case_sha3_224_0(self):
337+
self.check('sha3_224', b"",
338+
"F71837502BA8E10837BDD8D365ADB85591895602FC552B48B7390ABD")
339+
340+
def test_case_sha3_224_1(self):
341+
self.check('sha3_224', bytes.fromhex("CC"),
342+
"A9CAB59EB40A10B246290F2D6086E32E3689FAF1D26B470C899F2802")
343+
344+
def test_case_sha3_224_2(self):
345+
self.check('sha3_224', bytes.fromhex("41FB"),
346+
"615BA367AFDC35AAC397BC7EB5D58D106A734B24986D5D978FEFD62C")
347+
348+
def test_case_sha3_224_3(self):
349+
self.check('sha3_224', bytes.fromhex(
350+
"433C5303131624C0021D868A30825475E8D0BD3052A022180398F4CA4423B9"+
351+
"8214B6BEAAC21C8807A2C33F8C93BD42B092CC1B06CEDF3224D5ED1EC29784"+
352+
"444F22E08A55AA58542B524B02CD3D5D5F6907AFE71C5D7462224A3F9D9E53"+
353+
"E7E0846DCBB4CE"),
354+
"62B10F1B6236EBC2DA72957742A8D4E48E213B5F8934604BFD4D2C3A")
355+
356+
@bigmemtest(size=_4G + 5, memuse=1)
357+
def test_case_sha3_224_huge(self, size):
358+
if size == _4G + 5:
359+
try:
360+
self.check('sha3_224', b'A'*size,
361+
'58ef60057c9dddb6a87477e9ace5a26f0d9db01881cf9b10a9f8c224')
362+
except OverflowError:
363+
pass # 32-bit arch
364+
365+
366+
def test_case_sha3_256_0(self):
367+
self.check('sha3_256', b"",
368+
"C5D2460186F7233C927E7DB2DCC703C0E500B653CA82273B7BFAD8045D85A470")
369+
370+
def test_case_sha3_256_1(self):
371+
self.check('sha3_256', bytes.fromhex("CC"),
372+
"EEAD6DBFC7340A56CAEDC044696A168870549A6A7F6F56961E84A54BD9970B8A")
373+
374+
def test_case_sha3_256_2(self):
375+
self.check('sha3_256', bytes.fromhex("41FB"),
376+
"A8EACEDA4D47B3281A795AD9E1EA2122B407BAF9AABCB9E18B5717B7873537D2")
377+
378+
def test_case_sha3_256_3(self):
379+
self.check('sha3_256', bytes.fromhex(
380+
"433C5303131624C0021D868A30825475E8D0BD3052A022180398F4CA4423B9"+
381+
"8214B6BEAAC21C8807A2C33F8C93BD42B092CC1B06CEDF3224D5ED1EC29784"+
382+
"444F22E08A55AA58542B524B02CD3D5D5F6907AFE71C5D7462224A3F9D9E53"+
383+
"E7E0846DCBB4CE"),
384+
"CE87A5173BFFD92399221658F801D45C294D9006EE9F3F9D419C8D427748DC41")
385+
386+
387+
def test_case_sha3_384_0(self):
388+
self.check('sha3_384', b"",
389+
"2C23146A63A29ACF99E73B88F8C24EAA7DC60AA771780CCC006AFBFA8FE2479B"+
390+
"2DD2B21362337441AC12B515911957FF")
391+
392+
def test_case_sha3_384_1(self):
393+
self.check('sha3_384', bytes.fromhex("CC"),
394+
"1B84E62A46E5A201861754AF5DC95C4A1A69CAF4A796AE405680161E29572641"+
395+
"F5FA1E8641D7958336EE7B11C58F73E9")
396+
397+
def test_case_sha3_384_2(self):
398+
self.check('sha3_384', bytes.fromhex("41FB"),
399+
"495CCE2714CD72C8C53C3363D22C58B55960FE26BE0BF3BBC7A3316DD563AD1D"+
400+
"B8410E75EEFEA655E39D4670EC0B1792")
401+
402+
def test_case_sha3_384_3(self):
403+
self.check('sha3_384', bytes.fromhex(
404+
"433C5303131624C0021D868A30825475E8D0BD3052A022180398F4CA4423B9"+
405+
"8214B6BEAAC21C8807A2C33F8C93BD42B092CC1B06CEDF3224D5ED1EC29784"+
406+
"444F22E08A55AA58542B524B02CD3D5D5F6907AFE71C5D7462224A3F9D9E53"+
407+
"E7E0846DCBB4CE"),
408+
"135114508DD63E279E709C26F7817C0482766CDE49132E3EDF2EEDD8996F4E35"+
409+
"96D184100B384868249F1D8B8FDAA2C9")
410+
411+
412+
def test_case_sha3_512_0(self):
413+
self.check('sha3_512', b"",
414+
"0EAB42DE4C3CEB9235FC91ACFFE746B29C29A8C366B7C60E4E67C466F36A4304"+
415+
"C00FA9CAF9D87976BA469BCBE06713B435F091EF2769FB160CDAB33D3670680E")
416+
417+
def test_case_sha3_512_1(self):
418+
self.check('sha3_512', bytes.fromhex("CC"),
419+
"8630C13CBD066EA74BBE7FE468FEC1DEE10EDC1254FB4C1B7C5FD69B646E4416"+
420+
"0B8CE01D05A0908CA790DFB080F4B513BC3B6225ECE7A810371441A5AC666EB9")
421+
422+
def test_case_sha3_512_2(self):
423+
self.check('sha3_512', bytes.fromhex("41FB"),
424+
"551DA6236F8B96FCE9F97F1190E901324F0B45E06DBBB5CDB8355D6ED1DC34B3"+
425+
"F0EAE7DCB68622FF232FA3CECE0D4616CDEB3931F93803662A28DF1CD535B731")
426+
427+
def test_case_sha3_512_3(self):
428+
self.check('sha3_512', bytes.fromhex(
429+
"433C5303131624C0021D868A30825475E8D0BD3052A022180398F4CA4423B9"+
430+
"8214B6BEAAC21C8807A2C33F8C93BD42B092CC1B06CEDF3224D5ED1EC29784"+
431+
"444F22E08A55AA58542B524B02CD3D5D5F6907AFE71C5D7462224A3F9D9E53"+
432+
"E7E0846DCBB4CE"),
433+
"527D28E341E6B14F4684ADB4B824C496C6482E51149565D3D17226828884306B"+
434+
"51D6148A72622C2B75F5D3510B799D8BDC03EAEDE453676A6EC8FE03A1AD0EAB")
435+
436+
321437
def test_gil(self):
322438
# Check things work fine with an input larger than the size required
323439
# for multithreaded operation (which is hardwired to 2048).
324440
gil_minsize = 2048
325441

442+
for name in self.supported_hash_names:
443+
m = hashlib.new(name)
444+
m.update(b'1')
445+
m.update(b'#' * gil_minsize)
446+
m.update(b'1')
447+
448+
m = hashlib.new(name, b'x' * gil_minsize)
449+
m.update(b'1')
450+
326451
m = hashlib.md5()
327452
m.update(b'1')
328453
m.update(b'#' * gil_minsize)

Modules/_hashopenssl.c

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -17,24 +17,6 @@
1717
#include "structmember.h"
1818
#include "hashlib.h"
1919

20-
#ifdef WITH_THREAD
21-
#include "pythread.h"
22-
#define ENTER_HASHLIB(obj) \
23-
if ((obj)->lock) { \
24-
if (!PyThread_acquire_lock((obj)->lock, 0)) { \
25-
Py_BEGIN_ALLOW_THREADS \
26-
PyThread_acquire_lock((obj)->lock, 1); \
27-
Py_END_ALLOW_THREADS \
28-
} \
29-
}
30-
#define LEAVE_HASHLIB(obj) \
31-
if ((obj)->lock) { \
32-
PyThread_release_lock((obj)->lock); \
33-
}
34-
#else
35-
#define ENTER_HASHLIB(obj)
36-
#define LEAVE_HASHLIB(obj)
37-
#endif
3820

3921
/* EVP is the preferred interface to hashing in OpenSSL */
4022
#include <openssl/evp.h>
@@ -43,10 +25,6 @@
4325

4426
#define MUNCH_SIZE INT_MAX
4527

46-
/* TODO(gps): We should probably make this a module or EVPobject attribute
47-
* to allow the user to optimize based on the platform they're using. */
48-
#define HASHLIB_GIL_MINSIZE 2048
49-
5028
#ifndef HASH_OBJ_CONSTRUCTOR
5129
#define HASH_OBJ_CONSTRUCTOR 0
5230
#endif

Modules/_sha3/cleanup.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
#!/usr/bin/env python
2+
# Copyright (C) 2012 Christian Heimes ([email protected])
3+
# Licensed to PSF under a Contributor Agreement.
4+
#
5+
# cleanup Keccak sources
6+
7+
import os
8+
import re
9+
10+
CPP1 = re.compile("^//(.*)")
11+
CPP2 = re.compile("\ //(.*)")
12+
13+
STATICS = ("void ", "int ", "HashReturn ", "const UINT64 ", "UINT16 ")
14+
15+
HERE = os.path.dirname(os.path.abspath(__file__))
16+
KECCAK = os.path.join(HERE, "keccak")
17+
18+
def getfiles():
19+
for name in os.listdir(KECCAK):
20+
name = os.path.join(KECCAK, name)
21+
if os.path.isfile(name):
22+
yield name
23+
24+
def cleanup(f):
25+
buf = []
26+
for line in f:
27+
# mark all functions and global data as static
28+
if line.startswith(STATICS):
29+
buf.append("static " + line)
30+
continue
31+
# remove UINT64 typedef, we have our own
32+
if line.startswith("typedef unsigned long long int"):
33+
buf.append("/* %s */\n" % line.strip())
34+
continue
35+
# remove #include "brg_endian.h"
36+
if "brg_endian.h" in line:
37+
buf.append("/* %s */\n" % line.strip())
38+
continue
39+
# transform C++ comments into ANSI C comments
40+
line = CPP1.sub(r"/* \1 */", line)
41+
line = CPP2.sub(r" /* \1 */", line)
42+
buf.append(line)
43+
return "".join(buf)
44+
45+
for name in getfiles():
46+
with open(name) as f:
47+
res = cleanup(f)
48+
with open(name, "w") as f:
49+
f.write(res)

0 commit comments

Comments
 (0)