blob: 5e4f116329591ec1f10e81484b3cbe6e7139969b [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 {
Barry Warsaw8b43b191996-12-09 22:32:36 +000017 PyObject_HEAD
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000018 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
23#define is_md5object(v) ((v)->ob_type == &MD5type)
24
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{
28 md5object *md5p;
29
Guido van Rossumb18618d2000-05-03 23:44:39 +000030 md5p = PyObject_New(md5object, &MD5type);
Guido van Rossum5f59d601992-12-14 16:59:51 +000031 if (md5p == NULL)
32 return NULL;
33
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000034 md5_init(&md5p->md5); /* actual initialisation */
Guido van Rossum5f59d601992-12-14 16:59:51 +000035 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{
Guido van Rossumb18618d2000-05-03 23:44:39 +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{
53 unsigned char *cp;
54 int len;
55
Neal Norwitzba3a16c2002-03-31 15:27:00 +000056 if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
Guido van Rossumb6775db1994-08-01 11:34:53 +000057 return NULL;
58
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000059 md5_append(&self->md5, cp, len);
Guido van Rossumb6775db1994-08-01 11:34:53 +000060
Barry Warsaw8b43b191996-12-09 22:32:36 +000061 Py_INCREF(Py_None);
62 return Py_None;
Guido van Rossumb6775db1994-08-01 11:34:53 +000063}
64
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000065PyDoc_STRVAR(update_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +000066"update (arg)\n\
67\n\
68Update the md5 object with the string arg. Repeated calls are\n\
69equivalent to a single call with the concatenation of all the\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000070arguments.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +000071
72
Barry Warsaw8b43b191996-12-09 22:32:36 +000073static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +000074md5_digest(md5object *self)
Guido van Rossumb6775db1994-08-01 11:34:53 +000075{
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000076 md5_state_t mdContext;
Guido van Rossumb6775db1994-08-01 11:34:53 +000077 unsigned char aDigest[16];
78
Guido van Rossumb6775db1994-08-01 11:34:53 +000079 /* make a temporary copy, and perform the final */
80 mdContext = self->md5;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000081 md5_finish(&mdContext, aDigest);
Guido van Rossumb6775db1994-08-01 11:34:53 +000082
Barry Warsaw8b43b191996-12-09 22:32:36 +000083 return PyString_FromStringAndSize((char *)aDigest, 16);
Guido van Rossumb6775db1994-08-01 11:34:53 +000084}
85
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000086PyDoc_STRVAR(digest_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +000087"digest() -> string\n\
88\n\
89Return the digest of the strings passed to the update() method so\n\
Skip Montanarobd2de3a2003-07-08 21:17:25 +000090far. This is a 16-byte string which may contain non-ASCII characters,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000091including null bytes.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +000092
93
Barry Warsaw8b43b191996-12-09 22:32:36 +000094static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +000095md5_hexdigest(md5object *self)
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +000096{
Thomas Wouters49fd7fa2006-04-21 10:40:58 +000097 md5_state_t mdContext;
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +000098 unsigned char digest[16];
99 unsigned char hexdigest[32];
100 int i, j;
101
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000102 /* make a temporary copy, and perform the final */
103 mdContext = self->md5;
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000104 md5_finish(&mdContext, digest);
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000105
106 /* Make hex version of the digest */
107 for(i=j=0; i<16; i++) {
108 char c;
109 c = (digest[i] >> 4) & 0xf;
110 c = (c>9) ? c+'a'-10 : c + '0';
111 hexdigest[j++] = c;
112 c = (digest[i] & 0xf);
113 c = (c>9) ? c+'a'-10 : c + '0';
114 hexdigest[j++] = c;
115 }
116 return PyString_FromStringAndSize((char*)hexdigest, 32);
117}
118
119
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000120PyDoc_STRVAR(hexdigest_doc,
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000121"hexdigest() -> string\n\
122\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000123Like digest(), but returns the digest as a string of hexadecimal digits.");
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000124
125
126static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000127md5_copy(md5object *self)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000128{
129 md5object *md5p;
130
Guido van Rossumb6775db1994-08-01 11:34:53 +0000131 if ((md5p = newmd5object()) == NULL)
132 return NULL;
133
134 md5p->md5 = self->md5;
135
Barry Warsaw8b43b191996-12-09 22:32:36 +0000136 return (PyObject *)md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000137}
138
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000139PyDoc_STRVAR(copy_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000140"copy() -> md5 object\n\
141\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000142Return a copy (``clone'') of the md5 object.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000143
144
Barry Warsaw8b43b191996-12-09 22:32:36 +0000145static PyMethodDef md5_methods[] = {
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000146 {"update", (PyCFunction)md5_update, METH_VARARGS, update_doc},
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000147 {"digest", (PyCFunction)md5_digest, METH_NOARGS, digest_doc},
148 {"hexdigest", (PyCFunction)md5_hexdigest, METH_NOARGS, hexdigest_doc},
149 {"copy", (PyCFunction)md5_copy, METH_NOARGS, copy_doc},
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000150 {NULL, NULL} /* sentinel */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000151};
152
Barry Warsaw8b43b191996-12-09 22:32:36 +0000153static PyObject *
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000154md5_get_block_size(PyObject *self, void *closure)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000155{
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000156 return PyInt_FromLong(64);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000157}
158
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000159static PyObject *
160md5_get_digest_size(PyObject *self, void *closure)
161{
162 return PyInt_FromLong(16);
163}
164
165static PyObject *
166md5_get_name(PyObject *self, void *closure)
167{
168 return PyString_FromStringAndSize("MD5", 3);
169}
170
171static PyGetSetDef md5_getseters[] = {
172 {"digest_size",
173 (getter)md5_get_digest_size, NULL,
174 NULL,
175 NULL},
176 {"block_size",
177 (getter)md5_get_block_size, NULL,
178 NULL,
179 NULL},
180 {"name",
181 (getter)md5_get_name, NULL,
182 NULL,
183 NULL},
184 /* the old md5 and sha modules support 'digest_size' as in PEP 247.
185 * the old sha module also supported 'digestsize'. ugh. */
186 {"digestsize",
187 (getter)md5_get_digest_size, NULL,
188 NULL,
189 NULL},
190 {NULL} /* Sentinel */
191};
192
193
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000194PyDoc_STRVAR(module_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000195"This module implements the interface to RSA's MD5 message digest\n\
196algorithm (see also Internet RFC 1321). Its use is quite\n\
197straightforward: use the new() to create an md5 object. You can now\n\
198feed this object with arbitrary strings using the update() method, and\n\
199at any point you can ask it for the digest (a strong kind of 128-bit\n\
Thomas Wouters7e474022000-07-16 12:04:32 +0000200checksum, a.k.a. ``fingerprint'') of the concatenation of the strings\n\
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000201fed to it so far using the digest() method.\n\
202\n\
203Functions:\n\
204\n\
205new([arg]) -- return a new md5 object, initialized with arg if provided\n\
206md5([arg]) -- DEPRECATED, same as new, but for compatibility\n\
207\n\
208Special Objects:\n\
209\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000210MD5Type -- type object for md5 objects");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000211
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000212PyDoc_STRVAR(md5type_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000213"An md5 represents the object used to calculate the MD5 checksum of a\n\
214string of information.\n\
215\n\
216Methods:\n\
217\n\
218update() -- updates the current digest with an additional string\n\
219digest() -- return the current digest value\n\
Neal Norwitz98a355d2002-10-11 21:53:01 +0000220hexdigest() -- return the current digest as a string of hexadecimal digits\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000221copy() -- return a copy of the current md5 object");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000222
Tim Peters0c322792002-07-17 16:49:03 +0000223static PyTypeObject MD5type = {
Fred Drake0d40ba42000-02-04 20:33:49 +0000224 PyObject_HEAD_INIT(NULL)
Barry Warsaw8b43b191996-12-09 22:32:36 +0000225 0, /*ob_size*/
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000226 "_md5.md5", /*tp_name*/
Barry Warsaw8b43b191996-12-09 22:32:36 +0000227 sizeof(md5object), /*tp_size*/
228 0, /*tp_itemsize*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000229 /* methods */
Barry Warsaw8b43b191996-12-09 22:32:36 +0000230 (destructor)md5_dealloc, /*tp_dealloc*/
231 0, /*tp_print*/
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000232 0, /*tp_getattr*/
Barry Warsaw8b43b191996-12-09 22:32:36 +0000233 0, /*tp_setattr*/
234 0, /*tp_compare*/
235 0, /*tp_repr*/
236 0, /*tp_as_number*/
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000237 0, /*tp_as_sequence*/
238 0, /*tp_as_mapping*/
239 0, /*tp_hash*/
240 0, /*tp_call*/
241 0, /*tp_str*/
242 0, /*tp_getattro*/
243 0, /*tp_setattro*/
244 0, /*tp_as_buffer*/
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000245 Py_TPFLAGS_DEFAULT, /*tp_flags*/
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000246 md5type_doc, /*tp_doc*/
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000247 0, /*tp_traverse*/
248 0, /*tp_clear*/
249 0, /*tp_richcompare*/
250 0, /*tp_weaklistoffset*/
251 0, /*tp_iter*/
252 0, /*tp_iternext*/
253 md5_methods, /*tp_methods*/
254 0, /*tp_members*/
255 md5_getseters, /*tp_getset*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000256};
257
258
259/* MD5 functions */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000260
Barry Warsaw8b43b191996-12-09 22:32:36 +0000261static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +0000262MD5_new(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000263{
264 md5object *md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000265 unsigned char *cp = NULL;
Guido van Rossumef38b781995-07-26 17:33:10 +0000266 int len = 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000267
Guido van Rossum43713e52000-02-29 13:59:29 +0000268 if (!PyArg_ParseTuple(args, "|s#:new", &cp, &len))
Guido van Rossumef38b781995-07-26 17:33:10 +0000269 return NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000270
271 if ((md5p = newmd5object()) == NULL)
272 return NULL;
273
274 if (cp)
Thomas Wouters49fd7fa2006-04-21 10:40:58 +0000275 md5_append(&md5p->md5, cp, len);
Guido van Rossum5f59d601992-12-14 16:59:51 +0000276
Barry Warsaw8b43b191996-12-09 22:32:36 +0000277 return (PyObject *)md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000278}
Guido van Rossum5f59d601992-12-14 16:59:51 +0000279
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000280PyDoc_STRVAR(new_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000281"new([arg]) -> md5 object\n\
282\n\
283Return a new md5 object. If arg is present, the method call update(arg)\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000284is made.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000285
Guido van Rossum5f59d601992-12-14 16:59:51 +0000286
Guido van Rossum5f59d601992-12-14 16:59:51 +0000287/* List of functions exported by this module */
288
Barry Warsaw8b43b191996-12-09 22:32:36 +0000289static PyMethodDef md5_functions[] = {
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000290 {"new", (PyCFunction)MD5_new, METH_VARARGS, new_doc},
Guido van Rossumef38b781995-07-26 17:33:10 +0000291 {NULL, NULL} /* Sentinel */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000292};
293
294
295/* Initialize this module. */
296
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000297PyMODINIT_FUNC
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000298init_md5(void)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000299{
Fred Drake52a42e92001-11-02 22:05:06 +0000300 PyObject *m, *d;
Fred Drake0d40ba42000-02-04 20:33:49 +0000301
302 MD5type.ob_type = &PyType_Type;
Gregory P. Smithf21a5f72005-08-21 18:45:59 +0000303 if (PyType_Ready(&MD5type) < 0)
304 return;
305 m = Py_InitModule3("_md5", md5_functions, module_doc);
Neal Norwitz1ac754f2006-01-19 06:09:39 +0000306 if (m == NULL)
307 return;
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000308 d = PyModule_GetDict(m);
309 PyDict_SetItemString(d, "MD5Type", (PyObject *)&MD5type);
Fred Drake52a42e92001-11-02 22:05:06 +0000310 PyModule_AddIntConstant(m, "digest_size", 16);
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000311 /* No need to check the error here, the caller will do that */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000312}