3 * _fastmath.c: Accelerator module that uses GMP for faster numerics.
5 * Part of the Python Cryptography Toolkit
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.
11 * $Id: _fastmath.c,v 1.13 2003/04/04 19:20:29 jbontje Exp $
17 #include <longintrepr.h> /* for conversions */
21 longObjToMPZ (mpz_t m, PyLongObject * p)
31 for (i = 0; i < size; i++)
33 mpz_set_ui (temp, p->ob_digit[i]);
34 mpz_mul_2exp (temp2, temp, SHIFT * i);
35 mpz_add (m, m, temp2);
42 mpzToLongObj (mpz_t m)
44 /* borrowed from gmpy */
45 int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT;
48 PyLongObject *l = _PyLong_New (size);
51 mpz_init_set (temp, m);
52 for (i = 0; i < size; i++)
54 l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK);
55 mpz_fdiv_q_2exp (temp, temp, SHIFT);
58 while ((i > 0) && (l->ob_digit[i - 1] == 0))
62 return (PyObject *) l;
67 PyObject_HEAD mpz_t y;
77 PyObject_HEAD mpz_t n;
86 PyObject *rsaKey_new (PyObject *, PyObject *);
87 PyObject *dsaKey_new (PyObject *, PyObject *);
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 *);
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 *);
107 dsaSign (dsaKey * key, mpz_t m, mpz_t k, mpz_t r, mpz_t s)
110 if (mpz_cmp_ui (k, 2) < 0 || mpz_cmp (k, key->q) >= 0)
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);
127 dsaVerify (dsaKey * key, mpz_t m, mpz_t r, mpz_t s)
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)
139 mpz_invert (w, s, key->q);
141 mpz_mod (u1, u1, key->q);
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);
147 mpz_mod (w, w, key->p);
148 mpz_mod (w, w, key->q);
149 if (mpz_cmp (r, w) == 0)
163 rsaEncrypt (rsaKey * key, mpz_t v)
165 if (mpz_cmp (v, key->n) >= 0)
169 mpz_powm (v, v, key->e, key->n);
174 rsaDecrypt (rsaKey * key, mpz_t v)
177 if (mpz_cmp (v, key->n) >= 0)
181 if (mpz_size (key->d) == 0)
186 if ((mpz_size (key->p) != 0) && (mpz_size (key->q) != 0) &&
187 (mpz_size (key->u) != 0))
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 */
205 mpz_add(h, h, key->q);
206 mpz_mul(h, key->u, h);
207 mpz_mod(h, h, key->q);
209 mpz_mul(h, h, key->p);
220 mpz_powm (v, v, key->d, key->n);
225 rsaBlind (rsaKey * key, mpz_t v, mpz_t b)
227 if (mpz_cmp (v, key->n) >= 0)
231 if (mpz_cmp (b, key->n) >= 0)
235 mpz_powm (b, b, key->e, key->n);
237 mpz_mod (v, v, key->n);
242 rsaUnBlind (rsaKey * key, mpz_t v, mpz_t b)
244 if (mpz_cmp (v, key->n) >= 0)
248 if (mpz_cmp (b, key->n) >= 0)
252 if (!mpz_invert (b, b, key->n))
257 mpz_mod (v, v, key->n);
262 static PyTypeObject dsaKeyType = {
263 PyObject_HEAD_INIT (NULL) 0,
267 (destructor) dsaKey_dealloc, /* dealloc */
269 (getattrfunc) dsaKey_getattr, /* getattr */
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}
292 PyObject *fastmathError; /* raised on errors */
294 static PyTypeObject rsaKeyType = {
295 PyObject_HEAD_INIT (NULL) 0,
299 (destructor) rsaKey_dealloc, /* dealloc */
301 (getattrfunc) rsaKey_getattr, /* getattr */
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}
333 dsaKey_new (PyObject * self, PyObject * args)
335 PyLongObject *y = NULL, *g = NULL, *p = NULL, *q = NULL, *x = NULL;
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))
342 key = PyObject_New (dsaKey, &dsaKeyType);
348 longObjToMPZ (key->y, y);
349 longObjToMPZ (key->g, g);
350 longObjToMPZ (key->p, p);
351 longObjToMPZ (key->q, q);
354 longObjToMPZ (key->x, x);
356 return (PyObject *) key;
360 dsaKey_dealloc (dsaKey * key)
371 dsaKey_getattr (dsaKey * key, char *attr)
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)
383 if (mpz_size (key->x) == 0)
385 PyErr_SetString (PyExc_AttributeError,
386 "dsaKey instance has no attribute 'x'");
389 return mpzToLongObj (key->x);
393 return Py_FindMethod (dsaKey__methods__, (PyObject *) key, attr);
398 dsaKey__sign (dsaKey * key, PyObject * args)
400 PyObject *lm, *lk, *lr, *ls;
403 if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &lm,
412 longObjToMPZ (m, (PyLongObject *) lm);
413 longObjToMPZ (k, (PyLongObject *) lk);
414 result = dsaSign (key, m, k, r, s);
417 PyErr_SetString (fastmathError, "K not between 2 and q");
420 lr = mpzToLongObj (r);
421 ls = mpzToLongObj (s);
426 return Py_BuildValue ("(NN)", lr, ls);
430 dsaKey__verify (dsaKey * key, PyObject * args)
432 PyObject *lm, *lr, *ls;
435 if (!PyArg_ParseTuple (args, "O!O!O!", &PyLong_Type, &lm,
436 &PyLong_Type, &lr, &PyLong_Type, &ls))
443 longObjToMPZ (m, (PyLongObject *) lm);
444 longObjToMPZ (r, (PyLongObject *) lr);
445 longObjToMPZ (s, (PyLongObject *) ls);
446 result = dsaVerify (key, m, r, s);
460 dsaKey_size (dsaKey * key, PyObject * args)
462 if (!PyArg_ParseTuple (args, ""))
464 return Py_BuildValue ("i", mpz_sizeinbase (key->p, 2) - 1);
468 dsaKey_has_private (dsaKey * key, PyObject * args)
470 if (!PyArg_ParseTuple (args, ""))
472 if (mpz_size (key->x) == 0) {
482 rsaKey_new (PyObject * self, PyObject * args)
484 PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL,
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,
494 key = PyObject_New (rsaKey, &rsaKeyType);
501 longObjToMPZ (key->n, n);
502 longObjToMPZ (key->e, e);
505 return (PyObject *) key;
507 longObjToMPZ (key->d, d);
510 longObjToMPZ (key->p, p);
511 longObjToMPZ (key->q, q);
513 longObjToMPZ (key->u, u);
515 mpz_invert (key->u, key->p, key->q);
518 return (PyObject *) key;
522 rsaKey_dealloc (rsaKey * key)
534 rsaKey_getattr (rsaKey * key, char *attr)
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)
542 if (mpz_size (key->d) == 0)
544 PyErr_SetString(PyExc_AttributeError,
545 "rsaKey instance has no attribute 'd'");
548 return mpzToLongObj (key->d);
550 else if (strcmp (attr, "p") == 0)
552 if (mpz_size (key->p) == 0)
554 PyErr_SetString(PyExc_AttributeError,
555 "rsaKey instance has no attribute 'p'");
558 return mpzToLongObj (key->p);
560 else if (strcmp (attr, "q") == 0)
562 if (mpz_size (key->q) == 0)
564 PyErr_SetString(PyExc_AttributeError,
565 "rsaKey instance has no attribute 'q'");
568 return mpzToLongObj (key->q);
570 else if (strcmp (attr, "u") == 0)
572 if (mpz_size (key->u) == 0)
574 PyErr_SetString(PyExc_AttributeError,
575 "rsaKey instance has no attribute 'u'");
578 return mpzToLongObj (key->u);
582 return Py_FindMethod (rsaKey__methods__,
583 (PyObject *) key, attr);
588 rsaKey__encrypt (rsaKey * key, PyObject * args)
593 if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))
598 longObjToMPZ (v, (PyLongObject *) l);
599 result = rsaEncrypt (key, v);
602 PyErr_SetString (fastmathError, "Plaintext too large");
605 r = (PyObject *) mpzToLongObj (v);
607 return Py_BuildValue ("N", r);
611 rsaKey__decrypt (rsaKey * key, PyObject * args)
616 if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))
621 longObjToMPZ (v, (PyLongObject *) l);
622 result = rsaDecrypt (key, v);
625 PyErr_SetString (fastmathError,
626 "Ciphertext too large");
629 else if (result == 2)
631 PyErr_SetString (fastmathError,
632 "Private key not available in this object");
635 r = mpzToLongObj (v);
637 return Py_BuildValue ("N", r);
641 rsaKey__verify (rsaKey * key, PyObject * args)
645 if (!PyArg_ParseTuple(args, "O!O!",
646 &PyLong_Type, &l, &PyLong_Type, &lsig))
652 longObjToMPZ (v, (PyLongObject *) l);
653 longObjToMPZ (vsig, (PyLongObject *) lsig);
654 rsaEncrypt (key, vsig);
655 if (mpz_cmp (v, vsig) == 0) {
666 rsaKey__blind (rsaKey * key, PyObject * args)
668 PyObject *l, *lblind, *r;
671 if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l,
672 &PyLong_Type, &lblind))
678 longObjToMPZ (v, (PyLongObject *) l);
679 longObjToMPZ (vblind, (PyLongObject *) lblind);
680 result = rsaBlind (key, v, vblind);
683 PyErr_SetString (fastmathError, "Message too large");
686 else if (result == 2)
688 PyErr_SetString (fastmathError, "Blinding factor too large");
691 r = (PyObject *) mpzToLongObj (v);
694 return Py_BuildValue ("N", r);
698 rsaKey__unblind (rsaKey * key, PyObject * args)
700 PyObject *l, *lblind, *r;
703 if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l,
704 &PyLong_Type, &lblind))
710 longObjToMPZ (v, (PyLongObject *) l);
711 longObjToMPZ (vblind, (PyLongObject *) lblind);
712 result = rsaUnBlind (key, v, vblind);
715 PyErr_SetString (fastmathError, "Message too large");
718 else if (result == 2)
720 PyErr_SetString (fastmathError, "Blinding factor too large");
723 else if (result == 3)
725 PyErr_SetString (fastmathError, "Inverse doesn't exist");
728 r = (PyObject *) mpzToLongObj (v);
731 return Py_BuildValue ("N", r);
735 rsaKey_size (rsaKey * key, PyObject * args)
737 if (!PyArg_ParseTuple (args, ""))
739 return Py_BuildValue ("i", mpz_sizeinbase (key->n, 2) - 1);
743 rsaKey_has_private (rsaKey * key, PyObject * args)
745 if (!PyArg_ParseTuple (args, ""))
747 if (mpz_size (key->d) == 0) {
758 isPrime (PyObject * self, PyObject * args)
764 if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))
769 longObjToMPZ (n, (PyLongObject *) l);
771 result = mpz_probab_prime_p(n, 5);
785 static PyMethodDef _fastmath__methods__[] = {
786 {"dsa_construct", dsaKey_new, METH_VARARGS},
787 {"rsa_construct", rsaKey_new, METH_VARARGS},
788 {"isPrime", isPrime, METH_VARARGS},
795 PyObject *_fastmath_module;
796 PyObject *_fastmath_dict;
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);