Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Initial implementation of sha3 module.
- Loading branch information
1 parent
235b670
commit 771c8e5
Showing
7 changed files
with
334 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
*~ | ||
*.pyc | ||
build/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
Keccak is written by the Keccak author. See the | ||
KeccakReferenceAndOptimized directory for more information. | ||
|
||
The python binding is written by Björn Edström <be@bjrn.se>. See | ||
sha3.c header for license details. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
= python-sha3 | ||
|
||
A fast `hashlib` style Python implementation of SHA-3 (Keccak) | ||
implemented in C, on top of the Keccak reference implementation. | ||
|
||
Sample usage: | ||
|
||
import sha3 | ||
s = sha3.SHA3512() # also 224, 256, 384, 512 | ||
s.update('foo') | ||
print s.hexdigest() | ||
|
||
== Building | ||
|
||
python setup.py build | ||
|
||
== Caveats | ||
|
||
While Keccak is tweakable, can hash on a bit level etc, this module is | ||
not. It works on byte arrays only. It also works with the select block | ||
sizes only. | ||
|
||
There are probably bugs. Possibly endianness-issues. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
from distutils.core import setup, Extension | ||
|
||
_sha3 = Extension('_sha3', | ||
sources = ['sha3.c', | ||
'KeccakReferenceAndOptimized/Sources/KeccakNISTInterface.c', | ||
'KeccakReferenceAndOptimized/Sources/KeccakSponge.c', | ||
'KeccakReferenceAndOptimized/Sources/KeccakF-1600-reference.c', | ||
'KeccakReferenceAndOptimized/Sources/displayIntermediateValues.c']) | ||
|
||
setup(name='_sha3', | ||
version='0.1', | ||
description='SHA-3', | ||
ext_modules=[_sha3], | ||
packages=['sha3']) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
/* SHA3 module */ | ||
|
||
/* This module provides an interface to NIST's SHA-3 algorithms */ | ||
|
||
/* This module is based on sha256module.c, which has the following header: | ||
Additional work performed by: | ||
Andrew Kuchling (amk@amk.ca) | ||
Greg Stein (gstein@lyra.org) | ||
Trevor Perrin (trevp@trevp.net) | ||
Copyright (C) 2005 Gregory P. Smith (greg@krypto.org) | ||
Licensed to PSF under a Contributor Agreement. | ||
*/ | ||
|
||
/* | ||
The SHA3-module is written by Björn Edström <be@bjrn.se> 2012. | ||
It is placed under the same license as the original module: | ||
Licensed to PSF under a Contributor Agreement. | ||
*/ | ||
|
||
#include "Python.h" | ||
#include "structmember.h" | ||
#include "KeccakReferenceAndOptimized/Sources/KeccakNISTInterface.h" | ||
|
||
typedef unsigned char SHA_BYTE; | ||
|
||
#if SIZEOF_INT == 4 | ||
typedef unsigned int SHA_INT32; /* 32-bit integer */ | ||
#else | ||
/* not defined. compilation will die. */ | ||
#endif | ||
|
||
|
||
typedef struct { | ||
PyObject_HEAD | ||
int hashbitlen; | ||
hashState state; | ||
} SHAobject; | ||
|
||
static void SHAcopy(SHAobject *src, SHAobject *dest) | ||
{ | ||
dest->hashbitlen = src->hashbitlen; | ||
memcpy(&dest->state, &src->state, sizeof(src->state)); | ||
} | ||
|
||
// | ||
|
||
static PyTypeObject SHA3type; | ||
|
||
|
||
static SHAobject * | ||
newSHA3object(void) | ||
{ | ||
return (SHAobject *)PyObject_New(SHAobject, &SHA3type); | ||
} | ||
|
||
static void | ||
SHA_dealloc(PyObject *ptr) | ||
{ | ||
PyObject_Del(ptr); | ||
} | ||
|
||
|
||
PyDoc_STRVAR(SHA3_copy__doc__, "Return a copy of the hash object."); | ||
|
||
static PyObject * | ||
SHA3_copy(SHAobject *self, PyObject *unused) | ||
{ | ||
SHAobject *newobj; | ||
|
||
if (Py_TYPE(self) == &SHA3type) { | ||
if ( (newobj = newSHA3object())==NULL) | ||
return NULL; | ||
} | ||
SHAcopy(self, newobj); | ||
return (PyObject *)newobj; | ||
} | ||
|
||
PyDoc_STRVAR(SHA3_digest__doc__, | ||
"Return the digest value as a string of binary data."); | ||
|
||
static PyObject * | ||
SHA3_digest(SHAobject *self, PyObject *unused) | ||
{ | ||
unsigned char digest[512]; | ||
SHAobject temp; | ||
|
||
SHAcopy(self, &temp); | ||
|
||
Final(&temp.state, digest); | ||
|
||
return PyString_FromStringAndSize((const char *)digest, self->hashbitlen / 8); | ||
} | ||
|
||
PyDoc_STRVAR(SHA3_update__doc__, | ||
"Update this hash object's state with the provided string."); | ||
|
||
static PyObject * | ||
SHA3_update(SHAobject *self, PyObject *args) | ||
{ | ||
unsigned char *cp; | ||
int len; | ||
|
||
if (!PyArg_ParseTuple(args, "s#:update", &cp, &len)) | ||
return NULL; | ||
|
||
Update(&self->state, cp, len * 8); | ||
|
||
Py_INCREF(Py_None); | ||
return Py_None; | ||
} | ||
|
||
|
||
PyDoc_STRVAR(SHA3_init__doc__, | ||
"Init this hash object's state."); | ||
|
||
static PyObject * | ||
SHA3_init(SHAobject *self, PyObject *args) | ||
{ | ||
int hashbitlen; | ||
|
||
if (!PyArg_ParseTuple(args, "i", &hashbitlen)) | ||
return NULL; | ||
|
||
self->hashbitlen = hashbitlen; | ||
Init(&self->state, hashbitlen); | ||
|
||
Py_INCREF(Py_None); | ||
return Py_None; | ||
} | ||
|
||
|
||
|
||
static PyMethodDef SHA_methods[] = { | ||
{"copy", (PyCFunction)SHA3_copy, METH_NOARGS, SHA3_copy__doc__}, | ||
{"digest", (PyCFunction)SHA3_digest, METH_NOARGS, SHA3_digest__doc__}, | ||
{"update", (PyCFunction)SHA3_update, METH_VARARGS, SHA3_update__doc__}, | ||
{"init" , (PyCFunction)SHA3_init, METH_VARARGS, SHA3_init__doc__}, | ||
{NULL, NULL} /* sentinel */ | ||
}; | ||
|
||
|
||
static PyGetSetDef SHA_getseters[] = { | ||
{NULL} /* Sentinel */ | ||
}; | ||
|
||
static PyMemberDef SHA_members[] = { | ||
{NULL} /* Sentinel */ | ||
}; | ||
|
||
|
||
static PyTypeObject SHA3type = { | ||
PyVarObject_HEAD_INIT(NULL, 0) | ||
"_sha3.sha3", /*tp_name*/ | ||
sizeof(SHAobject), /*tp_size*/ | ||
0, /*tp_itemsize*/ | ||
/* methods */ | ||
SHA_dealloc, /*tp_dealloc*/ | ||
0, /*tp_print*/ | ||
0, /*tp_getattr*/ | ||
0, /*tp_setattr*/ | ||
0, /*tp_compare*/ | ||
0, /*tp_repr*/ | ||
0, /*tp_as_number*/ | ||
0, /*tp_as_sequence*/ | ||
0, /*tp_as_mapping*/ | ||
0, /*tp_hash*/ | ||
0, /*tp_call*/ | ||
0, /*tp_str*/ | ||
0, /*tp_getattro*/ | ||
0, /*tp_setattro*/ | ||
0, /*tp_as_buffer*/ | ||
Py_TPFLAGS_DEFAULT, /*tp_flags*/ | ||
0, /*tp_doc*/ | ||
0, /*tp_traverse*/ | ||
0, /*tp_clear*/ | ||
0, /*tp_richcompare*/ | ||
0, /*tp_weaklistoffset*/ | ||
0, /*tp_iter*/ | ||
0, /*tp_iternext*/ | ||
SHA_methods, /* tp_methods */ | ||
SHA_members, /* tp_members */ | ||
SHA_getseters, /* tp_getset */ | ||
}; | ||
|
||
|
||
PyDoc_STRVAR(SHA3_new__doc__, | ||
"Return a new SHA-3 hash object."); | ||
|
||
|
||
static PyObject * | ||
SHA3_new(PyObject *self, PyObject *args, PyObject *kwdict) | ||
{ | ||
SHAobject *new; | ||
|
||
if ((new = newSHA3object()) == NULL) | ||
return NULL; | ||
|
||
if (PyErr_Occurred()) { | ||
Py_DECREF(new); | ||
return NULL; | ||
} | ||
|
||
return (PyObject *)new; | ||
} | ||
|
||
|
||
static struct PyMethodDef SHA_functions[] = { | ||
{"sha3", (PyCFunction)SHA3_new, METH_VARARGS|METH_KEYWORDS, SHA3_new__doc__}, | ||
{NULL, NULL} /* Sentinel */ | ||
}; | ||
|
||
|
||
|
||
#define insint(n,v) { PyModule_AddIntConstant(m,n,v); } | ||
|
||
|
||
PyMODINIT_FUNC | ||
init_sha3(void) | ||
{ | ||
PyObject *m; | ||
|
||
Py_TYPE(&SHA3type) = &PyType_Type; | ||
if (PyType_Ready(&SHA3type) < 0) { | ||
return; | ||
} | ||
m = Py_InitModule("_sha3", SHA_functions); | ||
if (m == NULL) { | ||
return; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
import _sha3 | ||
|
||
class _SHA3Base(object): | ||
block_size = None | ||
|
||
def __init__(self, s=None): | ||
self._s = _sha3.sha3() | ||
self._s.init(self.digest_size * 8) | ||
if s is not None: | ||
self._s.update(s) | ||
|
||
def update(self, s): | ||
return self._s.update(s) | ||
|
||
def digest(self): | ||
return self._s.digest() | ||
|
||
def hexdigest(self): | ||
return self.digest().encode('hex') | ||
|
||
@property | ||
def digestsize(self): | ||
return self.digest_size | ||
|
||
|
||
class SHA3224(_SHA3Base): | ||
digest_size = 28 | ||
name = 'sha3-224' | ||
|
||
|
||
class SHA3256(_SHA3Base): | ||
digest_size = 32 | ||
name = 'sha3-256' | ||
|
||
|
||
class SHA3384(_SHA3Base): | ||
digest_size = 48 | ||
name = 'sha3-384' | ||
|
||
|
||
class SHA3512(_SHA3Base): | ||
digest_size = 64 | ||
name = 'sha3-512' |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import sha3 | ||
|
||
def c(inst, s): | ||
h = inst() | ||
h.update(s) | ||
return h.hexdigest().upper() | ||
|
||
# Test vectors from KeccakKAT/ShortMsgKAT_512.txt | ||
assert c(sha3.SHA3512, '') == "0EAB42DE4C3CEB9235FC91ACFFE746B29C29A8C366B7C60E4E67C466F36A4304C00FA9CAF9D87976BA469BCBE06713B435F091EF2769FB160CDAB33D3670680E" | ||
assert c(sha3.SHA3512, '\xCC') == "8630C13CBD066EA74BBE7FE468FEC1DEE10EDC1254FB4C1B7C5FD69B646E44160B8CE01D05A0908CA790DFB080F4B513BC3B6225ECE7A810371441A5AC666EB9" | ||
assert c(sha3.SHA3512, '\x41\xFB') == "551DA6236F8B96FCE9F97F1190E901324F0B45E06DBBB5CDB8355D6ED1DC34B3F0EAE7DCB68622FF232FA3CECE0D4616CDEB3931F93803662A28DF1CD535B731" |