blob: 6c9f2c688635fc3dde2b3908218175ec003a17d0 [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"
Guido van Rossum5f59d601992-12-14 16:59:51 +000013#include "md5.h"
Guido van Rossumb6775db1994-08-01 11:34:53 +000014
Guido van Rossum5f59d601992-12-14 16:59:51 +000015typedef struct {
Barry Warsaw8b43b191996-12-09 22:32:36 +000016 PyObject_HEAD
Guido van Rossum5f59d601992-12-14 16:59:51 +000017 MD5_CTX md5; /* the context holder */
18} md5object;
19
Jeremy Hylton938ace62002-07-17 16:30:39 +000020static PyTypeObject MD5type;
Guido van Rossum5f59d601992-12-14 16:59:51 +000021
22#define is_md5object(v) ((v)->ob_type == &MD5type)
23
Guido van Rossum5f59d601992-12-14 16:59:51 +000024static md5object *
Thomas Woutersf3f33dc2000-07-21 06:00:07 +000025newmd5object(void)
Guido van Rossum5f59d601992-12-14 16:59:51 +000026{
27 md5object *md5p;
28
Guido van Rossumb18618d2000-05-03 23:44:39 +000029 md5p = PyObject_New(md5object, &MD5type);
Guido van Rossum5f59d601992-12-14 16:59:51 +000030 if (md5p == NULL)
31 return NULL;
32
33 MD5Init(&md5p->md5); /* actual initialisation */
34 return md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +000035}
Guido van Rossum5f59d601992-12-14 16:59:51 +000036
37
38/* MD5 methods */
39
40static void
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +000041md5_dealloc(md5object *md5p)
Guido van Rossum5f59d601992-12-14 16:59:51 +000042{
Guido van Rossumb18618d2000-05-03 23:44:39 +000043 PyObject_Del(md5p);
Guido van Rossumb6775db1994-08-01 11:34:53 +000044}
Guido van Rossum5f59d601992-12-14 16:59:51 +000045
46
Guido van Rossumb6775db1994-08-01 11:34:53 +000047/* MD5 methods-as-attributes */
48
Barry Warsaw8b43b191996-12-09 22:32:36 +000049static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +000050md5_update(md5object *self, PyObject *args)
Guido van Rossumb6775db1994-08-01 11:34:53 +000051{
52 unsigned char *cp;
53 int len;
54
Neal Norwitzba3a16c2002-03-31 15:27:00 +000055 if (!PyArg_ParseTuple(args, "s#:update", &cp, &len))
Guido van Rossumb6775db1994-08-01 11:34:53 +000056 return NULL;
57
58 MD5Update(&self->md5, cp, len);
59
Barry Warsaw8b43b191996-12-09 22:32:36 +000060 Py_INCREF(Py_None);
61 return Py_None;
Guido van Rossumb6775db1994-08-01 11:34:53 +000062}
63
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000064PyDoc_STRVAR(update_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +000065"update (arg)\n\
66\n\
67Update the md5 object with the string arg. Repeated calls are\n\
68equivalent to a single call with the concatenation of all the\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000069arguments.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +000070
71
Barry Warsaw8b43b191996-12-09 22:32:36 +000072static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +000073md5_digest(md5object *self)
Guido van Rossumb6775db1994-08-01 11:34:53 +000074{
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +000075 MD5_CTX mdContext;
Guido van Rossumb6775db1994-08-01 11:34:53 +000076 unsigned char aDigest[16];
77
Guido van Rossumb6775db1994-08-01 11:34:53 +000078 /* make a temporary copy, and perform the final */
79 mdContext = self->md5;
80 MD5Final(aDigest, &mdContext);
81
Barry Warsaw8b43b191996-12-09 22:32:36 +000082 return PyString_FromStringAndSize((char *)aDigest, 16);
Guido van Rossumb6775db1994-08-01 11:34:53 +000083}
84
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000085PyDoc_STRVAR(digest_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +000086"digest() -> string\n\
87\n\
88Return the digest of the strings passed to the update() method so\n\
89far. This is an 16-byte string which may contain non-ASCII characters,\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +000090including null bytes.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +000091
92
Barry Warsaw8b43b191996-12-09 22:32:36 +000093static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +000094md5_hexdigest(md5object *self)
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +000095{
96 MD5_CTX mdContext;
97 unsigned char digest[16];
98 unsigned char hexdigest[32];
99 int i, j;
100
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000101 /* make a temporary copy, and perform the final */
102 mdContext = self->md5;
103 MD5Final(digest, &mdContext);
104
105 /* Make hex version of the digest */
106 for(i=j=0; i<16; i++) {
107 char c;
108 c = (digest[i] >> 4) & 0xf;
109 c = (c>9) ? c+'a'-10 : c + '0';
110 hexdigest[j++] = c;
111 c = (digest[i] & 0xf);
112 c = (c>9) ? c+'a'-10 : c + '0';
113 hexdigest[j++] = c;
114 }
115 return PyString_FromStringAndSize((char*)hexdigest, 32);
116}
117
118
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000119PyDoc_STRVAR(hexdigest_doc,
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000120"hexdigest() -> string\n\
121\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000122Like digest(), but returns the digest as a string of hexadecimal digits.");
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000123
124
125static PyObject *
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000126md5_copy(md5object *self)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000127{
128 md5object *md5p;
129
Guido van Rossumb6775db1994-08-01 11:34:53 +0000130 if ((md5p = newmd5object()) == NULL)
131 return NULL;
132
133 md5p->md5 = self->md5;
134
Barry Warsaw8b43b191996-12-09 22:32:36 +0000135 return (PyObject *)md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000136}
137
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000138PyDoc_STRVAR(copy_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000139"copy() -> md5 object\n\
140\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000141Return a copy (``clone'') of the md5 object.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000142
143
Barry Warsaw8b43b191996-12-09 22:32:36 +0000144static PyMethodDef md5_methods[] = {
Neal Norwitzba3a16c2002-03-31 15:27:00 +0000145 {"update", (PyCFunction)md5_update, METH_VARARGS, update_doc},
Neal Norwitz3a6f9782002-03-25 20:46:46 +0000146 {"digest", (PyCFunction)md5_digest, METH_NOARGS, digest_doc},
147 {"hexdigest", (PyCFunction)md5_hexdigest, METH_NOARGS, hexdigest_doc},
148 {"copy", (PyCFunction)md5_copy, METH_NOARGS, copy_doc},
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000149 {NULL, NULL} /* sentinel */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000150};
151
Barry Warsaw8b43b191996-12-09 22:32:36 +0000152static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +0000153md5_getattr(md5object *self, char *name)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000154{
Andrew M. Kuchling75fec2c2001-11-02 21:41:00 +0000155 if (strcmp(name, "digest_size") == 0) {
156 return PyInt_FromLong(16);
157 }
158
Barry Warsaw8b43b191996-12-09 22:32:36 +0000159 return Py_FindMethod(md5_methods, (PyObject *)self, name);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000160}
161
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000162PyDoc_STRVAR(module_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000163"This module implements the interface to RSA's MD5 message digest\n\
164algorithm (see also Internet RFC 1321). Its use is quite\n\
165straightforward: use the new() to create an md5 object. You can now\n\
166feed this object with arbitrary strings using the update() method, and\n\
167at any point you can ask it for the digest (a strong kind of 128-bit\n\
Thomas Wouters7e474022000-07-16 12:04:32 +0000168checksum, a.k.a. ``fingerprint'') of the concatenation of the strings\n\
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000169fed to it so far using the digest() method.\n\
170\n\
171Functions:\n\
172\n\
173new([arg]) -- return a new md5 object, initialized with arg if provided\n\
174md5([arg]) -- DEPRECATED, same as new, but for compatibility\n\
175\n\
176Special Objects:\n\
177\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000178MD5Type -- type object for md5 objects");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000179
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000180PyDoc_STRVAR(md5type_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000181"An md5 represents the object used to calculate the MD5 checksum of a\n\
182string of information.\n\
183\n\
184Methods:\n\
185\n\
186update() -- updates the current digest with an additional string\n\
187digest() -- return the current digest value\n\
Neal Norwitz98a355d2002-10-11 21:53:01 +0000188hexdigest() -- return the current digest as a string of hexadecimal digits\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000189copy() -- return a copy of the current md5 object");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000190
Tim Peters0c322792002-07-17 16:49:03 +0000191static PyTypeObject MD5type = {
Fred Drake0d40ba42000-02-04 20:33:49 +0000192 PyObject_HEAD_INIT(NULL)
Barry Warsaw8b43b191996-12-09 22:32:36 +0000193 0, /*ob_size*/
Guido van Rossum14648392001-12-08 18:02:58 +0000194 "md5.md5", /*tp_name*/
Barry Warsaw8b43b191996-12-09 22:32:36 +0000195 sizeof(md5object), /*tp_size*/
196 0, /*tp_itemsize*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000197 /* methods */
Barry Warsaw8b43b191996-12-09 22:32:36 +0000198 (destructor)md5_dealloc, /*tp_dealloc*/
199 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000200 (getattrfunc)md5_getattr, /*tp_getattr*/
Barry Warsaw8b43b191996-12-09 22:32:36 +0000201 0, /*tp_setattr*/
202 0, /*tp_compare*/
203 0, /*tp_repr*/
204 0, /*tp_as_number*/
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000205 0, /*tp_as_sequence*/
206 0, /*tp_as_mapping*/
207 0, /*tp_hash*/
208 0, /*tp_call*/
209 0, /*tp_str*/
210 0, /*tp_getattro*/
211 0, /*tp_setattro*/
212 0, /*tp_as_buffer*/
213 0, /*tp_xxx4*/
214 md5type_doc, /*tp_doc*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000215};
216
217
218/* MD5 functions */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000219
Barry Warsaw8b43b191996-12-09 22:32:36 +0000220static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +0000221MD5_new(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000222{
223 md5object *md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000224 unsigned char *cp = NULL;
Guido van Rossumef38b781995-07-26 17:33:10 +0000225 int len = 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000226
Guido van Rossum43713e52000-02-29 13:59:29 +0000227 if (!PyArg_ParseTuple(args, "|s#:new", &cp, &len))
Guido van Rossumef38b781995-07-26 17:33:10 +0000228 return NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000229
230 if ((md5p = newmd5object()) == NULL)
231 return NULL;
232
233 if (cp)
234 MD5Update(&md5p->md5, cp, len);
235
Barry Warsaw8b43b191996-12-09 22:32:36 +0000236 return (PyObject *)md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000237}
Guido van Rossum5f59d601992-12-14 16:59:51 +0000238
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000239PyDoc_STRVAR(new_doc,
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000240"new([arg]) -> md5 object\n\
241\n\
242Return a new md5 object. If arg is present, the method call update(arg)\n\
Martin v. Löwis14f8b4c2002-06-13 20:33:02 +0000243is made.");
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000244
Guido van Rossum5f59d601992-12-14 16:59:51 +0000245
Guido van Rossum5f59d601992-12-14 16:59:51 +0000246/* List of functions exported by this module */
247
Barry Warsaw8b43b191996-12-09 22:32:36 +0000248static PyMethodDef md5_functions[] = {
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000249 {"new", (PyCFunction)MD5_new, METH_VARARGS, new_doc},
250 {"md5", (PyCFunction)MD5_new, METH_VARARGS, new_doc}, /* Backward compatibility */
Guido van Rossumef38b781995-07-26 17:33:10 +0000251 {NULL, NULL} /* Sentinel */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000252};
253
254
255/* Initialize this module. */
256
Mark Hammondfe51c6d2002-08-02 02:27:13 +0000257PyMODINIT_FUNC
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000258initmd5(void)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000259{
Fred Drake52a42e92001-11-02 22:05:06 +0000260 PyObject *m, *d;
Fred Drake0d40ba42000-02-04 20:33:49 +0000261
262 MD5type.ob_type = &PyType_Type;
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000263 m = Py_InitModule3("md5", md5_functions, module_doc);
264 d = PyModule_GetDict(m);
265 PyDict_SetItemString(d, "MD5Type", (PyObject *)&MD5type);
Fred Drake52a42e92001-11-02 22:05:06 +0000266 PyModule_AddIntConstant(m, "digest_size", 16);
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000267 /* No need to check the error here, the caller will do that */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000268}