blob: 269a298c05ade1fa5da388a452fbb835dcfb572b [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{
Barry Warsaw8b43b191996-12-09 22:32:36 +0000164 return Py_FindMethod(md5_methods, (PyObject *)self, name);
Guido van Rossumb6775db1994-08-01 11:34:53 +0000165}
166
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000167static char module_doc [] =
168
169"This module implements the interface to RSA's MD5 message digest\n\
170algorithm (see also Internet RFC 1321). Its use is quite\n\
171straightforward: use the new() to create an md5 object. You can now\n\
172feed this object with arbitrary strings using the update() method, and\n\
173at any point you can ask it for the digest (a strong kind of 128-bit\n\
Thomas Wouters7e474022000-07-16 12:04:32 +0000174checksum, a.k.a. ``fingerprint'') of the concatenation of the strings\n\
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000175fed to it so far using the digest() method.\n\
176\n\
177Functions:\n\
178\n\
179new([arg]) -- return a new md5 object, initialized with arg if provided\n\
180md5([arg]) -- DEPRECATED, same as new, but for compatibility\n\
181\n\
182Special Objects:\n\
183\n\
184MD5Type -- type object for md5 objects\n\
185";
186
187static char md5type_doc [] =
188"An md5 represents the object used to calculate the MD5 checksum of a\n\
189string of information.\n\
190\n\
191Methods:\n\
192\n\
193update() -- updates the current digest with an additional string\n\
194digest() -- return the current digest value\n\
195copy() -- return a copy of the current md5 object\n\
196";
197
Barry Warsaw8b43b191996-12-09 22:32:36 +0000198statichere PyTypeObject MD5type = {
Fred Drake0d40ba42000-02-04 20:33:49 +0000199 PyObject_HEAD_INIT(NULL)
Barry Warsaw8b43b191996-12-09 22:32:36 +0000200 0, /*ob_size*/
201 "md5", /*tp_name*/
202 sizeof(md5object), /*tp_size*/
203 0, /*tp_itemsize*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000204 /* methods */
Barry Warsaw8b43b191996-12-09 22:32:36 +0000205 (destructor)md5_dealloc, /*tp_dealloc*/
206 0, /*tp_print*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000207 (getattrfunc)md5_getattr, /*tp_getattr*/
Barry Warsaw8b43b191996-12-09 22:32:36 +0000208 0, /*tp_setattr*/
209 0, /*tp_compare*/
210 0, /*tp_repr*/
211 0, /*tp_as_number*/
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000212 0, /*tp_as_sequence*/
213 0, /*tp_as_mapping*/
214 0, /*tp_hash*/
215 0, /*tp_call*/
216 0, /*tp_str*/
217 0, /*tp_getattro*/
218 0, /*tp_setattro*/
219 0, /*tp_as_buffer*/
220 0, /*tp_xxx4*/
221 md5type_doc, /*tp_doc*/
Guido van Rossumb6775db1994-08-01 11:34:53 +0000222};
223
224
225/* MD5 functions */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000226
Barry Warsaw8b43b191996-12-09 22:32:36 +0000227static PyObject *
Peter Schneider-Kamp286da3b2000-07-10 12:43:58 +0000228MD5_new(PyObject *self, PyObject *args)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000229{
230 md5object *md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000231 unsigned char *cp = NULL;
Guido van Rossumef38b781995-07-26 17:33:10 +0000232 int len = 0;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000233
Guido van Rossum43713e52000-02-29 13:59:29 +0000234 if (!PyArg_ParseTuple(args, "|s#:new", &cp, &len))
Guido van Rossumef38b781995-07-26 17:33:10 +0000235 return NULL;
Guido van Rossum5f59d601992-12-14 16:59:51 +0000236
237 if ((md5p = newmd5object()) == NULL)
238 return NULL;
239
240 if (cp)
241 MD5Update(&md5p->md5, cp, len);
242
Barry Warsaw8b43b191996-12-09 22:32:36 +0000243 return (PyObject *)md5p;
Guido van Rossumb6775db1994-08-01 11:34:53 +0000244}
Guido van Rossum5f59d601992-12-14 16:59:51 +0000245
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000246static char new_doc [] =
247"new([arg]) -> md5 object\n\
248\n\
249Return a new md5 object. If arg is present, the method call update(arg)\n\
250is made.";
251
Guido van Rossum5f59d601992-12-14 16:59:51 +0000252
Guido van Rossum5f59d601992-12-14 16:59:51 +0000253/* List of functions exported by this module */
254
Barry Warsaw8b43b191996-12-09 22:32:36 +0000255static PyMethodDef md5_functions[] = {
Andrew M. Kuchlinge365fb82000-08-03 02:06:16 +0000256 {"new", (PyCFunction)MD5_new, METH_VARARGS, new_doc},
257 {"md5", (PyCFunction)MD5_new, METH_VARARGS, new_doc}, /* Backward compatibility */
Guido van Rossumef38b781995-07-26 17:33:10 +0000258 {NULL, NULL} /* Sentinel */
Guido van Rossum5f59d601992-12-14 16:59:51 +0000259};
260
261
262/* Initialize this module. */
263
Guido van Rossum3886bb61998-12-04 18:50:17 +0000264DL_EXPORT(void)
Thomas Woutersf3f33dc2000-07-21 06:00:07 +0000265initmd5(void)
Guido van Rossum5f59d601992-12-14 16:59:51 +0000266{
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000267 PyObject *m, *d;
Fred Drake0d40ba42000-02-04 20:33:49 +0000268
269 MD5type.ob_type = &PyType_Type;
Guido van Rossumd3a6a141998-10-14 13:46:57 +0000270 m = Py_InitModule3("md5", md5_functions, module_doc);
271 d = PyModule_GetDict(m);
272 PyDict_SetItemString(d, "MD5Type", (PyObject *)&MD5type);
273 /* No need to check the error here, the caller will do that */
Guido van Rossumb6775db1994-08-01 11:34:53 +0000274}