~ubuntu-branches/ubuntu/lucid/python-crypto/lucid-updates

« back to all changes in this revision

Viewing changes to src/_rsa.c

  • Committer: Bazaar Package Importer
  • Author(s): Andreas Rottmann
  • Date: 2005-01-04 17:47:27 UTC
  • Revision ID: james.westby@ubuntu.com-20050104174727-kcbtzesd07hhozm5
Tags: upstream-2.0+dp1
ImportĀ upstreamĀ versionĀ 2.0+dp1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 *  _rsa.c: C implementation of the RSA algorithm.
 
4
 *
 
5
 * Part of the Python Cryptography Toolkit
 
6
 *
 
7
 * Distribute and use freely; there are no restrictions on further 
 
8
 * dissemination and usage except those imposed by the laws of your 
 
9
 * country of residence.
 
10
 *
 
11
 */
 
12
 
 
13
#include <stdio.h>
 
14
#include <string.h>
 
15
#include <Python.h>
 
16
#include <longintrepr.h>                                /* for conversions */
 
17
#include <gmp.h>
 
18
 
 
19
PyObject *_rsa_module;
 
20
PyObject *_rsa_dict;
 
21
 
 
22
void
 
23
longObjToMPZ (mpz_t m, PyLongObject * p)
 
24
{
 
25
        int size, i;
 
26
        mpz_t temp, temp2;
 
27
        mpz_init (temp);
 
28
        mpz_init (temp2);
 
29
        if (p->ob_size > 0)
 
30
                size = p->ob_size;
 
31
        else
 
32
                size = -p->ob_size;
 
33
        for (i = 0; i < size; i++)
 
34
                {
 
35
                        mpz_set_ui (temp, p->ob_digit[i]);
 
36
                        mpz_mul_2exp (temp2, temp, SHIFT * i);
 
37
                        mpz_add (m, m, temp2);
 
38
                }
 
39
        mpz_clear (temp);
 
40
        mpz_clear (temp2);
 
41
}
 
42
 
 
43
PyObject *
 
44
mpzToLongObj (mpz_t m)
 
45
{
 
46
        /* borrowed from gmpy */
 
47
        int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT;
 
48
        int i;
 
49
        mpz_t temp;
 
50
        PyLongObject *l = _PyLong_New (size);
 
51
        if (!l)
 
52
                return NULL;
 
53
        mpz_init_set (temp, m);
 
54
        for (i = 0; i < size; i++)
 
55
                {
 
56
                        l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK);
 
57
                        mpz_fdiv_q_2exp (temp, temp, SHIFT);
 
58
                }
 
59
        i = size;
 
60
        while ((i > 0) && (l->ob_digit[i - 1] == 0))
 
61
                i--;
 
62
        l->ob_size = i;
 
63
        mpz_clear (temp);
 
64
        return (PyObject *) l;
 
65
}
 
66
 
 
67
PyObject *rsaKey_new (PyObject *, PyObject *);
 
68
 
 
69
static PyMethodDef _rsa__methods__[] = {
 
70
        {"construct", rsaKey_new, METH_VARARGS},
 
71
        {NULL, NULL}
 
72
};
 
73
 
 
74
typedef struct
 
75
{
 
76
        PyObject_HEAD mpz_t n;
 
77
        mpz_t e;
 
78
        mpz_t d;
 
79
        mpz_t p;
 
80
        mpz_t q;
 
81
}
 
82
rsaKey;
 
83
 
 
84
static int
 
85
rsaEncrypt (rsaKey * key, mpz_t v)
 
86
{
 
87
        if (mpz_cmp (v, key->n) >= 0)
 
88
                {
 
89
                        return 1;
 
90
                }
 
91
        mpz_powm (v, v, key->e, key->n);
 
92
        return 0;
 
93
}
 
94
 
 
95
static int
 
96
rsaDecrypt (rsaKey * key, mpz_t v)
 
97
{
 
98
        if (mpz_cmp (v, key->n) >= 0)
 
99
                {
 
100
                        return 1;
 
101
                }
 
102
        if (mpz_size (key->d) == 0)
 
103
                {
 
104
                        return 2;
 
105
                }
 
106
        mpz_powm (v, v, key->d, key->n);
 
107
        return 0;
 
108
}
 
109
 
 
110
static void rsaKey_dealloc (rsaKey *);
 
111
static PyObject *rsaKey_getattr (rsaKey *, char *);
 
112
static PyObject *rsaKey__encrypt (rsaKey *, PyObject *);
 
113
static PyObject *rsaKey__decrypt (rsaKey *, PyObject *);
 
114
static PyObject *rsaKey__verify (rsaKey *, PyObject *);
 
115
static PyObject *rsaKey_size (rsaKey *, PyObject *);
 
116
static PyObject *rsaKey_hasprivate (rsaKey *, PyObject *);
 
117
 
 
118
PyObject *rsaError;                                                     /* raised on errors */
 
