blob: 103da1497dac9607d593801a6980d8cdc0645e6a [file] [log] [blame]
Guido van Rossumb6775db1994-08-01 11:34:53 +00001
Guido van Rossum5f59d601992-12-14 16:59:51 +00002/* MD5 module */
3
Guido van Rossumb6775db1994-08-01 11:34:53 +00004/* This module provides an interface to the RSA Data Security,
5 Inc. MD5 Message-Digest Algorithm, described in RFC 1321.
6 It requires the files md5c.c and md5.h (which are slightly changed
7 from the versions in the RFC to avoid the "global.h" file.) */
8
Guido van Rossum5f59d601992-12-14 16:59:51 +00009
10/* MD5 objects */
11
Barry Warsaw8b43b191996-12-09 22:32:36 +000012#include "Python.h"
Gregory P. Smithf21a5f72005-08-21 18:45:59 +000013#include "structmember.h"
Guido van Rossum5f59d601992-12-14 16:59:51 +000014#include "md5.h"
Guido van Rossumb6775db1994-08-01 11:34:53 +000015
Guido van Rossum5f59d601992-12-14 16:59:51 +000016typedef struct {
Antoine Pitrouc83ea132010-05-09 14:46:46 +000017 PyObject_HEAD
18 md5_state_t md5; /* the context holder */
Guido van Rossum5f59d601992-12-14 16:59:51 +000019} md5object;
20
Jeremy Hylton938ace62002-07-17 16:30:39 +000021static PyTypeObject MD5type;
Guido van Rossum5f59d601992-12-14 16:59:51 +000022
Antoine Pitrouc83ea132010-05-09 14:46:46 +000023#define is_md5object(v) ((v)->ob_type == &MD5type)
Guido van Rossum5f59d601992-12-14 16:59:51 +000024
Guido van Rossum5f59d601992-12-14 16:59:51 +000025static md5object *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +000026newmd5object(void)
Guido van Rossum5f59d601992-12-14 16:59:51 +000027{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000028 md5object *md5p;
Guido van Rossum5f59d601992-12-14 16:59:51 +000029
Antoine Pitrouc83ea132010-05-09 14:46:46 +000030 md5p = PyObject_New(md5object, &MD5type);
31 if (md5p == NULL)
32 return NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +000033
Antoine Pitrouc83ea132010-05-09 14:46:46 +000034 md5_init(&md5p->md5); /* actual initialisation */
35 return md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +000036}
Guido van Rossum5f59d601992-12-14 16:59:51 +000037
38
39/* MD5 methods */
40
41static void
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +000042md5_dealloc(md5object *md5p)
Guido van Rossum5f59d601992-12-14 16:59:51 +000043{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000044 PyObject_Del(md5p);
Guido van Rossumb6775db1994-08-01 11:34:53 +000045}
Guido van Rossum5f59d601992-12-14 16:59:51 +000046
47
Guido van Rossumb6775db1994-08-01 11:34:53 +000048/* MD5 methods-as-attributes */
49
Barry Warsaw8b43b191996-12-09 22:32:36 +000050static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +000051md5_update(md5object *self, PyObject *args)
Guido van Rossumb6775db1994-08-01 11:34:53 +000052{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000053 Py_buffer view;
Jesus Cea3fb774e2012-09-10 21:39:07 +020054 Py_ssize_t n;
55 unsigned char *buf;
Guido van Rossumb6775db1994-08-01 11:34:53 +000056
Antoine Pitrouc83ea132010-05-09 14:46:46 +000057 if (!PyArg_ParseTuple(args, "s*:update", &view))
58 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +000059
Jesus Cea3fb774e2012-09-10 21:39:07 +020060 n = view.len;
61 buf = (unsigned char *) view.buf;
62 while (n > 0) {
63 Py_ssize_t nbytes;
64 if (n > INT_MAX)
65 nbytes = INT_MAX;
66 else
67 nbytes = n;
68 md5_append(&self->md5, buf,
69 Py_SAFE_DOWNCAST(nbytes, Py_ssize_t, unsigned int));
70 buf += nbytes;
71 n -= nbytes;
72 }
Gregory P. Smithea388262009-02-13 03:00:00 +000073
Antoine Pitrouc83ea132010-05-09 14:46:46 +000074 PyBuffer_Release(&view);
75 Py_RETURN_NONE;
Guido van Rossumb6775db1994-08-01 11:34:53 +000076}
77
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000078PyDoc_STRVAR(update_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +000079"update (arg)\n\
80\n\
81Update the md5 object with the string arg. Repeated calls are\n\
82equivalent to a single call with the concatenation of all the\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000083arguments.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +000084
85
Barry Warsaw8b43b191996-12-09 22:32:36 +000086static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +000087md5_digest(md5object *self)
Guido van Rossumb6775db1994-08-01 11:34:53 +000088{
Antoine Pitrouc83ea132010-05-09 14:46:46 +000089 md5_state_t mdContext;
90 unsigned char aDigest[16];
Guido van Rossumb6775db1994-08-01 11:34:53 +000091
Antoine Pitrouc83ea132010-05-09 14:46:46 +000092 /* make a temporary copy, and perform the final */
93 mdContext = self->md5;
94 md5_finish(&mdContext, aDigest);
Guido van Rossumb6775db1994-08-01 11:34:53 +000095
Antoine Pitrouc83ea132010-05-09 14:46:46 +000096 return PyString_FromStringAndSize((char *)aDigest, 16);
Guido van Rossumb6775db1994-08-01 11:34:53 +000097}
98
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000099PyDoc_STRVAR(digest_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000100"digest() -> string\n\
101\n\
102Return the digest of the strings passed to the update() method so\n\
Skip Montanarobd2de3a2003-07-08 21:17:25 +0000103far. This is a 16-byte string which may contain non-ASCII characters,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000104including null bytes.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000105
106
Barry Warsaw8b43b191996-12-09 22:32:36 +0000107static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000108md5_hexdigest(md5object *self)
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000109{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000110 md5_state_t mdContext;
111 unsigned char digest[16];
112 unsigned char hexdigest[32];
113 int i, j;
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000114
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000115 /* make a temporary copy, and perform the final */
116 mdContext = self->md5;
117 md5_finish(&mdContext, digest);
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000118
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000119 /* Make hex version of the digest */
120 for(i=j=0; i<16; i++) {
121 char c;
122 c = (digest[i] >> 4) & 0xf;
123 c = (c>9) ? c+'a'-10 : c + '0';
124 hexdigest[j++] = c;
125 c = (digest[i] & 0xf);
126 c = (c>9) ? c+'a'-10 : c + '0';
127 hexdigest[j++] = c;
128 }
129 return PyString_FromStringAndSize((char*)hexdigest, 32);
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000130}
131
132
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000133PyDoc_STRVAR(hexdigest_doc,
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000134"hexdigest() -> string\n\
135\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000136Like digest(), but returns the digest as a string of hexadecimal digits.");
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000137
138
139static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000140md5_copy(md5object *self)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000141{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000142 md5object *md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000143
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000144 if ((md5p = newmd5object()) == NULL)
145 return NULL;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000146
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000147 md5p->md5 = self->md5;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000148
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000149 return (PyObject *)md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000150}
151
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000152PyDoc_STRVAR(copy_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000153"copy() -> md5 object\n\
154\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000155Return a copy (``clone'') of the md5 object.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000156
157
Barry Warsaw8b43b191996-12-09 22:32:36 +0000158static PyMethodDef md5_methods[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000159 {"update", (PyCFunction)md5_update, METH_VARARGS, update_doc},
160 {"digest", (PyCFunction)md5_digest, METH_NOARGS, digest_doc},
161 {"hexdigest", (PyCFunction)md5_hexdigest, METH_NOARGS, hexdigest_doc},
162 {"copy", (PyCFunction)md5_copy, METH_NOARGS, copy_doc},
163 {NULL, NULL} /* sentinel */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000164};
165
Barry Warsaw8b43b191996-12-09 22:32:36 +0000166static PyObject *
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000167md5_get_block_size(PyObject *self, void *closure)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000168{
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000169 return PyInt_FromLong(64);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000170}
171
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000172static PyObject *
173md5_get_digest_size(PyObject *self, void *closure)
174{
175 return PyInt_FromLong(16);
176}
177
178static PyObject *
179md5_get_name(PyObject *self, void *closure)
180{
Gregory P. Smithdd96db62008-06-09 04:58:54 +0000181 return PyString_FromStringAndSize("MD5", 3);
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000182}
183
184static PyGetSetDef md5_getseters[] = {
185 {"digest_size",
186 (getter)md5_get_digest_size, NULL,
187 NULL,
188 NULL},
189 {"block_size",
190 (getter)md5_get_block_size, NULL,
191 NULL,
192 NULL},
193 {"name",
194 (getter)md5_get_name, NULL,
195 NULL,
196 NULL},
197 /* the old md5 and sha modules support 'digest_size' as in PEP 247.
198 * the old sha module also supported 'digestsize'. ugh. */
199 {"digestsize",
200 (getter)md5_get_digest_size, NULL,
201 NULL,
202 NULL},
203 {NULL} /* Sentinel */
204};
205
206
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000207PyDoc_STRVAR(module_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000208"This module implements the interface to RSA's MD5 message digest\n\
209algorithm (see also Internet RFC 1321). Its use is quite\n\
210straightforward: use the new() to create an md5 object. You can now\n\
211feed this object with arbitrary strings using the update() method, and\n\
212at any point you can ask it for the digest (a strong kind of 128-bit\n\
Thomas Wouters7e474022000-07-16 12:04:32 +0000213checksum, a.k.a. ``fingerprint'') of the concatenation of the strings\n\
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000214fed to it so far using the digest() method.\n\
215\n\
216Functions:\n\
217\n\
218new([arg]) -- return a new md5 object, initialized with arg if provided\n\
219md5([arg]) -- DEPRECATED, same as new, but for compatibility\n\
220\n\
221Special Objects:\n\
222\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000223MD5Type -- type object for md5 objects");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000224
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000225PyDoc_STRVAR(md5type_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000226"An md5 represents the object used to calculate the MD5 checksum of a\n\
227string of information.\n\
228\n\
229Methods:\n\
230\n\
231update() -- updates the current digest with an additional string\n\
232digest() -- return the current digest value\n\
Neal Norwitz98a355d2002-10-11 21:53:01 +0000233hexdigest() -- return the current digest as a string of hexadecimal digits\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000234copy() -- return a copy of the current md5 object");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000235
Tim Peters0c322792002-07-17 16:49:03 +0000236static PyTypeObject MD5type = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000237 PyVarObject_HEAD_INIT(NULL, 0)
238 "_md5.md5", /*tp_name*/
239 sizeof(md5object), /*tp_size*/
240 0, /*tp_itemsize*/
241 /* methods */
242 (destructor)md5_dealloc, /*tp_dealloc*/
243 0, /*tp_print*/
244 0, /*tp_getattr*/
245 0, /*tp_setattr*/
246 0, /*tp_compare*/
247 0, /*tp_repr*/
248 0, /*tp_as_number*/
249 0, /*tp_as_sequence*/
250 0, /*tp_as_mapping*/
251 0, /*tp_hash*/
252 0, /*tp_call*/
253 0, /*tp_str*/
254 0, /*tp_getattro*/
255 0, /*tp_setattro*/
256 0, /*tp_as_buffer*/
257 Py_TPFLAGS_DEFAULT, /*tp_flags*/
258 md5type_doc, /*tp_doc*/
259 0, /*tp_traverse*/
260 0, /*tp_clear*/
261 0, /*tp_richcompare*/
262 0, /*tp_weaklistoffset*/
263 0, /*tp_iter*/
264 0, /*tp_iternext*/
265 md5_methods, /*tp_methods*/
266 0, /*tp_members*/
267 md5_getseters, /*tp_getset*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000268};
269
270
271/* MD5 functions */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000272
Barry Warsaw8b43b191996-12-09 22:32:36 +0000273static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +0000274MD5_new(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000275{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000276 md5object *md5p;
277 Py_buffer view = { 0 };
Antoine Pitroucd8799f2012-05-23 23:16:14 +0200278 Py_ssize_t n;
279 unsigned char *buf;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000280
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000281 if (!PyArg_ParseTuple(args, "|s*:new", &view))
282 return NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000283
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000284 if ((md5p = newmd5object()) == NULL) {
285 PyBuffer_Release(&view);
286 return NULL;
287 }
Guido van Rossum5f59d601992-12-14 16:59:51 +0000288
Antoine Pitroucd8799f2012-05-23 23:16:14 +0200289 n = view.len;
290 buf = (unsigned char *) view.buf;
291 while (n > 0) {
292 Py_ssize_t nbytes;
293 if (n > INT_MAX)
294 nbytes = INT_MAX;
295 else
296 nbytes = n;
297 md5_append(&md5p->md5, buf,
298 Py_SAFE_DOWNCAST(nbytes, Py_ssize_t, unsigned int));
299 buf += nbytes;
300 n -= nbytes;
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000301 }
302 PyBuffer_Release(&view);
303
304 return (PyObject *)md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000305}
Guido van Rossum5f59d601992-12-14 16:59:51 +0000306
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000307PyDoc_STRVAR(new_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000308"new([arg]) -> md5 object\n\
309\n\
310Return a new md5 object. If arg is present, the method call update(arg)\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000311is made.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000312
Guido van Rossum5f59d601992-12-14 16:59:51 +0000313
Guido van Rossum5f59d601992-12-14 16:59:51 +0000314/* List of functions exported by this module */
315
Barry Warsaw8b43b191996-12-09 22:32:36 +0000316static PyMethodDef md5_functions[] = {
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000317 {"new", (PyCFunction)MD5_new, METH_VARARGS, new_doc},
318 {NULL, NULL} /* Sentinel */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000319};
320
321
322/* Initialize this module. */
323
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000324PyMODINIT_FUNC
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000325init_md5(void)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000326{
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000327 PyObject *m, *d;
Fred Drake0d40ba42000-02-04 20:33:49 +0000328
Antoine Pitrouc83ea132010-05-09 14:46:46 +0000329 Py_TYPE(&MD5type) = &PyType_Type;
330 if (PyType_Ready(&MD5type) < 0)
331 return;
332 m = Py_InitModule3("_md5", md5_functions, module_doc);
333 if (m == NULL)
334 return;
335 d = PyModule_GetDict(m);
336 PyDict_SetItemString(d, "MD5Type", (PyObject *)&MD5type);
337 PyModule_AddIntConstant(m, "digest_size", 16);
338 /* No need to check the error here, the caller will do that */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000339}