Skip to content

Commit 44bd3f3

Browse files
committed
Created hashlib compatible interface for whirlpool
1 parent ce71d18 commit 44bd3f3

File tree

1 file changed

+279
-6
lines changed

1 file changed

+279
-6
lines changed

main.c

Lines changed: 279 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,145 @@
1010
#define PY_SSIZE_T_CLEAN 1
1111
#include <Python.h>
1212
#include "Whirlpool.c"
13+
14+
typedef struct {
15+
PyObject_HEAD
16+
NESSIEstruct whirlpool; /* the context holder */
17+
} whirlpoolobject;
18+
19+
static PyTypeObject Whirlpooltype;
20+
21+
#define is_whirlpoolobject(v) ((v)->ob_type == &Whirlpooltype)
22+
23+
static whirlpoolobject *
24+
newwhirlpoolobject(void)
25+
{
26+
whirlpoolobject *wpp;
27+
28+
wpp = PyObject_New(whirlpoolobject, &Whirlpooltype);
29+
if (wpp == NULL)
30+
return NULL;
31+
32+
NESSIEinit(&wpp->whirlpool); /* actual initialisation */
33+
return wpp;
34+
}
35+
36+
/* Whirlpool methods */
37+
38+
static void
39+
whirlpool_dealloc(whirlpoolobject *wpp)
40+
{
41+
PyObject_Del(wpp);
42+
}
43+
44+
/* Whirlpool methods-as-attributes */
45+
46+
static PyObject *
47+
whirlpool_update(whirlpoolobject *self, PyObject *args)
48+
{
49+
Py_buffer view;
50+
51+
if (!PyArg_ParseTuple(args, "s*:update", &view))
52+
return NULL;
53+
54+
NESSIEadd((unsigned char*)view.buf,
55+
Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int) * 8,
56+
&self->whirlpool);
57+
58+
PyBuffer_Release(&view);
59+
Py_RETURN_NONE;
60+
}
61+
62+
PyDoc_STRVAR(update_doc,
63+
"update (arg)\n\
64+
\n\
65+
Update the whirlpool object with the string arg. Repeated calls are\n\
66+
equivalent to a single call with the concatenation of all the\n\
67+
arguments.");
68+
69+
70+
static PyObject *
71+
whirlpool_digest(whirlpoolobject *self)
72+
{
73+
NESSIEstruct wpContext;
74+
unsigned char digest[DIGESTBYTES];
75+
76+
/* make a temporary copy, and perform the final */
77+
wpContext = self->whirlpool;
78+
NESSIEfinalize(&wpContext, digest);
79+
80+
return PyString_FromStringAndSize((const char *)digest, sizeof(digest));
81+
}
82+
83+
PyDoc_STRVAR(digest_doc,
84+
"digest() -> string\n\
85+
\n\
86+
Return the digest of the strings passed to the update() method so\n\
87+
far. This is a binary string which may contain non-ASCII characters,\n\
88+
including null bytes.");
89+
90+
91+
static PyObject *
92+
whirlpool_hexdigest(whirlpoolobject *self)
93+
{
94+
NESSIEstruct wpContext;
95+
PyObject *retval;
96+
unsigned char digest[DIGESTBYTES];
97+
char *hexdigest;
98+
int i, j;
99+
100+
/* Get the raw (binary) digest value */
101+
wpContext = self->whirlpool;
102+
NESSIEfinalize(&wpContext, digest);
103+
104+
/* Create a new string */
105+
retval = PyString_FromStringAndSize(NULL, sizeof(digest) * 2);
106+
if (!retval)
107+
return NULL;
108+
hexdigest = PyString_AsString(retval);
109+
if (!hexdigest) {
110+
Py_DECREF(retval);
111+
return NULL;
112+
}
113+
114+
/* Make hex version of the digest */
115+
for(i=j=0; i<sizeof(digest); i++) {
116+
char c;
117+
c = (digest[i] >> 4) & 0xf;
118+
c = (c>9) ? c+'a'-10 : c+'0';
119+
hexdigest[j++] = c;
120+
c = (digest[i] & 0xf);
121+
c = (c>9) ? c+'a'-10 : c+'0';
122+
hexdigest[j++] = c;
123+
}
124+
return retval;
125+
}
126+
127+
PyDoc_STRVAR(hexdigest_doc,
128+
"hexdigest() -> string\n\
129+
\n\
130+
Like digest(), but returns the digest as a string of hexadecimal digits.");
131+
132+
133+
static PyObject *
134+
whirlpool_copy(whirlpoolobject *self)
135+
{
136+
whirlpoolobject *wpp;
137+
138+
if ((wpp = newwhirlpoolobject()) == NULL)
139+
return NULL;
140+
141+
wpp->whirlpool = self->whirlpool;
142+
return (PyObject *)wpp;
143+
}
144+
145+
PyDoc_STRVAR(copy_doc,
146+
"copy() -> whirlpool object\n\
147+
\n\
148+
Return a copy (``clone'') of the whirlpool object.");
149+
150+
151+
// TODO Mark deprecated
13152
static PyObject *
14153
whirlpool_hash(PyObject *self, PyObject *args) {
15154
struct NESSIEstruct w;
@@ -28,13 +167,147 @@ whirlpool_hash(PyObject *self, PyObject *args) {
28167
return Py_BuildValue("s#", digest, DIGESTBYTES);
29168
}
30169

31-
PyMethodDef methods[] = {
32-
{"hash", whirlpool_hash, METH_VARARGS,
33-
"Hash with whirlpool algorithm."},
34-
{NULL, NULL, 0, NULL}
170+
PyDoc_STRVAR(hash_doc,
171+
"Hash with whirlpool algorithm.");
172+
173+
174+
PyMethodDef whirlpool_methods[] = {
175+
{"update", (PyCFunction)whirlpool_update, METH_VARARGS, update_doc},
176+
{"digest", (PyCFunction)whirlpool_digest, METH_NOARGS, digest_doc},
177+
{"hexdigest", (PyCFunction)whirlpool_hexdigest, METH_NOARGS, hexdigest_doc},
178+
{"copy", (PyCFunction)whirlpool_copy, METH_NOARGS, copy_doc},
179+
{"hash", (PyCFunction)whirlpool_hash, METH_VARARGS, hash_doc},
180+
{NULL, NULL} /* sentinel */
181+
};
182+
183+
184+
static PyObject *
185+
whirlpool_get_name(PyObject *self, void *closure)
186+
{
187+
return PyString_FromStringAndSize("WHIRLPOOL", 9);
188+
}
189+
190+
191+
static PyGetSetDef whirlpool_getseters[] = {
192+
{"name",
193+
(getter)whirlpool_get_name, NULL,
194+
NULL,
195+
NULL},
196+
{NULL} /* sentinel */
197+
};
198+
199+
200+
PyDoc_STRVAR(module_doc,
201+
"This module implements the whirlpool digest algorithm.\n\
202+
\n\
203+
Functions:\n\
204+
new([arg]) -- return a new whirlpool object, initialized with arg if provided\n\
205+
\n\
206+
Special Objects:\n\
207+
\n\
208+
WhirlpoolType -- type object for whirlpool objects");
209+
210+
PyDoc_STRVAR(whirlpooltype_doc,
211+
"A whirlpool represents the object used to calculate the WHIRLPOOL checksum of\n\
212+
a string of information.\n\
213+
\n\
214+
Methods:\n\
215+
\n\
216+
update() -- updates the current digest with an additional string\n\
217+
digest() -- return the current digest value\n\
218+
hexdigest() -- return the current digest as a string of hexadecimal digits\n\
219+
copy() -- return a copy of the current whirlpool object");
220+
221+
static PyTypeObject Whirlpooltype = {
222+
PyVarObject_HEAD_INIT(NULL, 0)
223+
"whirlpool.whirlpool", /*tp_name*/
224+
sizeof(whirlpoolobject), /*tp_size*/
225+
0, /*tp_itemsize*/
226+
/* methods */
227+
(destructor)whirlpool_dealloc, /*tp_dealloc*/
228+
0, /*tp_print*/
229+
0, /*tp_getattr*/
230+
0, /*tp_setattr*/
231+
0, /*tp_compare*/
232+
0, /*tp_repr*/
233+
0, /*tp_as_number*/
234+
0, /*tp_as_sequence*/
235+
0, /*tp_as_mapping*/
236+
0, /*tp_hash*/
237+
0, /*tp_call*/
238+
0, /*tp_str*/
239+
0, /*tp_getattro*/
240+
0, /*tp_setattro*/
241+
0, /*tp_as_buffer*/
242+
Py_TPFLAGS_DEFAULT, /*tp_flags*/
243+
whirlpooltype_doc, /*tp_doc*/
244+
0, /*tp_traverse*/
245+
0, /*tp_clear*/
246+
0, /*tp_richcompare*/
247+
0, /*tp_weaklistoffset*/
248+
0, /*tp_iter*/
249+
0, /*tp_iternext*/
250+
whirlpool_methods, /*tp_methods */
251+
0, /*tp_members */
252+
whirlpool_getseters, /*tp_getset */
35253
};
36254

255+
256+
/* Whirlpool functions */
257+
258+
static PyObject *
259+
whirlpool_new(PyObject *self, PyObject *args)
260+
{
261+
whirlpoolobject *wpp;
262+
Py_buffer view = { 0 };
263+
264+
if (!PyArg_ParseTuple(args, "|s*:new", &view))
265+
return NULL;
266+
267+
if ((wpp = newwhirlpoolobject()) == NULL) {
268+
PyBuffer_Release(&view);
269+
return NULL;
270+
}
271+
272+
if (view.len > 0) {
273+
NESSIEadd((unsigned char*)view.buf,
274+
Py_SAFE_DOWNCAST(view.len, Py_ssize_t, unsigned int) * 8,
275+
&wpp->whirlpool);
276+
}
277+
PyBuffer_Release(&view);
278+
279+
return (PyObject *)wpp;
280+
}
281+
282+
PyDoc_STRVAR(new_doc,
283+
"new([arg]) -> whirlpool object\n\
284+
\n\
285+
Return a new whirlpool object. If arg is present, the method call update(arg)\n\
286+
is made.");
287+
288+
289+
/* List of functions exported by this module */
290+
291+
static PyMethodDef whirlpool_functions[] = {
292+
{"new", (PyCFunction)whirlpool_new, METH_VARARGS, new_doc},
293+
{NULL, NULL} /* sentinel */
294+
};
295+
296+
297+
/* Initialize this module */
298+
37299
PyMODINIT_FUNC
38-
initwhirlpool() {
39-
(void) Py_InitModule("whirlpool", methods);
300+
initwhirlpool(void)
301+
{
302+
PyObject *m, *d;
303+
304+
Py_TYPE(&Whirlpooltype) = &PyType_Type;
305+
if (PyType_Ready(&Whirlpooltype) < 0)
306+
return;
307+
m = Py_InitModule3("whirlpool", whirlpool_functions, module_doc);
308+
if (m == NULL)
309+
return;
310+
d = PyModule_GetDict(m);
311+
PyDict_SetItemString(d, "WhirlpoolType", (PyObject *)&Whirlpooltype);
40312
}
313+

0 commit comments

Comments
 (0)