summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog8
-rw-r--r--PublicKey/RSA.py38
-rwxr-xr-xsrc/_fastmath.c72
3 files changed, 94 insertions, 24 deletions
diff --git a/ChangeLog b/ChangeLog
index 934504c..c14663f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -12,9 +12,11 @@
* Merged the _rsa.c and _dsa.c files into a single accelerator
module, _fastmath.c.
- * Added fast isPrime() function to _fastmath, cutting the time to
- generate a 1024-bit prime by a factor of 10. (Contributed by
- Joris Bontje.)
+ * Speed improvements: Added fast isPrime() function to _fastmath,
+ cutting the time to generate a 1024-bit prime by a factor of 10.
+ Optimized the C version of RSA decryption to use a longer series
+ of operations that's roughly 3x faster than a single
+ exponentiation. (Contributed by Joris Bontje.)
* Added support to RSA key objects for blinding and unblinding
data. (Contributed by Joris Bontje.)
diff --git a/PublicKey/RSA.py b/PublicKey/RSA.py
index a9149d7..6613910 100644
--- a/PublicKey/RSA.py
+++ b/PublicKey/RSA.py
@@ -10,7 +10,7 @@
# or implied. Use at your own risk or not at all.
#
-__revision__ = "$Id: RSA.py,v 1.15 2003-04-03 20:36:13 akuchling Exp $"
+__revision__ = "$Id: RSA.py,v 1.16 2003-04-04 14:59:19 akuchling Exp $"
from Crypto.PublicKey import pubkey
@@ -38,6 +38,11 @@ def generate(bits, randfunc, progress_func=None):
obj.p=pubkey.getPrime(bits/2, randfunc)
if progress_func: progress_func('q\n')
obj.q=pubkey.getPrime((bits/2)+difference, randfunc)
+ # p shall be smaller than q (for calc of u)
+ if obj.p>obj.q:
+ (obj.p, obj.q)=(obj.q, obj.p)
+ if progress_func: progress_func('u\n')
+ obj.u=pubkey.inverse(obj.p, obj.q)
obj.n=obj.p*obj.q
# Generate encryption exponent
@@ -48,21 +53,29 @@ def generate(bits, randfunc, progress_func=None):
return obj
def construct(tuple):
- """construct(tuple:(long,long)|(long,long,long)|(long,long,long,long,long))
- : RSAobj
- Construct an RSA object from a 2-, 3-, or 5-tuple of numbers.
+ """construct(tuple:(long,) : RSAobj
+ Construct an RSA object from a 2-, 3-, 5-, or 6-tuple of numbers.
"""
obj=RSAobj()
- if len(tuple) not in [2,3,5]:
+ if len(tuple) not in [2,3,5,6]:
raise error, 'argument for construct() wrong length'
for i in range(len(tuple)):
field = obj.keydata[i]
setattr(obj, field, tuple[i])
+ if len(tuple) >= 5:
+ # Ensure p is smaller than q
+ if obj.p>obj.q:
+ (obj.p, obj.q)=(obj.q, obj.p)
+
+ if len(tuple) == 5:
+ # u not supplied, so we're going to have to compute it.
+ obj.u=pubkey.inverse(obj.p, obj.q)
+
return obj
class RSAobj(pubkey.pubkey):
- keydata=['n', 'e', 'd', 'p','q']
+ keydata = ['n', 'e', 'd', 'p', 'q', 'u']
def _encrypt(self, plaintext, K=''):
if self.n<=plaintext:
raise error, 'Plaintext too large'
@@ -123,7 +136,7 @@ class RSAobj(pubkey.pubkey):
return construct((self.n, self.e))
class RSAobj_c(pubkey.pubkey):
- keydata = ['n', 'e', 'd', 'p', 'q']
+ keydata = ['n', 'e', 'd', 'p', 'q', 'u']
def __init__(self, key):
self.key = key
@@ -153,8 +166,8 @@ class RSAobj_c(pubkey.pubkey):
if 'q' not in state:
self.key = _fastmath.rsa_construct(n,e,d)
else:
- p, q = state['p'], state['q']
- self.key = _fastmath.rsa_construct(n,e,d,p,q)
+ p, q, u = state['p'], state['q'], state['u']
+ self.key = _fastmath.rsa_construct(n,e,d,p,q,u)
def _encrypt(self, plain, K):
return (self.key._encrypt(plain),)
@@ -194,6 +207,11 @@ def generate_c(bits, randfunc, progress_func = None):
p=pubkey.getPrime(bits/2, randfunc)
if progress_func: progress_func('q\n')
q=pubkey.getPrime((bits/2)+difference, randfunc)
+ # p shall be smaller than q (for calc of u)
+ if p>q:
+ (p, q)=(q, p)
+ if progress_func: progress_func('u\n')
+ u=pubkey.inverse(p, q)
n=p*q
# Generate encryption exponent
@@ -201,7 +219,7 @@ def generate_c(bits, randfunc, progress_func = None):
e=pubkey.getPrime(17, randfunc)
if progress_func: progress_func('d\n')
d=pubkey.inverse(e, (p-1)*(q-1))
- key = _fastmath.rsa_construct(n,e,d,p,q)
+ key = _fastmath.rsa_construct(n,e,d,p,q,u)
return RSAobj_c(key)
def construct_c(tuple):
diff --git a/src/_fastmath.c b/src/_fastmath.c
index f658b6b..08480e7 100755
--- a/src/_fastmath.c
+++ b/src/_fastmath.c
@@ -8,7 +8,7 @@
* dissemination and usage except those imposed by the laws of your
* country of residence.
*
- * $Id: _fastmath.c,v 1.10 2003-04-04 14:28:39 akuchling Exp $
+ * $Id: _fastmath.c,v 1.11 2003-04-04 14:59:19 akuchling Exp $
*/
#include <stdio.h>
@@ -79,6 +79,7 @@ typedef struct
mpz_t d;
mpz_t p;
mpz_t q;
+ mpz_t u;
}
rsaKey;
@@ -172,6 +173,7 @@ rsaEncrypt (rsaKey * key, mpz_t v)
static int
rsaDecrypt (rsaKey * key, mpz_t v)
{
+ mpz_t m1, m2, h;
if (mpz_cmp (v, key->n) >= 0)
{
return 1;
@@ -180,6 +182,41 @@ rsaDecrypt (rsaKey * key, mpz_t v)
{
return 2;
}
+
+ if ((mpz_size (key->p) != 0) && (mpz_size (key->q) != 0) &&
+ (mpz_size (key->u) != 0))
+ {
+ /* fast path */
+ mpz_init(m1);
+ mpz_init(m2);
+ mpz_init(h);
+
+ /* m1 = c ^ (d mod (p-1)) mod p */
+ mpz_sub_ui(h, key->p, 1);
+ mpz_fdiv_r(h, key->d, h);
+ mpz_powm(m1, v, h, key->p);
+ /* m2 = c ^ (d mod (q-1)) mod q */
+ mpz_sub_ui(h, key->q, 1);
+ mpz_fdiv_r(h, key->d, h);
+ mpz_powm(m2, v, h, key->q);
+ /* h = u * ( m2 - m1 ) mod q */
+ mpz_sub(h, m2, m1);
+ if (mpz_sgn(h)==-1)
+ mpz_add(h, h, key->q);
+ mpz_mul(h, key->u, h);
+ mpz_mod(h, h, key->q);
+ /* m = m2 + h * p */
+ mpz_mul(h, h, key->p);
+ mpz_add(v, m1, h);
+ /* ready */
+
+ mpz_clear(m1);
+ mpz_clear(m2);
+ mpz_clear(h);
+ return 0;
+ }
+
+ /* slow */
mpz_powm (v, v, key->d, key->n);
return 0;
}
@@ -449,12 +486,14 @@ dsaKey_has_private (dsaKey * key, PyObject * args)
PyObject *
rsaKey_new (PyObject * self, PyObject * args)
{
- PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL;
+ PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL,
+ *u = NULL;
rsaKey *key;
- if (!PyArg_ParseTuple(args, "O!O!|O!O!O!", &PyLong_Type, &n,
+ if (!PyArg_ParseTuple(args, "O!O!|O!O!O!O!", &PyLong_Type, &n,
&PyLong_Type, &e, &PyLong_Type, &d,
- &PyLong_Type, &p, &PyLong_Type, &q))
+ &PyLong_Type, &p, &PyLong_Type, &q,
+ &PyLong_Type, &u))
return NULL;
key = PyObject_New (rsaKey, &rsaKeyType);
@@ -463,6 +502,7 @@ rsaKey_new (PyObject * self, PyObject * args)
mpz_init (key->d);
mpz_init (key->p);
mpz_init (key->q);
+ mpz_init (key->u);
longObjToMPZ (key->n, n);
longObjToMPZ (key->e, e);
if (!d)
@@ -470,19 +510,18 @@ rsaKey_new (PyObject * self, PyObject * args)
return (PyObject *) key;
}
longObjToMPZ (key->d, d);
- if (p)
+ if (p && q && u)
{
- if (q)
- {
- longObjToMPZ (key->p, p);
- longObjToMPZ (key->q, q);
- }
+ longObjToMPZ (key->p, p);
+ longObjToMPZ (key->q, q);
+ longObjToMPZ (key->u, u);
}
/*Py_XDECREF(n);
Py_XDECREF(e);
Py_XDECREF(d);
Py_XDECREF(p);
- Py_XDECREF(q); */
+ Py_XDECREF(q);
+ Py_XDECREF(u); */
return (PyObject *) key;
}
@@ -494,6 +533,7 @@ rsaKey_dealloc (rsaKey * key)
mpz_clear (key->d);
mpz_clear (key->p);
mpz_clear (key->q);
+ mpz_clear (key->u);
PyObject_Del (key);
}
@@ -534,6 +574,16 @@ rsaKey_getattr (rsaKey * key, char *attr)
}
return mpzToLongObj (key->q);
}
+ else if (strcmp (attr, "u") == 0)
+ {
+ if (mpz_size (key->u) == 0)
+ {
+ PyErr_SetString(PyExc_AttributeError,
+ "rsaKey instance has no attribute 'u'");
+ return NULL;
+ }
+ return mpzToLongObj (key->u);
+ }
else
{
return Py_FindMethod (rsaKey__methods__,