]> git.rkrishnan.org Git - tahoe-lafs/tahoe-lafs.git/blob - Crypto/src/_fastmath.c
7fe7abecf634396c0643802d66ef11cefd9b8b99
[tahoe-lafs/tahoe-lafs.git] / Crypto / src / _fastmath.c
1
2 /*
3  *  _fastmath.c: Accelerator module that uses GMP for faster numerics.
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  * $Id: _fastmath.c,v 1.13 2003/04/04 19:20:29 jbontje Exp $
12  */
13
14 #include <stdio.h>
15 #include <string.h>
16 #include <Python.h>
17 #include <longintrepr.h>                                /* for conversions */
18 #include <gmp.h>
19
20 void
21 longObjToMPZ (mpz_t m, PyLongObject * p)
22 {
23         int size, i;
24         mpz_t temp, temp2;
25         mpz_init (temp);
26         mpz_init (temp2);
27         if (p->ob_size > 0)
28                 size = p->ob_size;
29         else
30                 size = -p->ob_size;
31         for (i = 0; i < size; i++)
32         {
33                 mpz_set_ui (temp, p->ob_digit[i]);
34                 mpz_mul_2exp (temp2, temp, SHIFT * i);
35                 mpz_add (m, m, temp2);
36         }
37         mpz_clear (temp);
38         mpz_clear (temp2);
39 }
40
41 PyObject *
42 mpzToLongObj (mpz_t m)
43 {
44         /* borrowed from gmpy */
45         int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT;
46         int i;
47         mpz_t temp;
48         PyLongObject *l = _PyLong_New (size);
49         if (!l)
50                 return NULL;
51         mpz_init_set (temp, m);
52         for (i = 0; i < size; i++)
53         {
54                 l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK);
55                 mpz_fdiv_q_2exp (temp, temp, SHIFT);
56         }
57         i = size;
58         while ((i > 0) && (l->ob_digit[i - 1] == 0))
59                 i--;
60         l->ob_size = i;
61         mpz_clear (temp);
62         return (PyObject *) l;
63 }
64
65 typedef struct
66 {
67         PyObject_HEAD mpz_t y;
68         mpz_t g;
69         mpz_t p;
70         mpz_t q;
71         mpz_t x;
72 }
73 dsaKey;
74
75 typedef struct
76 {
77         PyObject_HEAD mpz_t n;
78         mpz_t e;
79         mpz_t d;
80         mpz_t p;
81         mpz_t q;
82         mpz_t u;
83 }
84 rsaKey;
85
86 PyObject *rsaKey_new (PyObject *, PyObject *);
87 PyObject *dsaKey_new (PyObject *, PyObject *);
88
89 static void dsaKey_dealloc (dsaKey *);
90 static PyObject *dsaKey_getattr (dsaKey *, char *);
91 static PyObject *dsaKey__sign (dsaKey *, PyObject *);
92 static PyObject *dsaKey__verify (dsaKey *, PyObject *);
93 static PyObject *dsaKey_size (dsaKey *, PyObject *);
94 static PyObject *dsaKey_has_private (dsaKey *, PyObject *);
95
96 static void rsaKey_dealloc (rsaKey *);
97 static PyObject *rsaKey_getattr (rsaKey *, char *);
98 static PyObject *rsaKey__encrypt (rsaKey *, PyObject *);
99 static PyObject *rsaKey__decrypt (rsaKey *, PyObject *);
100 static PyObject *rsaKey__verify (rsaKey *, PyObject *);
101 static PyObject *rsaKey__blind (rsaKey *, PyObject *);
102 static PyObject *rsaKey__unblind (rsaKey *, PyObject *);
103 static PyObject *rsaKey_size (rsaKey *, PyObject *);
104 static PyObject *rsaKey_has_private (rsaKey *, PyObject *);
105
106 static int
107 dsaSign (dsaKey * key, mpz_t m, mpz_t k, mpz_t r, mpz_t s)
108 {
109         mpz_t temp;
110         if (mpz_cmp_ui (k, 2) < 0 || mpz_cmp (k, key->q) >= 0)
111         {
112                 return 1;
113         }
114         mpz_init (temp);
115         mpz_powm (r, key->g, k, key->p);
116         mpz_mod (r, r, key->q);
117         mpz_invert (s, k, key->q);
118         mpz_mul (temp, key->x, r);
119         mpz_add (temp, m, temp);
120         mpz_mul (s, s, temp);
121         mpz_mod (s, s, key->q);
122         mpz_clear (temp);
123         return 0;
124 }
125
126 static int
127 dsaVerify (dsaKey * key, mpz_t m, mpz_t r, mpz_t s)
128 {
129         int result;
130         mpz_t u1, u2, v1, v2, w;
131         if (mpz_cmp_ui (r, 0) <= 0 || mpz_cmp (r, key->q) >= 0 ||
132             mpz_cmp_ui (s, 0) <= 0 || mpz_cmp (s, key->q) >= 0)
133                 return 0;
134         mpz_init (u1);
135         mpz_init (u2);
136         mpz_init (v1);
137         mpz_init (v2);
138         mpz_init (w);
139         mpz_invert (w, s, key->q);
140         mpz_mul (u1, m, w);
141         mpz_mod (u1, u1, key->q);
142         mpz_mul (u2, r, w);
143         mpz_mod (u2, u2, key->q);
144         mpz_powm (v1, key->g, u1, key->p);
145         mpz_powm (v2, key->y, u2, key->p);
146         mpz_mul (w, v1, v2);
147         mpz_mod (w, w, key->p);
148         mpz_mod (w, w, key->q);
149         if (mpz_cmp (r, w) == 0)
150                 result = 1;
151         else
152                 result = 0;
153         mpz_clear (u1);
154         mpz_clear (u2);
155         mpz_clear (v1);
156         mpz_clear (v2);
157         mpz_clear (w);
158         return result;
159 }
160
161
162 static int
163 rsaEncrypt (rsaKey * key, mpz_t v)
164 {
165         if (mpz_cmp (v, key->n) >= 0)
166         {
167                 return 1;
168         }
169         mpz_powm (v, v, key->e, key->n);
170         return 0;
171 }
172
173 static int
174 rsaDecrypt (rsaKey * key, mpz_t v)
175 {
176     mpz_t m1, m2, h;
177         if (mpz_cmp (v, key->n) >= 0)
178         {
179                 return 1;
180         }
181         if (mpz_size (key->d) == 0)
182         {
183                 return 2;
184         }
185
186     if ((mpz_size (key->p) != 0) && (mpz_size (key->q) != 0) && 
187         (mpz_size (key->u) != 0))
188     {
189         /* fast path */
190         mpz_init(m1);
191         mpz_init(m2);
192         mpz_init(h);
193
194         /* m1 = c ^ (d mod (p-1)) mod p */
195         mpz_sub_ui(h, key->p, 1);
196         mpz_fdiv_r(h, key->d, h);
197         mpz_powm(m1, v, h, key->p);
198         /* m2 = c ^ (d mod (q-1)) mod q */
199         mpz_sub_ui(h, key->q, 1);
200         mpz_fdiv_r(h, key->d, h);
201         mpz_powm(m2, v, h, key->q);
202         /* h = u * ( m2 - m1 ) mod q */
203         mpz_sub(h, m2, m1);
204         if (mpz_sgn(h)==-1)
205             mpz_add(h, h, key->q);
206         mpz_mul(h, key->u, h);
207         mpz_mod(h, h, key->q);
208         /* m = m2 + h * p */
209         mpz_mul(h, h, key->p);
210         mpz_add(v, m1, h);
211         /* ready */
212
213         mpz_clear(m1);
214         mpz_clear(m2);
215         mpz_clear(h);
216         return 0;
217     }
218
219     /* slow */
220         mpz_powm (v, v, key->d, key->n);
221         return 0;
222 }
223
224 static int
225 rsaBlind (rsaKey * key, mpz_t v, mpz_t b)
226 {
227     if (mpz_cmp (v, key->n) >= 0)
228         {
229             return 1;
230         }
231     if (mpz_cmp (b, key->n) >= 0)
232         {
233             return 2;
234         }
235     mpz_powm (b, b, key->e, key->n);
236     mpz_mul (v, v, b);
237     mpz_mod (v, v, key->n);
238     return 0;
239 }
240
241 static int
242 rsaUnBlind (rsaKey * key, mpz_t v, mpz_t b)
243 {
244     if (mpz_cmp (v, key->n) >= 0)
245         {
246             return 1;
247         }
248     if (mpz_cmp (b, key->n) >= 0)
249         {
250             return 2;
251         }
252     if (!mpz_invert (b, b, key->n))
253         {
254             return 3;
255         }
256     mpz_mul (v, v, b);
257     mpz_mod (v, v, key->n);
258     return 0;
259 }
260  
261
262 static PyTypeObject dsaKeyType = {
263         PyObject_HEAD_INIT (NULL) 0,
264         "dsaKey",
265         sizeof (dsaKey),
266         0,
267         (destructor) dsaKey_dealloc,    /* dealloc */
268         0,                              /* print */
269         (getattrfunc) dsaKey_getattr,   /* getattr */
270         0,                              /* setattr */
271         0,                              /* compare */
272         0,                              /* repr */
273         0,                              /* as_number */
274         0,                              /* as_sequence */
275         0,                              /* as_mapping */
276         0,                              /* hash */
277         0,                              /* call */
278 };
279
280 static PyMethodDef dsaKey__methods__[] = {
281         {"_sign", (PyCFunction) dsaKey__sign, METH_VARARGS, 
282          "Sign the given long."},
283         {"_verify", (PyCFunction) dsaKey__verify, METH_VARARGS,
284          "Verify that the signature is valid."},
285         {"size", (PyCFunction) dsaKey_size, METH_VARARGS,
286          "Return the number of bits that this key can handle."},
287         {"has_private", (PyCFunction) dsaKey_has_private, METH_VARARGS,
288          "Return 1 or 0 if this key does/doesn't have a private key."},
289         {NULL, NULL, 0, NULL}
290 };
291
292 PyObject *fastmathError;                                                        /* raised on errors */
293
294 static PyTypeObject rsaKeyType = {
295         PyObject_HEAD_INIT (NULL) 0,
296         "rsaKey",
297         sizeof (rsaKey),
298         0,
299         (destructor) rsaKey_dealloc,    /* dealloc */
300         0,                              /* print */
301         (getattrfunc) rsaKey_getattr,   /* getattr */
302         0,                              /* setattr */
303         0,                              /* compare */
304         0,                              /* repr */
305         0,                              /* as_number */
306         0,                              /* as_sequence */
307         0,                              /* as_mapping */
308         0,                              /* hash */
309         0,                              /* call */
310 };
311
312 static PyMethodDef rsaKey__methods__[] = {
313         {"_encrypt", (PyCFunction) rsaKey__encrypt, METH_VARARGS,
314          "Encrypt the given long."},
315         {"_decrypt", (PyCFunction) rsaKey__decrypt, METH_VARARGS,
316          "Decrypt the given long."},
317         {"_sign", (PyCFunction) rsaKey__decrypt, METH_VARARGS,
318          "Sign the given long."},
319         {"_verify", (PyCFunction) rsaKey__verify, METH_VARARGS,
320          "Verify that the signature is valid."},
321         {"_blind", (PyCFunction) rsaKey__blind, METH_VARARGS,
322          "Blind the given long."},
323         {"_unblind", (PyCFunction) rsaKey__unblind, METH_VARARGS,
324          "Unblind the given long."},
325         {"size", (PyCFunction) rsaKey_size, METH_VARARGS,
326          "Return the number of bits that this key can handle."},
327         {"has_private", (PyCFunction) rsaKey_has_private, METH_VARARGS,
328          "Return 1 or 0 if this key does/doesn't have a private key."},
329         {NULL, NULL, 0, NULL}
330 };
331
332 PyObject *
333 dsaKey_new (PyObject * self, PyObject * args)
334 {
335         PyLongObject *y = NULL, *g = NULL, *p = NULL, *q = NULL, *x = NULL;
336         dsaKey *key;
337         if (!PyArg_ParseTuple(args, "O!O!O!O!|O!", &PyLong_Type, &y,
338                               &PyLong_Type, &g, &PyLong_Type, &p, 
339                               &PyLong_Type, &q, &PyLong_Type, &x))
340                 return NULL;
341
342         key = PyObject_New (dsaKey, &dsaKeyType);
343         mpz_init (key->y);
344         mpz_init (key->g);
345         mpz_init (key->p);
346         mpz_init (key->q);
347         mpz_init (key->x);
348         longObjToMPZ (key->y, y);
349         longObjToMPZ (key->g, g);
350         longObjToMPZ (key->p, p);
351         longObjToMPZ (key->q, q);
352         if (x)
353         {
354                 longObjToMPZ (key->x, x);
355         }
356         return (PyObject *) key;
357 }
358
359 static void
360 dsaKey_dealloc (dsaKey * key)
361 {
362         mpz_clear (key->y);
363         mpz_clear (key->g);
364         mpz_clear (key->p);
365         mpz_clear (key->q);
366         mpz_clear (key->x);
367         PyObject_Del (key);
368 }
369
370 static PyObject *
371 dsaKey_getattr (dsaKey * key, char *attr)
372 {
373         if (strcmp (attr, "y") == 0)
374                 return mpzToLongObj (key->y);
375         else if (strcmp (attr, "g") == 0)
376                 return mpzToLongObj (key->g);
377         else if (strcmp (attr, "p") == 0)
378                 return mpzToLongObj (key->p);
379         else if (strcmp (attr, "q") == 0)
380                 return mpzToLongObj (key->q);
381         else if (strcmp (attr, "x") == 0)
382         {
383                 if (mpz_size (key->x) == 0)
384                 {
385                         PyErr_SetString (PyExc_AttributeError,
386                                          "dsaKey instance has no attribute 'x'");
387                         return NULL;
388                 }
389                 return mpzToLongObj (key->x);
390         }
391         else
392         {
393                 return Py_FindMethod (dsaKey__methods__, (PyObject *) key, attr);
394         }
395 }
396
397 PyObject *
398 dsaKey__sign (dsaKey * key, PyObject * args)
399 {
400         PyObject *lm, *lk, *lr, *ls;
401         mpz_t m, k, r, s;
402         int result;
403         if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &lm,
404                                &PyLong_Type, &lk))
405         {
406                 return NULL;
407         }
408         mpz_init (m);
409         mpz_init (k);
410         mpz_init (r);
411         mpz_init (s);
412         longObjToMPZ (m, (PyLongObject *) lm);
413         longObjToMPZ (k, (PyLongObject *) lk);
414         result = dsaSign (key, m, k, r, s);
415         if (result == 1)
416         {
417                 PyErr_SetString (fastmathError, "K not between 2 and q");
418                 return NULL;
419         }
420         lr = mpzToLongObj (r);
421         ls = mpzToLongObj (s);
422         mpz_clear (m);
423         mpz_clear (k);
424         mpz_clear (r);
425         mpz_clear (s);
426         return Py_BuildValue ("(NN)", lr, ls);
427 }
428
429 PyObject *
430 dsaKey__verify (dsaKey * key, PyObject * args)
431 {
432         PyObject *lm, *lr, *ls;
433         mpz_t m, r, s;
434         int result;
435         if (!PyArg_ParseTuple (args, "O!O!O!", &PyLong_Type, &lm,
436                                &PyLong_Type, &lr, &PyLong_Type, &ls))
437         {
438                 return NULL;
439         }
440         mpz_init (m);
441         mpz_init (r);
442         mpz_init (s);
443         longObjToMPZ (m, (PyLongObject *) lm);
444         longObjToMPZ (r, (PyLongObject *) lr);
445         longObjToMPZ (s, (PyLongObject *) ls);
446         result = dsaVerify (key, m, r, s);
447         mpz_clear (m);
448         mpz_clear (r);
449         mpz_clear (s);
450         if (result) {
451                 Py_INCREF(Py_True);
452                 return Py_True;
453         } else {
454                 Py_INCREF(Py_False);
455                 return Py_False;
456         }
457 }
458
459 PyObject *
460 dsaKey_size (dsaKey * key, PyObject * args)
461 {
462         if (!PyArg_ParseTuple (args, ""))
463                 return NULL;
464         return Py_BuildValue ("i", mpz_sizeinbase (key->p, 2) - 1);
465 }
466
467 PyObject *
468 dsaKey_has_private (dsaKey * key, PyObject * args)
469 {
470         if (!PyArg_ParseTuple (args, ""))
471                 return NULL;
472         if (mpz_size (key->x) == 0) {
473                 Py_INCREF(Py_False);
474                 return Py_False;
475         } else {
476                 Py_INCREF(Py_True);
477                 return Py_True;
478         }
479 }
480
481 PyObject *
482 rsaKey_new (PyObject * self, PyObject * args)
483 {
484         PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL, 
485                      *u = NULL;
486         rsaKey *key;
487
488         if (!PyArg_ParseTuple(args, "O!O!|O!O!O!O!", &PyLong_Type, &n,
489                               &PyLong_Type, &e, &PyLong_Type, &d, 
490                               &PyLong_Type, &p, &PyLong_Type, &q,
491                               &PyLong_Type, &u))
492                 return NULL;
493
494         key = PyObject_New (rsaKey, &rsaKeyType);
495         mpz_init (key->n);
496         mpz_init (key->e);
497         mpz_init (key->d);
498         mpz_init (key->p);
499         mpz_init (key->q);
500         mpz_init (key->u);
501         longObjToMPZ (key->n, n);
502         longObjToMPZ (key->e, e);
503         if (!d)
504         {
505                 return (PyObject *) key;
506         }
507         longObjToMPZ (key->d, d);
508         if (p && q)
509         {
510                 longObjToMPZ (key->p, p);
511                 longObjToMPZ (key->q, q);
512                 if (u) {
513                         longObjToMPZ (key->u, u);
514                 } else {
515                         mpz_invert (key->u, key->p, key->q);
516                 }
517         }
518         return (PyObject *) key;
519 }
520
521 static void
522 rsaKey_dealloc (rsaKey * key)
523 {
524         mpz_clear (key->n);
525         mpz_clear (key->e);
526         mpz_clear (key->d);
527         mpz_clear (key->p);
528         mpz_clear (key->q);
529         mpz_clear (key->u);
530         PyObject_Del (key);
531 }
532
533 static PyObject *
534 rsaKey_getattr (rsaKey * key, char *attr)
535 {
536         if (strcmp (attr, "n") == 0)
537                 return mpzToLongObj (key->n);
538         else if (strcmp (attr, "e") == 0)
539                 return mpzToLongObj (key->e);
540         else if (strcmp (attr, "d") == 0)
541         {
542                 if (mpz_size (key->d) == 0)
543                 {
544                         PyErr_SetString(PyExc_AttributeError,
545                                         "rsaKey instance has no attribute 'd'");
546                         return NULL;
547                 }
548                 return mpzToLongObj (key->d);
549         }
550         else if (strcmp (attr, "p") == 0)
551         {
552                 if (mpz_size (key->p) == 0)
553                 {
554                         PyErr_SetString(PyExc_AttributeError,
555                                         "rsaKey instance has no attribute 'p'");
556                         return NULL;
557                 }
558                 return mpzToLongObj (key->p);
559         }
560         else if (strcmp (attr, "q") == 0)
561         {
562                 if (mpz_size (key->q) == 0)
563                 {
564                         PyErr_SetString(PyExc_AttributeError,
565                                         "rsaKey instance has no attribute 'q'");
566                         return NULL;
567                 }
568                 return mpzToLongObj (key->q);
569         }
570         else if (strcmp (attr, "u") == 0)
571         {
572                 if (mpz_size (key->u) == 0)
573                 {
574                         PyErr_SetString(PyExc_AttributeError,
575                                         "rsaKey instance has no attribute 'u'");
576                         return NULL;
577                 }
578                 return mpzToLongObj (key->u);
579         }
580         else
581         {
582                 return Py_FindMethod (rsaKey__methods__, 
583                                       (PyObject *) key, attr);
584         }
585 }
586
587 PyObject *
588 rsaKey__encrypt (rsaKey * key, PyObject * args)
589 {
590         PyObject *l, *r;
591         mpz_t v;
592         int result;
593         if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))
594         {
595                 return NULL;
596         }
597         mpz_init (v);
598         longObjToMPZ (v, (PyLongObject *) l);
599         result = rsaEncrypt (key, v);
600         if (result == 1)
601         {
602                 PyErr_SetString (fastmathError, "Plaintext too large");
603                 return NULL;
604         }
605         r = (PyObject *) mpzToLongObj (v);
606         mpz_clear (v);
607         return Py_BuildValue ("N", r);
608 }
609
610 PyObject *
611 rsaKey__decrypt (rsaKey * key, PyObject * args)
612 {
613         PyObject *l, *r;
614         mpz_t v;
615         int result;
616         if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))
617         {
618                 return NULL;
619         }
620         mpz_init (v);
621         longObjToMPZ (v, (PyLongObject *) l);
622         result = rsaDecrypt (key, v);
623         if (result == 1)
624         {
625                 PyErr_SetString (fastmathError, 
626                                  "Ciphertext too large");
627                 return NULL;
628         }
629         else if (result == 2)
630         {
631                 PyErr_SetString (fastmathError, 
632                                  "Private key not available in this object");
633                 return NULL;
634         }
635         r = mpzToLongObj (v);
636         mpz_clear (v);
637         return Py_BuildValue ("N", r);
638 }
639
640 PyObject *
641 rsaKey__verify (rsaKey * key, PyObject * args)
642 {
643         PyObject *l, *lsig;
644         mpz_t v, vsig;
645         if (!PyArg_ParseTuple(args, "O!O!", 
646                               &PyLong_Type, &l, &PyLong_Type, &lsig))
647         {
648                 return NULL;
649         }
650         mpz_init (v);
651         mpz_init (vsig);
652         longObjToMPZ (v, (PyLongObject *) l);
653         longObjToMPZ (vsig, (PyLongObject *) lsig);
654         rsaEncrypt (key, vsig);
655         if (mpz_cmp (v, vsig) == 0) {
656                 Py_INCREF(Py_True);
657                 return Py_True;
658         }
659         else {
660                 Py_INCREF(Py_False);
661                 return Py_False;
662         }
663 }
664
665 PyObject *
666 rsaKey__blind (rsaKey * key, PyObject * args)
667 {
668         PyObject *l, *lblind, *r;
669         mpz_t v, vblind;
670         int result;
671         if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l, 
672                                &PyLong_Type, &lblind))
673                 {
674                         return NULL;
675                 }
676         mpz_init (v);
677         mpz_init (vblind);
678         longObjToMPZ (v, (PyLongObject *) l);
679         longObjToMPZ (vblind, (PyLongObject *) lblind);
680         result = rsaBlind (key, v, vblind);
681         if (result == 1)
682                 {
683                         PyErr_SetString (fastmathError, "Message too large");
684                         return NULL;
685                 }
686         else if (result == 2)
687                 {
688                         PyErr_SetString (fastmathError, "Blinding factor too large");
689                         return NULL;
690                 }
691         r = (PyObject *) mpzToLongObj (v);
692         mpz_clear (v);
693         mpz_clear (vblind);
694         return Py_BuildValue ("N", r);
695 }
696
697 PyObject *
698 rsaKey__unblind (rsaKey * key, PyObject * args)
699 {
700         PyObject *l, *lblind, *r;
701         mpz_t v, vblind;
702         int result;
703         if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l, 
704                                &PyLong_Type, &lblind))
705                 {
706                         return NULL;
707                 }
708         mpz_init (v);
709         mpz_init (vblind);
710         longObjToMPZ (v, (PyLongObject *) l);
711         longObjToMPZ (vblind, (PyLongObject *) lblind);
712         result = rsaUnBlind (key, v, vblind);
713         if (result == 1)
714                 {
715                         PyErr_SetString (fastmathError, "Message too large");
716                         return NULL;
717                 }
718         else if (result == 2)
719                 {
720                         PyErr_SetString (fastmathError, "Blinding factor too large");
721                         return NULL;
722                 }
723         else if (result == 3)
724                 {
725                         PyErr_SetString (fastmathError, "Inverse doesn't exist");
726                         return NULL;
727                 }
728         r = (PyObject *) mpzToLongObj (v);
729         mpz_clear (v);
730         mpz_clear (vblind);
731         return Py_BuildValue ("N", r);
732 }
733   
734 PyObject *
735 rsaKey_size (rsaKey * key, PyObject * args)
736 {
737         if (!PyArg_ParseTuple (args, ""))
738                 return NULL;
739         return Py_BuildValue ("i", mpz_sizeinbase (key->n, 2) - 1);
740 }
741
742 PyObject *
743 rsaKey_has_private (rsaKey * key, PyObject * args)
744 {
745         if (!PyArg_ParseTuple (args, ""))
746                 return NULL;
747         if (mpz_size (key->d) == 0) {
748                 Py_INCREF(Py_False);
749                 return Py_False;
750         } else {
751                 Py_INCREF(Py_True);
752                 return Py_True;
753         }
754 }
755
756
757 PyObject *
758 isPrime (PyObject * self, PyObject * args)
759 {
760         PyObject *l;
761         mpz_t n;
762         int result;
763
764         if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))
765         {
766                 return NULL;
767         }
768         mpz_init (n);
769         longObjToMPZ (n, (PyLongObject *) l);
770
771         result = mpz_probab_prime_p(n, 5);
772
773         mpz_clear (n);
774
775         if (result == 0) {
776                 Py_INCREF(Py_False);
777                 return Py_False;
778         } else {
779                 Py_INCREF(Py_True);
780                 return Py_True;
781         }
782 }
783
784
785 static PyMethodDef _fastmath__methods__[] = {
786         {"dsa_construct", dsaKey_new, METH_VARARGS},
787         {"rsa_construct", rsaKey_new, METH_VARARGS},
788         {"isPrime", isPrime, METH_VARARGS},
789         {NULL, NULL}
790 };
791
792 void
793 init_fastmath (void)
794 {
795         PyObject *_fastmath_module;
796         PyObject *_fastmath_dict;
797
798         rsaKeyType.ob_type = &PyType_Type;
799         dsaKeyType.ob_type = &PyType_Type;
800         _fastmath_module = Py_InitModule ("_fastmath", _fastmath__methods__);
801         _fastmath_dict = PyModule_GetDict (_fastmath_module);
802         fastmathError = PyErr_NewException ("_fastmath.error", NULL, NULL);
803         PyDict_SetItemString (_fastmath_dict, "error", fastmathError);
804 }