119
 
 
120
static PyTypeObject rsaKeyType = {
 
121
        PyObject_HEAD_INIT (NULL) 0,
 
122
        "rsaKey",
 
123
        sizeof (rsaKey),
 
124
        0,
 
125
        (destructor) rsaKey_dealloc,    /* dealloc */
 
126
        0,                                                                                                              /* print */
 
127
        (getattrfunc) rsaKey_getattr,   /* getattr */
 
128
        0,                                                                                                              /* setattr */
 
129
        0,                                                                                                              /* compare */
 
130
        0,                                                                                                              /* repr */
 
131
        0,                                                                                                              /* as_number */
 
132
        0,                                                                                                              /* as_sequence */
 
133
        0,                                                                                                              /* as_mapping */
 
134
        0,                                                                                                              /* hash */
 
135
        0,                                                                                                              /* call */
 
136
};
 
137
 
 
138
static PyMethodDef rsaKey__methods__[] = {
 
139
        {"_encrypt", (PyCFunction) rsaKey__encrypt, METH_VARARGS,
 
140
         "Encrypt the given long."},
 
141
        {"_decrypt", (PyCFunction) rsaKey__decrypt, METH_VARARGS,
 
142
         "Decrypt the given long."},
 
143
        {"_sign", (PyCFunction) rsaKey__decrypt, METH_VARARGS,
 
144
         "Sign the given long."},
 
145
        {"_verify", (PyCFunction) rsaKey__verify, METH_VARARGS,
 
146
         "Verify that the signature is valid."},
 
147
        {"size", (PyCFunction) rsaKey_size, METH_VARARGS,
 
148
         "Return the number of bits that this key can handle."},
 
149
        {"hasprivate", (PyCFunction) rsaKey_hasprivate, METH_VARARGS,
 
150
         "Return 1 or 0 if this key does/doesn't have a private key."},
 
151
        {NULL, NULL, 0, NULL}
 
152
};
 
153
 
 
154
PyObject *
 
155
rsaKey_new (PyObject * self, PyObject * args)
 
156
{
 
157
        PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL;
 
158
        rsaKey *key;
 
159
        key = PyObject_New (rsaKey, &rsaKeyType);
 
160
        mpz_init (key->n);
 
161
        mpz_init (key->e);
 
162
        mpz_init (key->d);
 
163
        mpz_init (key->p);
 
164
        mpz_init (key->q);
 
165
        PyArg_ParseTuple (args, "O!O!|O!O!O!", &PyLong_Type, &n,
 
166
                                                                                &PyLong_Type, &e,
 
167
                                                                                &PyLong_Type, &d, &PyLong_Type, &p, &PyLong_Type, &q);
 
168
        longObjToMPZ (key->n, n);
 
169
        longObjToMPZ (key->e, e);
 
170
        if (!d)
 
171
                {
 
172
                        return (PyObject *) key;
 
173
                }
 
174
        longObjToMPZ (key->d, d);
 
175
        if (p)
 
176
                {
 
177
                        if (q)
 
178
                                {
 
179
                                        longObjToMPZ (key->p, p);
 
180
                                        longObjToMPZ (key->q, q);
 
181
                                }
 
182
                }
 
183
        /*Py_XDECREF(n);
 
184
           Py_XDECREF(e);
 
185
           Py_XDECREF(d);
 
186
           Py_XDECREF(p);
 
187
           Py_XDECREF(q); */
 
188
        return (PyObject *) key;
 
189
}
 
190
 
 
191
static void
 
192
rsaKey_dealloc (rsaKey * key)
 
193
{
 
194
        mpz_clear (key->n);
 
195
        mpz_clear (key->e);
 
196
        mpz_clear (key->d);
 
197
        mpz_clear (key->p);
 
198
        mpz_clear (key->q);
 
199
        PyObject_Del (key);
 
200
}
 
201
 
 
202
static PyObject *
 
203
rsaKey_getattr (rsaKey * key, char *attr)
 
204
{
 
205
        if (strcmp (attr, "n") == 0)
 
206
                return mpzToLongObj (key->n);
 
207
        else if (strcmp (attr, "e") == 0)
 
208
                return mpzToLongObj (key->e);
 
209
        else if (strcmp (attr, "d") == 0)
 
210
                {
 
211
                        if (mpz_size (key->d) == 0)
 
212
                                {
 
213
                                        PyErr_SetString (PyExc_AttributeError,
 
214
                                                                                                         "rsaKey instance has no attribute 'd'");
 
215
                                        return NULL;
 
216
                                }
 
217
                        return mpzToLongObj (key->d);
 
218
                }
 
219
        else if (strcmp (attr, "p") == 0)
 
220
                {
 
221
                        if (mpz_size (key->p) == 0)
 
222
                                {
 
223
                                        PyErr_SetString (PyExc_AttributeError,
 
224
                                                                                                         "rsaKey instance has no attribute 'p'");
 
225
                                        return NULL;
 
226
                                }
 
227
                        return mpzToLongObj (key->p);
 
228
                }
 
229
        else if (strcmp (attr, "q") == 0)
 
230
                {
 
231
                        if (mpz_size (key->q) == 0)
 
232
                                {
 
233
                                        PyErr_SetString (PyExc_AttributeError,
 
234
                                                                                                         "rsaKey instance has no attribute 'q'");
 
235
                                        return NULL;
 
236
                                }
 
237
                        return mpzToLongObj (key->q);
 
238
                }
 
239
        else
 
240
                {
 
241
                        return Py_FindMethod (rsaKey__methods__, (PyObject *) key, attr);
 
242
                }
 
243
}
 
