Ticket #46: ciphercomb_cpp.dpatch

File ciphercomb_cpp.dpatch, 10.9 KB (added by xueyu, at 2010-08-11T14:26:16Z)

cipher combiner c++ patch

Line 
11 patch for repository http://tahoe-lafs.org/source/pycryptopp/trunk:
2
3Wed Aug 11 21:50:51 Öйú±ê׼ʱ¼ä 2010  xueyu7452@gmail.com
4  * ciphercomb_cpp.dpatch
5
6New patches:
7
8[ciphercomb_cpp.dpatch
9xueyu7452@gmail.com**20100811135051
10 Ignore-this: 34c8e24285544e60408d7038119819e9
11] {
12hunk ./pycryptopp/_pycryptoppmodule.cpp 8
13 #include "publickey/rsamodule.hpp"
14 #include "hash/sha256module.hpp"
15 #include "cipher/aesmodule.hpp"
16+#include "cipher/xsalsamodule.hpp"
17+#include "cipher/ciphercomb.hpp"
18 
19 PyDoc_STRVAR(_pycryptopp__doc__,
20 "_pycryptopp -- Python wrappers for a few algorithms from Crypto++\n\
21hunk ./pycryptopp/_pycryptoppmodule.cpp 19
22 from pycryptopp.publickey import rsa\n\
23 from pycryptopp import cipher\n\
24 from pycryptopp.cipher import aes\n\
25+from pycryptopp.cipher import xsalsa\n\
26+from pycryptopp.cipher import ciphercomb\n\
27 from pycryptopp import hash\n\
28 from pycryptopp.hash import sha256");
29 
30hunk ./pycryptopp/_pycryptoppmodule.cpp 46
31     init_rsa(module);
32     init_sha256(module);
33     init_aes(module);
34+    init_xsalsa(module);
35+    init_ciphercomb(module);
36 }
37 
38hunk ./pycryptopp/cipher/__init__.py 2
39 import aes
40+import xsalsa
41+import ciphercombiner 
42+import ciphercomb
43 
44 quiet_pyflakes=[aes]
45addfile ./pycryptopp/cipher/ciphercomb.cpp
46hunk ./pycryptopp/cipher/ciphercomb.cpp 1
47+/**
48+* ciphercomb.cpp -- Python wrappers around Crypto++'s AES-CTR and XSalsa20
49+*/
50+
51+#define PY_SSIZE_T_CLEAN
52+#include <Python.h>
53+#if (PY_VERSION_HEX < 0x02050000)
54+typedef int Py_ssize_t;
55+#endif
56+
57+#include "ciphercomb.hpp"
58+#include <iostream>
59+/* from Crypto++ */
60+#ifdef USE_NAME_CRYPTO_PLUS_PLUS
61+#include <crypto++/modes.h>
62+#include <crypto++/aes.h>
63+#include <crypto++/salsa.h>
64+#include <crypto++/sha.h>
65+#include <crypto++/hmac.h>
66+#else
67+#include <cryptopp/modes.h>
68+#include <cryptopp/aes.h>
69+#include <cryptopp/salsa.h>
70+#include <cryptopp/sha.h>
71+#include <cryptopp/hmac.h>
72+#endif
73+using namespace std;
74+
75+static const char*const ciphercomb___doc__ = "_ciphercomb mode\n\
76+You are advised to run aes.start_up_self_test() after importing this module.";
77+
78+static PyObject *ciphercomb_error;
79+
80+typedef struct {
81+    PyObject_HEAD
82+
83+    /* internal */
84+    CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption * e1;
85+    CryptoPP::XSalsa20::Encryption *e2;
86+} CipherComb;
87+
88+PyDoc_STRVAR(CipherComb__doc__,
89+"A CipherComb cipher object.\n\
90+\n\
91+This object encrypts/decrypts in Combiner mode.\n\
92+\n\
93+");
94+
95+static PyObject *
96+CipherComb_process(CipherComb* self, PyObject* msgobj) {
97+    if (!PyString_CheckExact(msgobj)) {
98+        PyStringObject* typerepr = reinterpret_cast<PyStringObject*>(PyObject_Repr(reinterpret_cast<PyObject*>(msgobj->ob_type)));
99+        if (typerepr) {
100+            PyErr_Format(ciphercomb_error, "Precondition violation: you are required to pass a Python string object (not a unicode, a subclass of string, or anything else), but you passed %s.", PyString_AS_STRING(reinterpret_cast<PyObject*>(typerepr)));
101+            Py_DECREF(typerepr);
102+        } else
103+            PyErr_Format(ciphercomb_error, "Precondition violation: you are required to pass a Python string object (not a unicode, a subclass of string, or anything else).");
104+        return NULL;
105+    }
106+
107+    const char *msg;
108+    Py_ssize_t msgsize;
109+    if (PyString_AsStringAndSize(msgobj, const_cast<char**>(&msg), &msgsize))
110+        return NULL;
111+    assert (msgsize >= 0);
112+
113+    PyStringObject* result1 = reinterpret_cast<PyStringObject*>(PyString_FromStringAndSize(NULL, msgsize));
114+    if (!result1)
115+        return NULL;
116+
117+    self->e1->ProcessData(reinterpret_cast<byte*>(PyString_AS_STRING(result1)), reinterpret_cast<const byte*>(msg), msgsize);
118+
119+    PyStringObject* result2 = reinterpret_cast<PyStringObject*>(PyString_FromStringAndSize(NULL, msgsize));
120+    if (!result2)
121+        return NULL;
122+    self->e2->ProcessString(reinterpret_cast<byte*>(PyString_AS_STRING(result2)), reinterpret_cast<const byte*>(PyString_AS_STRING(result1)), msgsize);
123+   
124+    return reinterpret_cast<PyObject*>(result2);
125+}
126+
127+PyDoc_STRVAR(CipherComb_process__doc__,
128+        "Encrypt or decrypt the next bytes, returning the result.");
129+
130+static PyMethodDef CipherComb_methods[] = {
131+    {"process", reinterpret_cast<PyCFunction>(CipherComb_process), METH_O, CipherComb_process__doc__},
132+    {NULL},
133+};
134+
135+static PyObject *
136+CipherComb_new(PyTypeObject* type, PyObject *args, PyObject *kwdict) {
137+    CipherComb* self = reinterpret_cast<CipherComb*>(type->tp_alloc(type, 0));
138+    if (!self)
139+        return NULL;
140+    self->e1 = NULL;
141+    self->e2 = NULL;
142+    return reinterpret_cast<PyObject*>(self);
143+}
144+
145+static void
146+CipherComb_dealloc(PyObject* self) {
147+    if (reinterpret_cast<CipherComb*>(self)->e1)
148+        delete reinterpret_cast<CipherComb*>(self)->e1;
149+    if (reinterpret_cast<CipherComb*>(self)->e2)
150+        delete reinterpret_cast<CipherComb*>(self)->e2;
151+    self->ob_type->tp_free(self);
152+}
153+
154+static int
155+CipherComb_init(PyObject* self, PyObject *args, PyObject *kwdict) {
156+    static const char *kwlist[] = { "key", "iv", NULL };
157+    const char *key = NULL;
158+    Py_ssize_t keysize = 0;
159+    const char *iv = NULL;
160+    const char defaultiv[40] = {0};
161+    Py_ssize_t ivsize = 0;
162+    if (!PyArg_ParseTupleAndKeywords(args, kwdict, "t#|t#:CipherComb.__init__", const_cast<char**>(kwlist), &key, &keysize, &iv, &ivsize))
163+        return -1;
164+    assert (keysize >= 0);
165+    assert (ivsize >= 0);
166+
167+    char prk[32];
168+    char* salt="";
169+    CryptoPP::HMAC<CryptoPP::SHA256>(reinterpret_cast<byte*>(salt), 0).CalculateDigest(reinterpret_cast<byte*>(prk), reinterpret_cast<const byte*>(key), keysize);
170+
171+    char t1[32];
172+    char t2[32];
173+    char ext1[1] = {0x01};
174+    CryptoPP::HMAC<CryptoPP::SHA256>(reinterpret_cast<byte*>(prk), 32).CalculateDigest(reinterpret_cast<byte*>(t1), reinterpret_cast<const byte*>(ext1), 1);
175+    char ext2[33];
176+    memcpy(ext2, t1, 32);
177+    ext2[32] = 0x02;
178+    CryptoPP::HMAC<CryptoPP::SHA256>(reinterpret_cast<byte*>(prk), 32).CalculateDigest(reinterpret_cast<byte*>(t2), reinterpret_cast<const byte*>(ext2), 33);
179+
180+    char aeskey[16];
181+    int aeskeysize = 16;
182+    char xsalsakey[32];
183+    int xskeysize = 32;
184+    memcpy(aeskey, t1, 16);
185+    memcpy(xsalsakey, t1+16, 16);
186+    memcpy(xsalsakey+16, t2, 16);
187+   
188+    char aesiv[16];
189+    char xsalsaiv[24];
190+    if (!iv)
191+        iv = defaultiv;
192+    memcpy(aesiv, iv, 16);
193+    memcpy(xsalsaiv, iv+16, 24);
194+    try {
195+        reinterpret_cast<CipherComb*>(self)->e1 = new CryptoPP::CTR_Mode<CryptoPP::AES>::Encryption(reinterpret_cast<const byte*>(aeskey), aeskeysize, reinterpret_cast<const byte*>(aesiv));
196+        reinterpret_cast<CipherComb*>(self)->e2 = new CryptoPP::XSalsa20::Encryption(reinterpret_cast<const byte*>(xsalsakey), xskeysize, reinterpret_cast<const byte*>(xsalsaiv));
197+       
198+    } catch (CryptoPP::InvalidKeyLength le) {
199+        PyErr_Format(ciphercomb_error, "Precondition violation: you are required to pass a valid key size.  Crypto++ gave this exception: %s", le.what());
200+        return -1;
201+    }
202+    if (!reinterpret_cast<CipherComb*>(self)->e1 || !reinterpret_cast<CipherComb*>(self)->e2 ) {
203+        PyErr_NoMemory();
204+        return -1;
205+    }
206+    return 0;
207+}
208+
209+static PyTypeObject CipherComb_type = {
210+    PyObject_HEAD_INIT(NULL)
211+    0,                         /*ob_size*/
212+    "_ciphercomb.CipherComb", /*tp_name*/
213+    sizeof(CipherComb),             /*tp_basicsize*/
214+    0,                         /*tp_itemsize*/
215+    CipherComb_dealloc, /*tp_dealloc*/
216+    0,                         /*tp_print*/
217+    0,                         /*tp_getattr*/
218+    0,                         /*tp_setattr*/
219+    0,                         /*tp_compare*/
220+    0,                         /*tp_repr*/
221+    0,                         /*tp_as_number*/
222+    0,                         /*tp_as_sequence*/
223+    0,                         /*tp_as_mapping*/
224+    0,                         /*tp_hash */
225+    0,                         /*tp_call*/
226+    0,                         /*tp_str*/
227+    0,                         /*tp_getattro*/
228+    0,                         /*tp_setattro*/
229+    0,                         /*tp_as_buffer*/
230+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /*tp_flags*/
231+    CipherComb__doc__,           /* tp_doc */
232+    0,                     /* tp_traverse */
233+    0,                     /* tp_clear */
234+    0,                     /* tp_richcompare */
235+    0,                     /* tp_weaklistoffset */
236+    0,                     /* tp_iter */
237+    0,                     /* tp_iternext */
238+    CipherComb_methods,      /* tp_methods */
239+    0,                         /* tp_members */
240+    0,                         /* tp_getset */
241+    0,                         /* tp_base */
242+    0,                         /* tp_dict */
243+    0,                         /* tp_descr_get */
244+    0,                         /* tp_descr_set */
245+    0,                         /* tp_dictoffset */
246+    CipherComb_init,               /* tp_init */
247+    0,                         /* tp_alloc */
248+    CipherComb_new,                /* tp_new */
249+};
250+
251+void init_ciphercomb(PyObject*const module) {
252+    if (PyType_Ready(&CipherComb_type) < 0)
253+        return;
254+    Py_INCREF(&CipherComb_type);
255+    PyModule_AddObject(module, "ciphercomb_CipherComb", (PyObject *)&CipherComb_type);
256+
257+    ciphercomb_error = PyErr_NewException(const_cast<char*>("_ciphercomb.Error"), NULL, NULL);
258+    PyModule_AddObject(module, "ciphercomb_Error", ciphercomb_error);
259+
260+    PyModule_AddStringConstant(module, "ciphercomb___doc__", const_cast<char*>(ciphercomb___doc__));
261+}
262+
263+
264addfile ./pycryptopp/cipher/ciphercomb.hpp
265hunk ./pycryptopp/cipher/ciphercomb.hpp 1
266+#ifndef __INCL_CIPHERCOMB_HPP
267+#define __INCL_CIPHERCOMB_HPP
268+
269+extern void init_ciphercomb(PyObject* module);
270+
271+#endif
272addfile ./pycryptopp/cipher/ciphercomb.py
273hunk ./pycryptopp/cipher/ciphercomb.py 1
274+
275+from pycryptopp import _import_my_names
276+
277+#CipherComb=None
278+#Error=None
279+
280+_import_my_names(globals(), "ciphercomb_")
281+
282+del _import_my_names
283+
284}
285
286Context:
287
288[fix compile on MacOS X and MinGW
289zooko@zooko.com**20100729061519
290 Ignore-this: c8ba5c5a1e78932e86a1beee38f0d98b
291 r463 | weidai | 2009-04-05 13:58:48 -0600 (Sun, 05 Apr 2009) | 2 lines
292] 
293[turns out rijndael.cpp doesn't need malloc at all! Which is good, because the current #include triggers a compile error on FreeBSD. This patches fixes that by removing the #include
294zooko@zooko.com**20100725164338
295 Ignore-this: 37c0da6d3b246b464975c7264df76792
296] 
297[setup: reorganize misc/ to match Tahoe-LAFS's misc/ so that the same buildmaster config can use pycryptopp's and Tahoe-LAFS's
298zooko@zooko.com**20100607062909
299 Ignore-this: 500b1eab3ac1983dd72d4d120b48ac64
300] 
301[TAG pycryptopp-0.5.19
302zooko@zooko.com**20100604065231
303 Ignore-this: 923894ad4dca6c77ed31e80c3e4b64e7
304] 
305Patch bundle hash:
3065804e4918425aa719acc4b3d6f50ca49ac20957f