##// END OF EJS Templates
sha1dc: use proper string functions on Python 2/3...
Gregory Szorc -
r44542:29a110e2 default
parent child Browse files
Show More
@@ -1,198 +1,198 b''
1 1 #define PY_SSIZE_T_CLEAN
2 2 #include <Python.h>
3 3
4 4 #include "lib/sha1.h"
5 5
6 6 #if PY_MAJOR_VERSION >= 3
7 7 #define IS_PY3K
8 8 #endif
9 9
10 10 /* helper to switch things like string literal depending on Python version */
11 11 #ifdef IS_PY3K
12 12 #define PY23(py2, py3) py3
13 13 #else
14 14 #define PY23(py2, py3) py2
15 15 #endif
16 16
17 17 static char sha1dc_doc[] = "Efficient detection of SHA1 collision constructs.";
18 18
19 19 /* clang-format off */
20 20 typedef struct {
21 21 PyObject_HEAD
22 22 SHA1_CTX ctx;
23 23 } pysha1ctx;
24 24 /* clang-format on */
25 25
26 26 static int pysha1ctx_init(pysha1ctx *self, PyObject *args)
27 27 {
28 28 const char *data = NULL;
29 29 Py_ssize_t len;
30 30
31 31 SHA1DCInit(&(self->ctx));
32 32 /* We don't want "safe" sha1s, wherein sha1dc can give you a
33 33 different hash for something that's trying to give you a
34 34 collision. We just want to detect collisions.
35 35 */
36 36 SHA1DCSetSafeHash(&(self->ctx), 0);
37 37 if (!PyArg_ParseTuple(args, PY23("|s#", "|y#"), &data, &len)) {
38 38 return -1;
39 39 }
40 40 if (data) {
41 41 SHA1DCUpdate(&(self->ctx), data, len);
42 42 }
43 43 return 0;
44 44 }
45 45
46 46 static void pysha1ctx_dealloc(pysha1ctx *self)
47 47 {
48 48 PyObject_Del(self);
49 49 }
50 50
51 51 static PyObject *pysha1ctx_update(pysha1ctx *self, PyObject *args)
52 52 {
53 53 const char *data;
54 54 Py_ssize_t len;
55 55 if (!PyArg_ParseTuple(args, PY23("s#", "y#"), &data, &len)) {
56 56 return NULL;
57 57 }
58 58 SHA1DCUpdate(&(self->ctx), data, len);
59 59 Py_RETURN_NONE;
60 60 }
61 61
62 62 /* it is intentional that this take a ctx by value, as that clones the
63 63 context so we can keep using .update() without poisoning the state
64 64 with padding.
65 65 */
66 66 static int finalize(SHA1_CTX ctx, unsigned char *hash_out)
67 67 {
68 68 if (SHA1DCFinal(hash_out, &ctx)) {
69 69 PyErr_SetString(PyExc_OverflowError,
70 70 "sha1 collision attack detected");
71 71 return 0;
72 72 }
73 73 return 1;
74 74 }
75 75
76 76 static PyObject *pysha1ctx_digest(pysha1ctx *self)
77 77 {
78 78 unsigned char hash[20];
79 79 if (!finalize(self->ctx, hash)) {
80 80 return NULL;
81 81 }
82 82 return PyBytes_FromStringAndSize((char *)hash, 20);
83 83 }
84 84
85 85 static PyObject *pysha1ctx_hexdigest(pysha1ctx *self)
86 86 {
87 87 static const char hexdigit[] = "0123456789abcdef";
88 88 unsigned char hash[20];
89 89 char hexhash[40];
90 90 int i;
91 91 if (!finalize(self->ctx, hash)) {
92 92 return NULL;
93 93 }
94 94 for (i = 0; i < 20; ++i) {
95 95 hexhash[i * 2] = hexdigit[hash[i] >> 4];
96 96 hexhash[i * 2 + 1] = hexdigit[hash[i] & 15];
97 97 }
98 return PyString_FromStringAndSize(hexhash, 40);
98 return PY23(PyString_FromStringAndSize, PyUnicode_FromStringAndSize)(hexhash, 40);
99 99 }
100 100
101 101 static PyTypeObject sha1ctxType;
102 102
103 103 static PyObject *pysha1ctx_copy(pysha1ctx *self)
104 104 {
105 105 pysha1ctx *clone = (pysha1ctx *)PyObject_New(pysha1ctx, &sha1ctxType);
106 106 if (!clone) {
107 107 return NULL;
108 108 }
109 109 clone->ctx = self->ctx;
110 110 return (PyObject *)clone;
111 111 }
112 112
113 113 static PyMethodDef pysha1ctx_methods[] = {
114 114 {"update", (PyCFunction)pysha1ctx_update, METH_VARARGS,
115 115 "Update this hash object's state with the provided bytes."},
116 116 {"digest", (PyCFunction)pysha1ctx_digest, METH_NOARGS,
117 117 "Return the digest value as a string of binary data."},
118 118 {"hexdigest", (PyCFunction)pysha1ctx_hexdigest, METH_NOARGS,
119 119 "Return the digest value as a string of hexadecimal digits."},
120 120 {"copy", (PyCFunction)pysha1ctx_copy, METH_NOARGS,
121 121 "Return a copy of the hash object."},
122 122 {NULL},
123 123 };
124 124
125 125 /* clang-format off */
126 126 static PyTypeObject sha1ctxType = {
127 127 PyVarObject_HEAD_INIT(NULL, 0) /* header */
128 128 "sha1dc.sha1", /* tp_name */
129 129 sizeof(pysha1ctx), /* tp_basicsize */
130 130 0, /* tp_itemsize */
131 131 (destructor)pysha1ctx_dealloc, /* tp_dealloc */
132 132 0, /* tp_print */
133 133 0, /* tp_getattr */
134 134 0, /* tp_setattr */
135 135 0, /* tp_compare */
136 136 0, /* tp_repr */
137 137 0, /* tp_as_number */
138 138 0, /* tp_as_sequence */
139 139 0, /* tp_as_mapping */
140 140 0, /* tp_hash */
141 141 0, /* tp_call */
142 142 0, /* tp_str */
143 143 0, /* tp_getattro */
144 144 0, /* tp_setattro */
145 145 0, /* tp_as_buffer */
146 146 Py_TPFLAGS_DEFAULT, /* tp_flags */
147 147 "sha1 implementation that looks for collisions", /* tp_doc */
148 148 0, /* tp_traverse */
149 149 0, /* tp_clear */
150 150 0, /* tp_richcompare */
151 151 0, /* tp_weaklistoffset */
152 152 0, /* tp_iter */
153 153 0, /* tp_iternext */
154 154 pysha1ctx_methods, /* tp_methods */
155 155 0, /* tp_members */
156 156 0, /* tp_getset */
157 157 0, /* tp_base */
158 158 0, /* tp_dict */
159 159 0, /* tp_descr_get */
160 160 0, /* tp_descr_set */
161 161 0, /* tp_dictoffset */
162 162 (initproc)pysha1ctx_init, /* tp_init */
163 163 0, /* tp_alloc */
164 164 };
165 165 /* clang-format on */
166 166
167 167 static PyMethodDef methods[] = {
168 168 {NULL, NULL},
169 169 };
170 170
171 171 static void module_init(PyObject *mod)
172 172 {
173 173 sha1ctxType.tp_new = PyType_GenericNew;
174 174 if (PyType_Ready(&sha1ctxType) < 0) {
175 175 return;
176 176 }
177 177 Py_INCREF(&sha1ctxType);
178 178
179 179 PyModule_AddObject(mod, "sha1", (PyObject *)&sha1ctxType);
180 180 }
181 181
182 182 #ifdef IS_PY3K
183 183 static struct PyModuleDef sha1dc_module = {PyModuleDef_HEAD_INIT, "sha1dc",
184 184 sha1dc_doc, -1, methods};
185 185
186 186 PyMODINIT_FUNC PyInit_sha1dc(void)
187 187 {
188 188 PyObject *mod = PyModule_Create(&sha1dc_module);
189 189 module_init(mod);
190 190 return mod;
191 191 }
192 192 #else
193 193 PyMODINIT_FUNC initsha1dc(void)
194 194 {
195 195 PyObject *mod = Py_InitModule3("sha1dc", methods, sha1dc_doc);
196 196 module_init(mod);
197 197 }
198 198 #endif
General Comments 0
You need to be logged in to leave comments. Login now