blob: fb904f49f56ef5afc92302de3ed49643bf1bf497 [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 *
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
Guido van Rossumd3a6a141998-10-14 13:46:57 +000085static char digest_doc [] =
86"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\
90including null bytes.";
91
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
119static char hexdigest_doc [] =
120"hexdigest() -> string\n\
121\n\
122Like digest(), but returns the digest as a string of hexadecimal digits.";
123
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
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000138static char copy_doc [] =
139"copy() -> md5 object\n\
140\n\
141Return a copy (``clone'') of the md5 object.";
142
143
Barry Warsaw8b43b191996-12-09 22:32:36 +0000144static PyMethodDef md5_methods[] = {
Barry Warsaw3ec0fbb2000-08-15 05:59:44 +0000145 {"update", (PyCFunction)md5_update, METH_OLDARGS, 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
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000162static char module_doc [] =
163
164"This module implements the interface to RSA's MD5 message digest\n\
165algorithm (see also Internet RFC 1321). Its use is quite\n\
166straightforward: use the new() to create an md5 object. You can now\n\
167feed this object with arbitrary strings using the update() method, and\n\
168at any point you can ask it for the digest (a strong kind of 128-bit\n\
Thomas Wouters7e474022000-07-16 12:04:32 +0000169checksum, a.k.a. ``fingerprint'') of the concatenation of the strings\n\
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000170fed to it so far using the digest() method.\n\
171\n\
172Functions:\n\
173\n\
174new([arg]) -- return a new md5 object, initialized with arg if provided\n\
175md5([arg]) -- DEPRECATED, same as new, but for compatibility\n\
176\n\
177Special Objects:\n\
178\n\
179MD5Type -- type object for md5 objects\n\
180";
181
182static char md5type_doc [] =
183"An md5 represents the object used to calculate the MD5 checksum of a\n\
184string of information.\n\
185\n\
186Methods:\n\
187\n\
188update() -- updates the current digest with an additional string\n\
189digest() -- return the current digest value\n\
190copy() -- return a copy of the current md5 object\n\
191";
192
Barry Warsaw8b43b191996-12-09 22:32:36 +0000193statichere PyTypeObject MD5type = {
Fred Drake0d40ba42000-02-04 20:33:49 +0000194 PyObject_HEAD_INIT(NULL)
Barry Warsaw8b43b191996-12-09 22:32:36 +0000195 0, /*ob_size*/
Guido van Rossum14648392001-12-08 18:02:58 +0000196 "md5.md5", /*tp_name*/
Barry Warsaw8b43b191996-12-09 22:32:36 +0000197 sizeof(md5object), /*tp_size*/
198 0, /*tp_itemsize*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000199 /* methods */
Barry Warsaw8b43b191996-12-09 22:32:36 +0000200 (destructor)md5_dealloc, /*tp_dealloc*/
201 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000202 (getattrfunc)md5_getattr, /*tp_getattr*/
Barry Warsaw8b43b191996-12-09 22:32:36 +0000203 0, /*tp_setattr*/
204 0, /*tp_compare*/
205 0, /*tp_repr*/
206 0, /*tp_as_number*/
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000207 0, /*tp_as_sequence*/
208 0, /*tp_as_mapping*/
209 0, /*tp_hash*/
210 0, /*tp_call*/
211 0, /*tp_str*/
212 0, /*tp_getattro*/
213 0, /*tp_setattro*/
214 0, /*tp_as_buffer*/
215 0, /*tp_xxx4*/
216 md5type_doc, /*tp_doc*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000217};
218
219
220/* MD5 functions */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000221
Barry Warsaw8b43b191996-12-09 22:32:36 +0000222static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +0000223MD5_new(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000224{
225 md5object *md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000226 unsigned char *cp = NULL;
Guido van Rossumef38b781995-07-26 17:33:10 +0000227 int len = 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000228
Guido van Rossum43713e52000-02-29 13:59:29 +0000229 if (!PyArg_ParseTuple(args, "|s#:new", &cp, &len))
Guido van Rossumef38b781995-07-26 17:33:10 +0000230 return NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000231
232 if ((md5p = newmd5object()) == NULL)
233 return NULL;
234
235 if (cp)
236 MD5Update(&md5p->md5, cp, len);
237
Barry Warsaw8b43b191996-12-09 22:32:36 +0000238 return (PyObject *)md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000239}
Guido van Rossum5f59d601992-12-14 16:59:51 +0000240
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000241static char new_doc [] =
242"new([arg]) -> md5 object\n\
243\n\
244Return a new md5 object. If arg is present, the method call update(arg)\n\
245is made.";
246
Guido van Rossum5f59d601992-12-14 16:59:51 +0000247
Guido van Rossum5f59d601992-12-14 16:59:51 +0000248/* List of functions exported by this module */
249
Barry Warsaw8b43b191996-12-09 22:32:36 +0000250static PyMethodDef md5_functions[] = {
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000251 {"new", (PyCFunction)MD5_new, METH_VARARGS, new_doc},
252 {"md5", (PyCFunction)MD5_new, METH_VARARGS, new_doc}, /* Backward compatibility */
Guido van Rossumef38b781995-07-26 17:33:10 +0000253 {NULL, NULL} /* Sentinel */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000254};
255
256
257/* Initialize this module. */
258
Guido van Rossum3886bb61998-12-04 18:50:17 +0000259DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000260initmd5(void)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000261{
Fred Drake52a42e92001-11-02 22:05:06 +0000262 PyObject *m, *d;
Fred Drake0d40ba42000-02-04 20:33:49 +0000263
264 MD5type.ob_type = &PyType_Type;
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000265 m = Py_InitModule3("md5", md5_functions, module_doc);
266 d = PyModule_GetDict(m);
267 PyDict_SetItemString(d, "MD5Type", (PyObject *)&MD5type);
Fred Drake52a42e92001-11-02 22:05:06 +0000268 PyModule_AddIntConstant(m, "digest_size", 16);
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000269 /* No need to check the error here, the caller will do that */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000270}