diff --git a/sys/lib/python/hashlib.py b/sys/lib/python/hashlib.py index 71f63c72a..06cc67c21 100644 --- a/sys/lib/python/hashlib.py +++ b/sys/lib/python/hashlib.py @@ -51,88 +51,24 @@ More condensed: """ +import _sechash -def __get_builtin_constructor(name): - if name in ('SHA1', 'sha1'): - import _sha - return _sha.new - elif name in ('MD5', 'md5'): - import _md5 - return _md5.new - elif name in ('SHA256', 'sha256', 'SHA224', 'sha224'): - import _sha256 - bs = name[3:] - if bs == '256': - return _sha256.sha256 - elif bs == '224': - return _sha256.sha224 -# elif name in ('SHA512', 'sha512', 'SHA384', 'sha384'): -# import _sha512 -# bs = name[3:] -# if bs == '512': -# return _sha512.sha512 -# elif bs == '384': -# return _sha512.sha384 +md5 = _sechash.md5 +sha1 = _sechash.sha1 +sha224 = _sechash.sha224 +sha256 = _sechash.sha256 +sha384 = _sechash.sha384 +sha512 = _sechash.sha512 - raise ValueError, "unsupported hash type" +algs = dict() +for a in [md5, sha1, sha224, sha256, sha384, sha512]: + algs[a().name.lower()] = a - -def __py_new(name, string=''): - """new(name, string='') - Return a new hashing object using the named algorithm; - optionally initialized with a string. - """ - return __get_builtin_constructor(name)(string) - - -def __hash_new(name, string=''): - """new(name, string='') - Return a new hashing object using the named algorithm; - optionally initialized with a string. - """ - try: - return _hashlib.new(name, string) - except ValueError: - # If the _hashlib module (OpenSSL) doesn't support the named - # hash, try using our builtin implementations. - # This allows for SHA224/256 and SHA384/512 support even though - # the OpenSSL library prior to 0.9.8 doesn't provide them. - return __get_builtin_constructor(name)(string) - - -try: - import _hashlib - # use the wrapper of the C implementation - new = __hash_new - - for opensslFuncName in filter(lambda n: n.startswith('openssl_'), dir(_hashlib)): - funcName = opensslFuncName[len('openssl_'):] - try: - # try them all, some may not work due to the OpenSSL - # version not supporting that algorithm. - f = getattr(_hashlib, opensslFuncName) - f() - # Use the C function directly (very fast) - exec funcName + ' = f' - except ValueError: - try: - # Use the builtin implementation directly (fast) - exec funcName + ' = __get_builtin_constructor(funcName)' - except ValueError: - # this one has no builtin implementation, don't define it - pass - # clean up our locals - del f - del opensslFuncName - del funcName - -except ImportError: - # We don't have the _hashlib OpenSSL module? - # use the built in legacy interfaces via a wrapper function - new = __py_new - - # lookup the C function to use directly for the named constructors - md5 = __get_builtin_constructor('md5') - sha1 = __get_builtin_constructor('sha1') - sha224 = __get_builtin_constructor('sha224') - sha256 = __get_builtin_constructor('sha256') - sha384 = __get_builtin_constructor('sha384') - sha512 = __get_builtin_constructor('sha512') +def new(name, string=''): + """new(name, string='') - Return a new hashing object using the named algorithm; + optionally initialized with a string. + """ + a = algs[name.lower()] + if a != None: + return a(string) + raise ValueError, "unsupported hash type" diff --git a/sys/src/cmd/python/Include/pyport.h b/sys/src/cmd/python/Include/pyport.h index 6fe3f0b52..ba3db76b8 100644 --- a/sys/src/cmd/python/Include/pyport.h +++ b/sys/src/cmd/python/Include/pyport.h @@ -765,7 +765,7 @@ typedef struct fd_set { #endif #ifndef Py_ULL -#define Py_ULL(x) Py_LL(x##U) +#define Py_ULL(x) x##ULL #endif #endif /* Py_PYPORT_H */ diff --git a/sys/src/cmd/python/Modules/config b/sys/src/cmd/python/Modules/config index ef3eb55bc..804fa79b7 100644 --- a/sys/src/cmd/python/Modules/config +++ b/sys/src/cmd/python/Modules/config @@ -4,15 +4,17 @@ _csv #_curses_panel _elementtree _functools -_hashlib +#_hashlib _locale _lsprof -_md5 +#_md5 _random -_sha -_sha256 +_sechash +#_sha +#_sha256 +#_sha512 _sre -_ssl +#_ssl _struct _symtable _testcapi diff --git a/sys/src/cmd/python/Modules/mkfile b/sys/src/cmd/python/Modules/mkfile index ff1bd7198..880fda8a6 100644 --- a/sys/src/cmd/python/Modules/mkfile +++ b/sys/src/cmd/python/Modules/mkfile @@ -12,14 +12,14 @@ OFILES=\ # _cursesmodule.$O\ _elementtree.$O\ _functoolsmodule.$O\ - _hashopenssl.$O\ +# _hashopenssl.$O\ _heapqmodule.$O\ # _hotshot.$O\ _localemodule.$O\ _lsprof.$O\ _randommodule.$O\ _sre.$O\ - _ssl.$O\ +# _ssl.$O\ _struct.$O\ _testcapimodule.$O\ # _tkinter.$O\ @@ -60,8 +60,8 @@ OFILES=\ # linuxaudiodev.$O\ main.$O\ mathmodule.$O\ - md5.$O\ - md5module.$O\ +# md5.$O\ +# md5module.$O\ # mmapmodule.$O\ # nismodule.$O\ operator.$O\ @@ -77,9 +77,10 @@ OFILES=\ rotatingtree.$O\ selectmodule.$O\ # sgimodule.$O\ - sha256module.$O\ +# sha256module.$O\ # sha512module.$O\ - shamodule.$O\ +# shamodule.$O\ + sechashmodule.$O\ signalmodule.$O\ socketmodule.$O\ # spwdmodule.$O\ diff --git a/sys/src/cmd/python/Modules/sechashmodule.c b/sys/src/cmd/python/Modules/sechashmodule.c new file mode 100644 index 000000000..283537244 --- /dev/null +++ b/sys/src/cmd/python/Modules/sechashmodule.c @@ -0,0 +1,367 @@ +/* Plan 9 sechash(2) module */ + +#include "Python.h" +#include "structmember.h" + +#define _PLAN9_SOURCE +#include + +typedef struct { + PyObject_HEAD + + char *t; + int n, b; + DigestState *(*f)(uchar *, ulong, uchar *, DigestState *); + DigestState s; +} SHobject; + +static PyTypeObject MD5type; +static PyTypeObject SHA1type; +static PyTypeObject SHA224type; +static PyTypeObject SHA256type; +static PyTypeObject SHA384type; +static PyTypeObject SHA512type; + +static void +sh_copy(SHobject *src, SHobject *dest) +{ + dest->t = src->t; + dest->n = src->n; + dest->b = src->b; + dest->f = src->f; + dest->s = src->s; +} + +static void +sh_update(SHobject *s, uchar *buffer, int count) +{ + (*s->f)(buffer, count, NULL, &s->s); +} + +static void +sh_final(SHobject *s, uchar digest[]) +{ + (*s->f)(NULL, 0, (uchar*)digest, &s->s); +} + +static void +sh_dealloc(PyObject *ptr) +{ + PyObject_Del(ptr); +} + +PyDoc_STRVAR(SH_copy__doc__, "Return a copy of the hash object."); + +static PyObject * +SH_copy(SHobject *self, PyObject *unused) +{ + SHobject *newobj; + + newobj = PyObject_New(SHobject, ((PyObject*)self)->ob_type); + if(newobj != NULL) + sh_copy(self, newobj); + return (PyObject *)newobj; +} + +PyDoc_STRVAR(SH_digest__doc__, +"Return the digest value as a string of binary data."); + +static PyObject * +SH_digest(SHobject *self, PyObject *unused) +{ + uchar digest[64]; + SHobject temp; + + sh_copy(self, &temp); + sh_final(&temp, digest); + return PyString_FromStringAndSize((const char *)digest, self->n); +} + +PyDoc_STRVAR(SH_hexdigest__doc__, +"Return the digest value as a string of hexadecimal digits."); + +static PyObject * +SH_hexdigest(SHobject *self, PyObject *unused) +{ + uchar digest[64]; + SHobject temp; + PyObject *retval; + char *hex_digest; + int i, j; + + /* Get the raw (binary) digest value */ + sh_copy(self, &temp); + sh_final(&temp, digest); + + /* Create a new string */ + retval = PyString_FromStringAndSize(NULL, self->n * 2); + if (!retval) + return NULL; + hex_digest = PyString_AsString(retval); + if (!hex_digest) { + Py_DECREF(retval); + return NULL; + } + + /* Make hex version of the digest */ + for (i=j=0; in; i++) { + char c; + c = (digest[i] >> 4) & 0xf; + c = (c>9) ? c+'a'-10 : c + '0'; + hex_digest[j++] = c; + c = (digest[i] & 0xf); + c = (c>9) ? c+'a'-10 : c + '0'; + hex_digest[j++] = c; + } + return retval; +} + +PyDoc_STRVAR(SH_update__doc__, +"Update this hash object's state with the provided string."); + +static PyObject * +SH_update(SHobject *self, PyObject *args) +{ + uchar *cp; + int len; + + if (!PyArg_ParseTuple(args, "s#:update", &cp, &len)) + return NULL; + sh_update(self, cp, len); + Py_INCREF(Py_None); + return Py_None; +} + +static PyMethodDef SH_methods[] = { + {"copy", (PyCFunction)SH_copy, METH_NOARGS, SH_copy__doc__}, + {"digest", (PyCFunction)SH_digest, METH_NOARGS, SH_digest__doc__}, + {"hexdigest", (PyCFunction)SH_hexdigest, METH_NOARGS, SH_hexdigest__doc__}, + {"update", (PyCFunction)SH_update, METH_VARARGS, SH_update__doc__}, + {NULL, NULL} +}; + +static PyObject * +SH_get_block_size(PyObject *self, void *closure) +{ + return PyInt_FromLong(((SHobject*)self)->b); +} + +static PyObject * +SH_get_name(PyObject *self, void *closure) +{ + char *s = ((SHobject*)self)->t; + return PyString_FromStringAndSize(s, strlen(s)); +} + +static PyGetSetDef SH_getseters[] = { + {"block_size", (getter)SH_get_block_size, NULL, NULL, NULL}, + {"name", (getter)SH_get_name, NULL, NULL, NULL}, + {NULL} +}; + +static PyMemberDef SH_members[] = { + {"digest_size", T_INT, offsetof(SHobject, n), READONLY, NULL}, + {"digestsize", T_INT, offsetof(SHobject, n), READONLY, NULL}, + {NULL} +}; + +static PyTypeObject MD5type = {PyObject_HEAD_INIT(NULL)0,"_sechash.md5",sizeof(SHobject),0,sh_dealloc, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; +static PyTypeObject SHA1type = {PyObject_HEAD_INIT(NULL)0,"_sechash.sha1",sizeof(SHobject),0,sh_dealloc, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; +static PyTypeObject SHA224type = {PyObject_HEAD_INIT(NULL)0,"_sechash.sha224",sizeof(SHobject),0,sh_dealloc, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; +static PyTypeObject SHA256type = {PyObject_HEAD_INIT(NULL)0,"_sechash.sha256",sizeof(SHobject),0,sh_dealloc, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; +static PyTypeObject SHA384type = {PyObject_HEAD_INIT(NULL)0,"_sechash.sha384",sizeof(SHobject),0,sh_dealloc, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; +static PyTypeObject SHA512type = {PyObject_HEAD_INIT(NULL)0,"_sechash.sha512",sizeof(SHobject),0,sh_dealloc, + 0,0,0,0,0,0,0,0,0,0,0,0,0,0,Py_TPFLAGS_DEFAULT,0,0,0,0,0,0,0,SH_methods,SH_members,SH_getseters}; + + +PyDoc_STRVAR(SHA512_new__doc__, +"Return a new SHA-512 hash object; optionally initialized with a string."); + +static PyObject * +SHA512_new(PyObject *self, PyObject *args, PyObject *kwdict) +{ + static char *kwlist[] = {"string", NULL}; + SHobject *new; + uchar *cp = NULL; + int len; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) + return NULL; + if ((new = (SHobject *)PyObject_New(SHobject, &SHA512type)) == NULL) + return NULL; + memset(&new->s, 0, sizeof(new->s)); + new->t = "SHA512"; + new->b = 128; + new->n = SHA2_512dlen; + new->f = sha2_512; + if (cp) + sh_update(new, cp, len); + return (PyObject *)new; +} + +PyDoc_STRVAR(SHA384_new__doc__, +"Return a new SHA-384 hash object; optionally initialized with a string."); + +static PyObject * +SHA384_new(PyObject *self, PyObject *args, PyObject *kwdict) +{ + static char *kwlist[] = {"string", NULL}; + SHobject *new; + uchar *cp = NULL; + int len; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) + return NULL; + if ((new = (SHobject *)PyObject_New(SHobject, &SHA384type)) == NULL) + return NULL; + memset(&new->s, 0, sizeof(new->s)); + new->t = "SHA384"; + new->b = 128; + new->n = SHA2_384dlen; + new->f = sha2_384; + if (cp) + sh_update(new, cp, len); + return (PyObject *)new; +} + +PyDoc_STRVAR(SHA256_new__doc__, +"Return a new SHA-256 hash object; optionally initialized with a string."); + +static PyObject * +SHA256_new(PyObject *self, PyObject *args, PyObject *kwdict) +{ + static char *kwlist[] = {"string", NULL}; + SHobject *new; + uchar *cp = NULL; + int len; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) + return NULL; + if ((new = (SHobject *)PyObject_New(SHobject, &SHA256type)) == NULL) + return NULL; + memset(&new->s, 0, sizeof(new->s)); + new->t = "SHA256"; + new->b = 64; + new->n = SHA2_256dlen; + new->f = sha2_256; + if (cp) + sh_update(new, cp, len); + return (PyObject *)new; +} + +PyDoc_STRVAR(SHA224_new__doc__, +"Return a new SHA-224 hash object; optionally initialized with a string."); + +static PyObject * +SHA224_new(PyObject *self, PyObject *args, PyObject *kwdict) +{ + static char *kwlist[] = {"string", NULL}; + SHobject *new; + uchar *cp = NULL; + int len; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) + return NULL; + if ((new = (SHobject *)PyObject_New(SHobject, &SHA224type)) == NULL) + return NULL; + memset(&new->s, 0, sizeof(new->s)); + new->t = "SHA224"; + new->b = 64; + new->n = SHA2_224dlen; + new->f = sha2_224; + if (cp) + sh_update(new, cp, len); + return (PyObject *)new; +} + +PyDoc_STRVAR(SHA1_new__doc__, +"Return a new SHA1 hash object; optionally initialized with a string."); + +static PyObject * +SHA1_new(PyObject *self, PyObject *args, PyObject *kwdict) +{ + static char *kwlist[] = {"string", NULL}; + SHobject *new; + uchar *cp = NULL; + int len; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) + return NULL; + if ((new = (SHobject *)PyObject_New(SHobject, &SHA1type)) == NULL) + return NULL; + memset(&new->s, 0, sizeof(new->s)); + new->t = "SHA1"; + new->b = 64; + new->n = SHA1dlen; + new->f = sha1; + if (cp) + sh_update(new, cp, len); + return (PyObject *)new; +} + +PyDoc_STRVAR(MD5_new__doc__, +"Return a new MD5 hash object; optionally initialized with a string."); + +static PyObject * +MD5_new(PyObject *self, PyObject *args, PyObject *kwdict) +{ + static char *kwlist[] = {"string", NULL}; + SHobject *new; + uchar *cp = NULL; + int len; + + if (!PyArg_ParseTupleAndKeywords(args, kwdict, "|s#:new", kwlist, &cp, &len)) + return NULL; + if ((new = (SHobject *)PyObject_New(SHobject, &MD5type)) == NULL) + return NULL; + memset(&new->s, 0, sizeof(new->s)); + new->t = "MD5"; + new->b = 16; + new->n = MD5dlen; + new->f = md5; + if (cp) + sh_update(new, cp, len); + return (PyObject *)new; +} + + +/* List of functions exported by this module */ + +static struct PyMethodDef SH_functions[] = { + {"sha512", (PyCFunction)SHA512_new, METH_VARARGS|METH_KEYWORDS, SHA512_new__doc__}, + {"sha384", (PyCFunction)SHA384_new, METH_VARARGS|METH_KEYWORDS, SHA384_new__doc__}, + {"sha256", (PyCFunction)SHA256_new, METH_VARARGS|METH_KEYWORDS, SHA256_new__doc__}, + {"sha224", (PyCFunction)SHA224_new, METH_VARARGS|METH_KEYWORDS, SHA224_new__doc__}, + {"sha1", (PyCFunction)SHA1_new, METH_VARARGS|METH_KEYWORDS, SHA1_new__doc__}, + {"md5", (PyCFunction)MD5_new, METH_VARARGS|METH_KEYWORDS, MD5_new__doc__}, + {NULL, NULL} /* Sentinel */ +}; + +PyMODINIT_FUNC +init_sechash(void) +{ + MD5type.ob_type = &PyType_Type; + if (PyType_Ready(&MD5type) < 0) + return; + SHA1type.ob_type = &PyType_Type; + if (PyType_Ready(&SHA1type) < 0) + return; + SHA224type.ob_type = &PyType_Type; + if (PyType_Ready(&SHA224type) < 0) + return; + SHA256type.ob_type = &PyType_Type; + if (PyType_Ready(&SHA256type) < 0) + return; + SHA384type.ob_type = &PyType_Type; + if (PyType_Ready(&SHA384type) < 0) + return; + SHA512type.ob_type = &PyType_Type; + if (PyType_Ready(&SHA512type) < 0) + return; + Py_InitModule("_sechash", SH_functions); +} diff --git a/sys/src/cmd/python/mkfile b/sys/src/cmd/python/mkfile index 8bd00ac7b..3f973d634 100644 --- a/sys/src/cmd/python/mkfile +++ b/sys/src/cmd/python/mkfile @@ -14,8 +14,6 @@ OFILES=\ LIB= \ /$objtype/lib/ape/libpython.a\ - /$objtype/lib/ape/libssl.a\ - /$objtype/lib/ape/libcrypto.a LIBDIRS=Modules Objects Parser Python