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