blob: beb743f765afeebbfd8549f2bbf63e81f8141885 [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
Barry Warsaw8b43b191996-12-09 22:32:36 +000020staticforward 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
Barry Warsaw8b43b191996-12-09 22:32:36 +000055 if (!PyArg_Parse(args, "s#", &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
Guido van Rossumd3a6a141998-10-14 13:46:57 +000064static char update_doc [] =
65"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\
69arguments.";
70
71
Barry Warsaw8b43b191996-12-09 22:32:36 +000072static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +000073md5_digest(md5object *self, PyObject *args)
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
Barry Warsaw8b43b191996-12-09 22:32:36 +000078 if (!PyArg_NoArgs(args))
Guido van Rossumb6775db1994-08-01 11:34:53 +000079 return NULL;
80
81 /* make a temporary copy, and perform the final */
82 mdContext = self->md5;
83 MD5Final(aDigest, &mdContext);
84
Barry Warsaw8b43b191996-12-09 22:32:36 +000085 return PyString_FromStringAndSize((char *)aDigest, 16);
Guido van Rossumb6775db1994-08-01 11:34:53 +000086}
87
Guido van Rossumd3a6a141998-10-14 13:46:57 +000088static char digest_doc [] =
89"digest() -> string\n\
90\n\
91Return the digest of the strings passed to the update() method so\n\
92far. This is an 16-byte string which may contain non-ASCII characters,\n\
93including null bytes.";
94
95
Barry Warsaw8b43b191996-12-09 22:32:36 +000096static PyObject *
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +000097md5_hexdigest(md5object *self, PyObject *args)
98{
99 MD5_CTX mdContext;
100 unsigned char digest[16];
101 unsigned char hexdigest[32];
102 int i, j;
103
104 if (!PyArg_NoArgs(args))
105 return NULL;
106
107 /* make a temporary copy, and perform the final */
108 mdContext = self->md5;
109 MD5Final(digest, &mdContext);
110
111 /* Make hex version of the digest */
112 for(i=j=0; i<16; i++) {
113 char c;
114 c = (digest[i] >> 4) & 0xf;
115 c = (c>9) ? c+'a'-10 : c + '0';
116 hexdigest[j++] = c;
117 c = (digest[i] & 0xf);
118 c = (c>9) ? c+'a'-10 : c + '0';
119 hexdigest[j++] = c;
120 }
121 return PyString_FromStringAndSize((char*)hexdigest, 32);
122}
123
124
125static char hexdigest_doc [] =
126"hexdigest() -> string\n\
127\n\
128Like digest(), but returns the digest as a string of hexadecimal digits.";
129
130
131static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +0000132md5_copy(md5object *self, PyObject *args)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000133{
134 md5object *md5p;
135
Barry Warsaw8b43b191996-12-09 22:32:36 +0000136 if (!PyArg_NoArgs(args))
Guido van Rossumb6775db1994-08-01 11:34:53 +0000137 return NULL;
138
139 if ((md5p = newmd5object()) == NULL)
140 return NULL;
141
142 md5p->md5 = self->md5;
143
Barry Warsaw8b43b191996-12-09 22:32:36 +0000144 return (PyObject *)md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000145}
146
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000147static char copy_doc [] =
148"copy() -> md5 object\n\
149\n\
150Return a copy (``clone'') of the md5 object.";
151
152
Barry Warsaw8b43b191996-12-09 22:32:36 +0000153static PyMethodDef md5_methods[] = {
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000154 {"update", (PyCFunction)md5_update, METH_OLDARGS, update_doc},
155 {"digest", (PyCFunction)md5_digest, METH_OLDARGS, digest_doc},
156 {"hexdigest", (PyCFunction)md5_hexdigest, METH_OLDARGS, hexdigest_doc},
157 {"copy", (PyCFunction)md5_copy, METH_OLDARGS, copy_doc},
158 {NULL, NULL} /* sentinel */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000159};
160
Barry Warsaw8b43b191996-12-09 22:32:36 +0000161static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +0000162md5_getattr(md5object *self, char *name)
Guido van Rossumb6775db1994-08-01 11:34:53 +0000163{
Andrew M. Kuchling75fec2c2001-11-02 21:41:00 +0000164 if (strcmp(name, "digest_size") == 0) {
165 return PyInt_FromLong(16);
166 }
167
Barry Warsaw8b43b191996-12-09 22:32:36 +0000168 return Py_FindMethod(md5_methods, (PyObject *)self, name);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000169}
170
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000171static char module_doc [] =
172
173"This module implements the interface to RSA's MD5 message digest\n\
174algorithm (see also Internet RFC 1321). Its use is quite\n\
175straightforward: use the new() to create an md5 object. You can now\n\
176feed this object with arbitrary strings using the update() method, and\n\
177at any point you can ask it for the digest (a strong kind of 128-bit\n\
Thomas Wouters7e474022000-07-16 12:04:32 +0000178checksum, a.k.a. ``fingerprint'') of the concatenation of the strings\n\
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000179fed to it so far using the digest() method.\n\
180\n\
181Functions:\n\
182\n\
183new([arg]) -- return a new md5 object, initialized with arg if provided\n\
184md5([arg]) -- DEPRECATED, same as new, but for compatibility\n\
185\n\
186Special Objects:\n\
187\n\
188MD5Type -- type object for md5 objects\n\
189";
190
191static char md5type_doc [] =
192"An md5 represents the object used to calculate the MD5 checksum of a\n\
193string of information.\n\
194\n\
195Methods:\n\
196\n\
197update() -- updates the current digest with an additional string\n\
198digest() -- return the current digest value\n\
199copy() -- return a copy of the current md5 object\n\
200";
201
Barry Warsaw8b43b191996-12-09 22:32:36 +0000202statichere PyTypeObject MD5type = {
Fred Drake0d40ba42000-02-04 20:33:49 +0000203 PyObject_HEAD_INIT(NULL)
Barry Warsaw8b43b191996-12-09 22:32:36 +0000204 0, /*ob_size*/
205 "md5", /*tp_name*/
206 sizeof(md5object), /*tp_size*/
207 0, /*tp_itemsize*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000208 /* methods */
Barry Warsaw8b43b191996-12-09 22:32:36 +0000209 (destructor)md5_dealloc, /*tp_dealloc*/
210 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000211 (getattrfunc)md5_getattr, /*tp_getattr*/
Barry Warsaw8b43b191996-12-09 22:32:36 +0000212 0, /*tp_setattr*/
213 0, /*tp_compare*/
214 0, /*tp_repr*/
215 0, /*tp_as_number*/
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000216 0, /*tp_as_sequence*/
217 0, /*tp_as_mapping*/
218 0, /*tp_hash*/
219 0, /*tp_call*/
220 0, /*tp_str*/
221 0, /*tp_getattro*/
222 0, /*tp_setattro*/
223 0, /*tp_as_buffer*/
224 0, /*tp_xxx4*/
225 md5type_doc, /*tp_doc*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000226};
227
228
229/* MD5 functions */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000230
Barry Warsaw8b43b191996-12-09 22:32:36 +0000231static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +0000232MD5_new(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000233{
234 md5object *md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000235 unsigned char *cp = NULL;
Guido van Rossumef38b781995-07-26 17:33:10 +0000236 int len = 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000237
Guido van Rossum43713e52000-02-29 13:59:29 +0000238 if (!PyArg_ParseTuple(args, "|s#:new", &cp, &len))
Guido van Rossumef38b781995-07-26 17:33:10 +0000239 return NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000240
241 if ((md5p = newmd5object()) == NULL)
242 return NULL;
243
244 if (cp)
245 MD5Update(&md5p->md5, cp, len);
246
Barry Warsaw8b43b191996-12-09 22:32:36 +0000247 return (PyObject *)md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000248}
Guido van Rossum5f59d601992-12-14 16:59:51 +0000249
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000250static char new_doc [] =
251"new([arg]) -> md5 object\n\
252\n\
253Return a new md5 object. If arg is present, the method call update(arg)\n\
254is made.";
255
Guido van Rossum5f59d601992-12-14 16:59:51 +0000256
Guido van Rossum5f59d601992-12-14 16:59:51 +0000257/* List of functions exported by this module */
258
Barry Warsaw8b43b191996-12-09 22:32:36 +0000259static PyMethodDef md5_functions[] = {
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000260 {"new", (PyCFunction)MD5_new, METH_VARARGS, new_doc},
261 {"md5", (PyCFunction)MD5_new, METH_VARARGS, new_doc}, /* Backward compatibility */
Guido van Rossumef38b781995-07-26 17:33:10 +0000262 {NULL, NULL} /* Sentinel */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000263};
264
265
266/* Initialize this module. */
267
Guido van Rossum3886bb61998-12-04 18:50:17 +0000268DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000269initmd5(void)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000270{
Fred Drake52a42e92001-11-02 22:05:06 +0000271 PyObject *m, *d;
Fred Drake0d40ba42000-02-04 20:33:49 +0000272
273 MD5type.ob_type = &PyType_Type;
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000274 m = Py_InitModule3("md5", md5_functions, module_doc);
275 d = PyModule_GetDict(m);
276 PyDict_SetItemString(d, "MD5Type", (PyObject *)&MD5type);
Fred Drake52a42e92001-11-02 22:05:06 +0000277 PyModule_AddIntConstant(m, "digest_size", 16);
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000278 /* No need to check the error here, the caller will do that */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000279}