77 * on irc.freenode.net
88 */
99
10- #define PY_SSIZE_T_CLEAN 1
1110#include <Python.h>
1211#include "Whirlpool.c"
12+
13+ typedef struct {
14+ PyObject_HEAD
15+ NESSIEstruct whirlpool ; /* the context holder */
16+ } whirlpoolobject ;
17+
18+ static PyTypeObject Whirlpooltype ;
19+
20+ #define is_whirlpoolobject (v ) ((v)->ob_type == &Whirlpooltype)
21+
22+ static whirlpoolobject *
23+ newwhirlpoolobject (void )
24+ {
25+ whirlpoolobject * wpp ;
26+
27+ wpp = PyObject_New (whirlpoolobject , & Whirlpooltype );
28+ if (wpp == NULL )
29+ return NULL ;
30+
31+ NESSIEinit (& wpp -> whirlpool ); /* actual initialisation */
32+ return wpp ;
33+ }
34+
35+ /* Whirlpool methods */
36+
37+ static void
38+ whirlpool_dealloc (whirlpoolobject * wpp )
39+ {
40+ PyObject_Del (wpp );
41+ }
42+
43+ /* Whirlpool methods-as-attributes */
44+
45+ static PyObject *
46+ whirlpool_update (whirlpoolobject * self , PyObject * args )
47+ {
48+ Py_buffer view ;
49+
50+ if (!PyArg_ParseTuple (args , "s*:update" , & view ))
51+ return NULL ;
52+
53+ NESSIEadd ((unsigned char * )view .buf ,
54+ Py_SAFE_DOWNCAST (view .len , Py_ssize_t , unsigned int ) * 8 ,
55+ & self -> whirlpool );
56+
57+ PyBuffer_Release (& view );
58+ Py_RETURN_NONE ;
59+ }
60+
61+ PyDoc_STRVAR (update_doc ,
62+ "update (arg)\n\
63+ \n\
64+ Update the whirlpool object with the string arg. Repeated calls are\n\
65+ equivalent to a single call with the concatenation of all the\n\
66+ arguments." );
67+
68+
69+ static PyObject *
70+ whirlpool_digest (whirlpoolobject * self )
71+ {
72+ NESSIEstruct wpContext ;
73+ unsigned char digest [DIGESTBYTES ];
74+
75+ /* Make a temporary copy, and perform the final */
76+ wpContext = self -> whirlpool ;
77+ NESSIEfinalize (& wpContext , digest );
78+
79+ return PyString_FromStringAndSize ((const char * )digest , sizeof (digest ));
80+ }
81+
82+ PyDoc_STRVAR (digest_doc ,
83+ "digest() -> string\n\
84+ \n\
85+ Return the digest of the strings passed to the update() method so\n\
86+ far. This is a binary string which may contain non-ASCII characters,\n\
87+ including null bytes." );
88+
89+
90+ static PyObject *
91+ whirlpool_hexdigest (whirlpoolobject * self )
92+ {
93+ NESSIEstruct wpContext ;
94+ PyObject * retval ;
95+ unsigned char digest [DIGESTBYTES ];
96+ char * hexdigest ;
97+ int i , j ;
98+
99+ /* Get the raw (binary) digest value */
100+ wpContext = self -> whirlpool ;
101+ NESSIEfinalize (& wpContext , digest );
102+
103+ /* Create a new string */
104+ retval = PyString_FromStringAndSize (NULL , sizeof (digest ) * 2 );
105+ if (!retval )
106+ return NULL ;
107+ hexdigest = PyString_AsString (retval );
108+ if (!hexdigest ) {
109+ Py_DECREF (retval );
110+ return NULL ;
111+ }
112+
113+ /* Make hex version of the digest */
114+ for (i = j = 0 ; i < sizeof (digest ); i ++ ) {
115+ char c ;
116+ c = (digest [i ] >> 4 ) & 0xf ;
117+ c = (c > 9 ) ? c + 'a' - 10 : c + '0' ;
118+ hexdigest [j ++ ] = c ;
119+ c = (digest [i ] & 0xf );
120+ c = (c > 9 ) ? c + 'a' - 10 : c + '0' ;
121+ hexdigest [j ++ ] = c ;
122+ }
123+ return retval ;
124+ }
125+
126+ PyDoc_STRVAR (hexdigest_doc ,
127+ "hexdigest() -> string\n\
128+ \n\
129+ Like digest(), but returns the digest as a string of hexadecimal digits." );
130+
131+
132+ static PyObject *
133+ whirlpool_copy (whirlpoolobject * self )
134+ {
135+ whirlpoolobject * wpp ;
136+
137+ if ((wpp = newwhirlpoolobject ()) == NULL )
138+ return NULL ;
139+
140+ wpp -> whirlpool = self -> whirlpool ;
141+ return (PyObject * )wpp ;
142+ }
143+
144+ PyDoc_STRVAR (copy_doc ,
145+ "copy() -> whirlpool object\n\
146+ \n\
147+ Return a copy (``clone'') of the whirlpool object." );
148+
149+
150+ PyMethodDef whirlpool_methods [] = {
151+ {"update" , (PyCFunction )whirlpool_update , METH_VARARGS , update_doc },
152+ {"digest" , (PyCFunction )whirlpool_digest , METH_NOARGS , digest_doc },
153+ {"hexdigest" , (PyCFunction )whirlpool_hexdigest , METH_NOARGS , hexdigest_doc },
154+ {"copy" , (PyCFunction )whirlpool_copy , METH_NOARGS , copy_doc },
155+ {NULL , NULL } /* sentinel */
156+ };
157+
158+
159+ static PyObject *
160+ whirlpool_get_block_size (PyObject * self , void * closure )
161+ {
162+ return PyInt_FromLong (WBLOCKBYTES );
163+ }
164+
165+ static PyObject *
166+ whirlpool_get_digest_size (PyObject * self , void * closure )
167+ {
168+ return PyInt_FromLong (DIGESTBYTES );
169+ }
170+
171+ static PyObject *
172+ whirlpool_get_name (PyObject * self , void * closure )
173+ {
174+ return PyString_FromStringAndSize ("WHIRLPOOL" , 9 );
175+ }
176+
177+ static PyGetSetDef whirlpool_getseters [] = {
178+ {"digest_size" ,
179+ (getter )whirlpool_get_digest_size , NULL ,
180+ NULL ,
181+ NULL },
182+ {"block_size" ,
183+ (getter )whirlpool_get_block_size , NULL ,
184+ NULL ,
185+ NULL },
186+ {"name" ,
187+ (getter )whirlpool_get_name , NULL ,
188+ NULL ,
189+ NULL },
190+ {NULL } /* sentinel */
191+ };
192+
193+
194+ PyDoc_STRVAR (module_doc ,
195+ "This module implements the interface to the whirlpool message digest\n\
196+ algorithm. It operates on messages less than 2^256 bits in length,\n\
197+ and produces a message digest of 512 bits. Its use is quite straighforward:\n\
198+ use new() to create a whirlpool object. You can now feed this object with\n\
199+ arbitrary strings using the update() method. At any point you can ask it for\n\
200+ the digest of the concatenation of the strings fed to it so far.\n\
201+ \n\
202+ Functions:\n\
203+ new([arg]) -- return a new whirlpool object, initialized with arg if provided\n\
204+ hash(arg) -- DEPRECATED, returns a whirlpool digest of arg, for backward \
205+ compatibility\n\
206+ \n\
207+ Special Objects:\n\
208+ \n\
209+ WhirlpoolType -- type object for whirlpool objects" );
210+
211+ PyDoc_STRVAR (whirlpooltype_doc ,
212+ "A whirlpool represents the object used to calculate the WHIRLPOOL checksum of\n\
213+ a string of information.\n\
214+ \n\
215+ Methods:\n\
216+ \n\
217+ update(arg) -- updates the current digest with an additional string\n\
218+ digest() -- return the current digest value\n\
219+ hexdigest() -- return the current digest as a string of hexadecimal digits\n\
220+ copy() -- return a copy of the current whirlpool object" );
221+
222+ static PyTypeObject Whirlpooltype = {
223+ PyVarObject_HEAD_INIT (NULL , 0 )
224+ "whirlpool.whirlpool" , /*tp_name*/
225+ sizeof (whirlpoolobject ), /*tp_size*/
226+ 0 , /*tp_itemsize*/
227+ /* methods */
228+ (destructor )whirlpool_dealloc , /*tp_dealloc*/
229+ 0 , /*tp_print*/
230+ 0 , /*tp_getattr*/
231+ 0 , /*tp_setattr*/
232+ 0 , /*tp_compare*/
233+ 0 , /*tp_repr*/
234+ 0 , /*tp_as_number*/
235+ 0 , /*tp_as_sequence*/
236+ 0 , /*tp_as_mapping*/
237+ 0 , /*tp_hash*/
238+ 0 , /*tp_call*/
239+ 0 , /*tp_str*/
240+ 0 , /*tp_getattro*/
241+ 0 , /*tp_setattro*/
242+ 0 , /*tp_as_buffer*/
243+ Py_TPFLAGS_DEFAULT , /*tp_flags*/
244+ whirlpooltype_doc , /*tp_doc*/
245+ 0 , /*tp_traverse*/
246+ 0 , /*tp_clear*/
247+ 0 , /*tp_richcompare*/
248+ 0 , /*tp_weaklistoffset*/
249+ 0 , /*tp_iter*/
250+ 0 , /*tp_iternext*/
251+ whirlpool_methods , /*tp_methods */
252+ 0 , /*tp_members */
253+ whirlpool_getseters , /*tp_getset */
254+ };
255+
256+
257+ /* Whirlpool functions */
258+
259+ static PyObject *
260+ whirlpool_new (PyObject * self , PyObject * args )
261+ {
262+ whirlpoolobject * wpp ;
263+ Py_buffer view = { 0 };
264+
265+ if (!PyArg_ParseTuple (args , "|s*:new" , & view ))
266+ return NULL ;
267+
268+ if ((wpp = newwhirlpoolobject ()) == NULL ) {
269+ PyBuffer_Release (& view );
270+ return NULL ;
271+ }
272+
273+ if (view .len > 0 ) {
274+ NESSIEadd ((unsigned char * )view .buf ,
275+ Py_SAFE_DOWNCAST (view .len , Py_ssize_t , unsigned int ) * 8 ,
276+ & wpp -> whirlpool );
277+ }
278+ PyBuffer_Release (& view );
279+
280+ return (PyObject * )wpp ;
281+ }
282+
283+ PyDoc_STRVAR (new_doc ,
284+ "new([arg]) -> whirlpool object\n\
285+ \n\
286+ Return a new whirlpool object. If arg is present, the method call update(arg)\n\
287+ is made." );
288+
289+
13290static PyObject *
14291whirlpool_hash (PyObject * self , PyObject * args ) {
15292 struct NESSIEstruct w ;
@@ -28,13 +305,36 @@ whirlpool_hash(PyObject *self, PyObject *args) {
28305 return Py_BuildValue ("s#" , digest , DIGESTBYTES );
29306}
30307
31- PyMethodDef methods [] = {
32- {"hash" , whirlpool_hash , METH_VARARGS ,
33- "Hash with whirlpool algorithm." },
34- {NULL , NULL , 0 , NULL }
308+ PyDoc_STRVAR (hash_doc ,
309+ "Returns a hash of argument using the whirlpool algorithm.\n\
310+ This function is deprecated. Please use new() and hexdigest()." );
311+
312+
313+ /* List of functions exported by this module */
314+
315+ static PyMethodDef whirlpool_functions [] = {
316+ {"new" , (PyCFunction )whirlpool_new , METH_VARARGS , new_doc },
317+ {"hash" , (PyCFunction )whirlpool_hash , METH_VARARGS , hash_doc },
318+ {NULL , NULL } /* sentinel */
35319};
36320
321+
322+ /* Initialize this module */
323+
37324PyMODINIT_FUNC
38- initwhirlpool () {
39- (void ) Py_InitModule ("whirlpool" , methods );
325+ initwhirlpool (void )
326+ {
327+ PyObject * m , * d ;
328+
329+ Py_TYPE (& Whirlpooltype ) = & PyType_Type ;
330+ if (PyType_Ready (& Whirlpooltype ) < 0 )
331+ return ;
332+ m = Py_InitModule3 ("whirlpool" , whirlpool_functions , module_doc );
333+ if (m == NULL )
334+ return ;
335+ PyModule_AddIntConstant (m , "digest_size" , DIGESTBYTES );
336+ PyModule_AddIntConstant (m , "block_size" , WBLOCKBYTES );
337+ d = PyModule_GetDict (m );
338+ PyDict_SetItemString (d , "WhirlpoolType" , (PyObject * )& Whirlpooltype );
40339}
340+
0 commit comments