244
 
 
245
PyObject *
 
246
rsaKey__encrypt (rsaKey * key, PyObject * args)
 
247
{
 
248
        PyObject *l, *r;
 
249
        mpz_t v;
 
250
        int result;
 
251
        if (!(PyArg_ParseTuple (args, "O!", &PyLong_Type, &l)))
 
252
                {
 
253
                        return NULL;
 
254
                }
 
255
        mpz_init (v);
 
256
        longObjToMPZ (v, (PyLongObject *) l);
 
257
        result = rsaEncrypt (key, v);
 
258
        if (result == 1)
 
259
                {
 
260
                        PyErr_SetString (rsaError, "Plaintext too large");
 
261
                        return NULL;
 
262
                }
 
263
        r = (PyObject *) mpzToLongObj (v);
 
264
        mpz_clear (v);
 
265
        return Py_BuildValue ("N", r);
 
266
}
 
267
 
 
268
PyObject *
 
269
rsaKey__decrypt (rsaKey * key, PyObject * args)
 
270
{
 
271
        PyObject *l, *r;
 
272
        mpz_t v;
 
273
        int result;
 
274
        if (!(PyArg_ParseTuple (args, "O!", &PyLong_Type, &l)))
 
275
                {
 
276
                        return NULL;
 
277
                }
 
278
        mpz_init (v);
 
279
        longObjToMPZ (v, (PyLongObject *) l);
 
280
        result = rsaDecrypt (key, v);
 
281
        if (result == 1)
 
282
                {
 
283
                        PyErr_SetString (rsaError, "Ciphertext too large");
 
284
                        return NULL;
 
285
                }
 
286
        else if (result == 2)
 
287
                {
 
288
                        PyErr_SetString (rsaError, "Private key not available in this object");
 
289
                        return NULL;
 
290
                }
 
291
        r = mpzToLongObj (v);
 
292
        mpz_clear (v);
 
293
        return Py_BuildValue ("N", r);
 
294
}
 
295
 
 
296
PyObject *
 
297
rsaKey__verify (rsaKey * key, PyObject * args)
 
298
{
 
299
        PyObject *l, *lsig;
 
300
        mpz_t v, vsig;
 
301
        if (!
 
302
                        (PyArg_ParseTuple
 
303
                         (args, "O!O!", &PyLong_Type, &l, &PyLong_Type, &lsig)))
 
304
                {
 
305
                        return NULL;
 
306
                }
 
307
        mpz_init (v);
 
308
        mpz_init (vsig);
 
309
        longObjToMPZ (v, (PyLongObject *) l);
 
310
        longObjToMPZ (vsig, (PyLongObject *) lsig);
 
311
        rsaEncrypt (key, vsig);
 
312
        if (mpz_cmp (v, vsig) == 0)
 
313
                return Py_BuildValue ("i", 1);
 
314
        else
 
315
                return Py_BuildValue ("i", 0);
 
316
}
 
317
 
 
318
PyObject *
 
319
rsaKey_size (rsaKey * key, PyObject * args)
 
320
{
 
321
        if (!PyArg_ParseTuple (args, ""))
 
322
                return NULL;
 
323
        return Py_BuildValue ("i", mpz_sizeinbase (key->n, 2) - 1);
 
324
}
 
325
 
 
326
PyObject *
 
327
rsaKey_hasprivate (rsaKey * key, PyObject * args)
 
328
{
 
329
        if (!PyArg_ParseTuple (args, ""))
 
330
                return NULL;
 
331
        if (mpz_size (key->d) == 0)
 
332
                return Py_BuildValue ("i", 0);
 
333
        else
 
334
                return Py_BuildValue ("i", 1);
 
335
}
 
336
 
 
337
 
 
338
void
 
339
init_rsa (void)
 
340
{
 
341
        rsaKeyType.ob_type = &PyType_Type;
 
342
        _rsa_module = Py_InitModule ("_rsa", _rsa__methods__);
 
343
        _rsa_dict = PyModule_GetDict (_rsa_module);
 
344
        rsaError = PyErr_NewException ("_rsa.error", NULL, NULL);
 
345
        PyDict_SetItemString (_rsa_dict, "error", rsaError);
 
346
}