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
13152static PyObject *
14153whirlpool_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+
37299PyMODINIT_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