--- /dev/null
+#
+# RSA.py : RSA encryption/decryption
+#
+# Part of the Python Cryptography Toolkit
+#
+# Distribute and use freely; there are no restrictions on further
+# dissemination and usage except those imposed by the laws of your
+# country of residence. This software is provided "as is" without
+# warranty of fitness for use or suitability for any purpose, express
+# or implied. Use at your own risk or not at all.
+#
+
+__revision__ = "$Id: RSA.py,v 1.20 2004/05/06 12:52:54 akuchling Exp $"
+
+from allmydata.Crypto.PublicKey import pubkey
+from allmydata.Crypto.Util import number
+
+_fastmath = None
+try:
+ from allmydata.Crypto.PublicKey import _fastmath
+except ImportError:
+ pass
+
+class error (Exception):
+ pass
+
+def generate(bits, randfunc, progress_func=None):
+ """generate(bits:int, randfunc:callable, progress_func:callable)
+
+ Generate an RSA key of length 'bits', using 'randfunc' to get
+ random data and 'progress_func', if present, to display
+ the progress of the key generation.
+ """
+ obj=RSAobj()
+
+ # Generate the prime factors of n
+ if progress_func:
+ progress_func('p,q\n')
+ p = q = 1L
+ while number.size(p*q) < bits:
+ p = pubkey.getPrime(bits/2, randfunc)
+ q = pubkey.getPrime(bits/2, randfunc)
+
+ # p shall be smaller than q (for calc of u)
+ if p > q:
+ (p, q)=(q, p)
+ obj.p = p
+ obj.q = q
+
+ if progress_func:
+ progress_func('u\n')
+ obj.u = pubkey.inverse(obj.p, obj.q)
+ obj.n = obj.p*obj.q
+
+ obj.e = 65537L
+ if progress_func:
+ progress_func('d\n')
+ obj.d=pubkey.inverse(obj.e, (obj.p-1)*(obj.q-1))
+
+ assert bits <= 1+obj.size(), "Generated key is too small"
+
+ return obj
+
+def construct(tuple):
+ """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,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', 'u']
+ def _encrypt(self, plaintext, K=''):
+ if self.n<=plaintext:
+ raise error, 'Plaintext too large'
+ return (pow(plaintext, self.e, self.n),)
+
+ def _decrypt(self, ciphertext):
+ if (not hasattr(self, 'd')):
+ raise error, 'Private key not available in this object'
+ if self.n<=ciphertext[0]:
+ raise error, 'Ciphertext too large'
+ return pow(ciphertext[0], self.d, self.n)
+
+ def _sign(self, M, K=''):
+ return (self._decrypt((M,)),)
+
+ def _verify(self, M, sig):
+ m2=self._encrypt(sig[0])
+ if m2[0]==M:
+ return 1
+ else: return 0
+
+ def _blind(self, M, B):
+ tmp = pow(B, self.e, self.n)
+ return (M * tmp) % self.n
+
+ def _unblind(self, M, B):
+ tmp = pubkey.inverse(B, self.n)
+ return (M * tmp) % self.n
+
+ def can_blind (self):
+ """can_blind() : bool
+ Return a Boolean value recording whether this algorithm can
+ blind data. (This does not imply that this
+ particular key object has the private information required to
+ to blind a message.)
+ """
+ return 1
+
+ def size(self):
+ """size() : int
+ Return the maximum number of bits that can be handled by this key.
+ """
+ return number.size(self.n) - 1
+
+ def has_private(self):
+ """has_private() : bool
+ Return a Boolean denoting whether the object contains
+ private components.
+ """
+ if hasattr(self, 'd'):
+ return 1
+ else: return 0
+
+ def publickey(self):
+ """publickey(): RSAobj
+ Return a new key object containing only the public key information.
+ """
+ return construct((self.n, self.e))
+
+class RSAobj_c(pubkey.pubkey):
+ keydata = ['n', 'e', 'd', 'p', 'q', 'u']
+
+ def __init__(self, key):
+ self.key = key
+
+ def __getattr__(self, attr):
+ if attr in self.keydata:
+ return getattr(self.key, attr)
+ else:
+ if self.__dict__.has_key(attr):
+ self.__dict__[attr]
+ else:
+ raise AttributeError, '%s instance has no attribute %s' % (self.__class__, attr)
+
+ def __getstate__(self):
+ d = {}
+ for k in self.keydata:
+ if hasattr(self.key, k):
+ d[k]=getattr(self.key, k)
+ return d
+
+ def __setstate__(self, state):
+ n,e = state['n'], state['e']
+ if not state.has_key('d'):
+ self.key = _fastmath.rsa_construct(n,e)
+ else:
+ d = state['d']
+ if not state.has_key('q'):
+ self.key = _fastmath.rsa_construct(n,e,d)
+ else:
+ 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),)
+
+ def _decrypt(self, cipher):
+ return self.key._decrypt(cipher[0])
+
+ def _sign(self, M, K):
+ return (self.key._sign(M),)
+
+ def _verify(self, M, sig):
+ return self.key._verify(M, sig[0])
+
+ def _blind(self, M, B):
+ return self.key._blind(M, B)
+
+ def _unblind(self, M, B):
+ return self.key._unblind(M, B)
+
+ def can_blind (self):
+ return 1
+
+ def size(self):
+ return self.key.size()
+
+ def has_private(self):
+ return self.key.has_private()
+
+ def publickey(self):
+ return construct_c((self.key.n, self.key.e))
+
+def generate_c(bits, randfunc, progress_func = None):
+ # Generate the prime factors of n
+ if progress_func:
+ progress_func('p,q\n')
+
+ p = q = 1L
+ while number.size(p*q) < bits:
+ p = pubkey.getPrime(bits/2, randfunc)
+ q = pubkey.getPrime(bits/2, 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
+
+ e = 65537L
+ if progress_func:
+ progress_func('d\n')
+ d=pubkey.inverse(e, (p-1)*(q-1))
+ key = _fastmath.rsa_construct(n,e,d,p,q,u)
+ obj = RSAobj_c(key)
+
+## print p
+## print q
+## print number.size(p), number.size(q), number.size(q*p),
+## print obj.size(), bits
+ assert bits <= 1+obj.size(), "Generated key is too small"
+ return obj
+
+
+def construct_c(tuple):
+ key = apply(_fastmath.rsa_construct, tuple)
+ return RSAobj_c(key)
+
+object = RSAobj
+
+generate_py = generate
+construct_py = construct
+
+if _fastmath:
+ #print "using C version of RSA"
+ generate = generate_c
+ construct = construct_c
+ error = _fastmath.error
--- /dev/null
+#
+# pubkey.py : Internal functions for public key operations
+#
+# Part of the Python Cryptography Toolkit
+#
+# Distribute and use freely; there are no restrictions on further
+# dissemination and usage except those imposed by the laws of your
+# country of residence. This software is provided "as is" without
+# warranty of fitness for use or suitability for any purpose, express
+# or implied. Use at your own risk or not at all.
+#
+
+__revision__ = "$Id: pubkey.py,v 1.11 2003/04/03 20:36:14 akuchling Exp $"
+
+import types, warnings
+from allmydata.Crypto.Util.number import bignum, bytes_to_long, \
+ long_to_bytes, error
+
+# Basic public key class
+class pubkey:
+ def __init__(self):
+ pass
+
+ def __getstate__(self):
+ """To keep key objects platform-independent, the key data is
+ converted to standard Python long integers before being
+ written out. It will then be reconverted as necessary on
+ restoration."""
+ d=self.__dict__
+ for key in self.keydata:
+ if d.has_key(key): d[key]=long(d[key])
+ return d
+
+ def __setstate__(self, d):
+ """On unpickling a key object, the key data is converted to the big
+number representation being used, whether that is Python long
+integers, MPZ objects, or whatever."""
+ for key in self.keydata:
+ if d.has_key(key): self.__dict__[key]=bignum(d[key])
+
+ def encrypt(self, plaintext, K):
+ """encrypt(plaintext:string|long, K:string|long) : tuple
+ Encrypt the string or integer plaintext. K is a random
+ parameter required by some algorithms.
+ """
+ wasString=0
+ if isinstance(plaintext, types.StringType):
+ plaintext=bytes_to_long(plaintext) ; wasString=1
+ if isinstance(K, types.StringType):
+ K=bytes_to_long(K)
+ ciphertext=self._encrypt(plaintext, K)
+ if wasString: return tuple(map(long_to_bytes, ciphertext))
+ else: return ciphertext
+
+ def decrypt(self, ciphertext):
+ """decrypt(ciphertext:tuple|string|long): string
+ Decrypt 'ciphertext' using this key.
+ """
+ wasString=0
+ if not isinstance(ciphertext, types.TupleType):
+ ciphertext=(ciphertext,)
+ if isinstance(ciphertext[0], types.StringType):
+ ciphertext=tuple(map(bytes_to_long, ciphertext)) ; wasString=1
+ plaintext=self._decrypt(ciphertext)
+ if wasString: return long_to_bytes(plaintext)
+ else: return plaintext
+
+ def sign(self, M, K):
+ """sign(M : string|long, K:string|long) : tuple
+ Return a tuple containing the signature for the message M.
+ K is a random parameter required by some algorithms.
+ """
+ if (not self.has_private()):
+ raise error, 'Private key not available in this object'
+ if isinstance(M, types.StringType): M=bytes_to_long(M)
+ if isinstance(K, types.StringType): K=bytes_to_long(K)
+ return self._sign(M, K)
+
+ def verify (self, M, signature):
+ """verify(M:string|long, signature:tuple) : bool
+ Verify that the signature is valid for the message M;
+ returns true if the signature checks out.
+ """
+ if isinstance(M, types.StringType): M=bytes_to_long(M)
+ return self._verify(M, signature)
+
+ # alias to compensate for the old validate() name
+ def validate (self, M, signature):
+ warnings.warn("validate() method name is obsolete; use verify()",
+ DeprecationWarning)
+
+ def blind(self, M, B):
+ """blind(M : string|long, B : string|long) : string|long
+ Blind message M using blinding factor B.
+ """
+ wasString=0
+ if isinstance(M, types.StringType):
+ M=bytes_to_long(M) ; wasString=1
+ if isinstance(B, types.StringType): B=bytes_to_long(B)
+ blindedmessage=self._blind(M, B)
+ if wasString: return long_to_bytes(blindedmessage)
+ else: return blindedmessage
+
+ def unblind(self, M, B):
+ """unblind(M : string|long, B : string|long) : string|long
+ Unblind message M using blinding factor B.
+ """
+ wasString=0
+ if isinstance(M, types.StringType):
+ M=bytes_to_long(M) ; wasString=1
+ if isinstance(B, types.StringType): B=bytes_to_long(B)
+ unblindedmessage=self._unblind(M, B)
+ if wasString: return long_to_bytes(unblindedmessage)
+ else: return unblindedmessage
+
+
+ # The following methods will usually be left alone, except for
+ # signature-only algorithms. They both return Boolean values
+ # recording whether this key's algorithm can sign and encrypt.
+ def can_sign (self):
+ """can_sign() : bool
+ Return a Boolean value recording whether this algorithm can
+ generate signatures. (This does not imply that this
+ particular key object has the private information required to
+ to generate a signature.)
+ """
+ return 1
+
+ def can_encrypt (self):
+ """can_encrypt() : bool
+ Return a Boolean value recording whether this algorithm can
+ encrypt data. (This does not imply that this
+ particular key object has the private information required to
+ to decrypt a message.)
+ """
+ return 1
+
+ def can_blind (self):
+ """can_blind() : bool
+ Return a Boolean value recording whether this algorithm can
+ blind data. (This does not imply that this
+ particular key object has the private information required to
+ to blind a message.)
+ """
+ return 0
+
+ # The following methods will certainly be overridden by
+ # subclasses.
+
+ def size (self):
+ """size() : int
+ Return the maximum number of bits that can be handled by this key.
+ """
+ return 0
+
+ def has_private (self):
+ """has_private() : bool
+ Return a Boolean denoting whether the object contains
+ private components.
+ """
+ return 0
+
+ def publickey (self):
+ """publickey(): object
+ Return a new key object containing only the public information.
+ """
+ return self
+
+ def __eq__ (self, other):
+ """__eq__(other): 0, 1
+ Compare us to other for equality.
+ """
+ return self.__getstate__() == other.__getstate__()
--- /dev/null
+
+/*
+ * _fastmath.c: Accelerator module that uses GMP for faster numerics.
+ *
+ * Part of the Python Cryptography Toolkit
+ *
+ * Distribute and use freely; there are no restrictions on further
+ * dissemination and usage except those imposed by the laws of your
+ * country of residence.
+ *
+ * $Id: _fastmath.c,v 1.13 2003/04/04 19:20:29 jbontje Exp $
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <Python.h>
+#include <longintrepr.h> /* for conversions */
+#include <gmp.h>
+
+void
+longObjToMPZ (mpz_t m, PyLongObject * p)
+{
+ int size, i;
+ mpz_t temp, temp2;
+ mpz_init (temp);
+ mpz_init (temp2);
+ if (p->ob_size > 0)
+ size = p->ob_size;
+ else
+ size = -p->ob_size;
+ for (i = 0; i < size; i++)
+ {
+ mpz_set_ui (temp, p->ob_digit[i]);
+ mpz_mul_2exp (temp2, temp, SHIFT * i);
+ mpz_add (m, m, temp2);
+ }
+ mpz_clear (temp);
+ mpz_clear (temp2);
+}
+
+PyObject *
+mpzToLongObj (mpz_t m)
+{
+ /* borrowed from gmpy */
+ int size = (mpz_sizeinbase (m, 2) + SHIFT - 1) / SHIFT;
+ int i;
+ mpz_t temp;
+ PyLongObject *l = _PyLong_New (size);
+ if (!l)
+ return NULL;
+ mpz_init_set (temp, m);
+ for (i = 0; i < size; i++)
+ {
+ l->ob_digit[i] = (digit) (mpz_get_ui (temp) & MASK);
+ mpz_fdiv_q_2exp (temp, temp, SHIFT);
+ }
+ i = size;
+ while ((i > 0) && (l->ob_digit[i - 1] == 0))
+ i--;
+ l->ob_size = i;
+ mpz_clear (temp);
+ return (PyObject *) l;
+}
+
+typedef struct
+{
+ PyObject_HEAD mpz_t y;
+ mpz_t g;
+ mpz_t p;
+ mpz_t q;
+ mpz_t x;
+}
+dsaKey;
+
+typedef struct
+{
+ PyObject_HEAD mpz_t n;
+ mpz_t e;
+ mpz_t d;
+ mpz_t p;
+ mpz_t q;
+ mpz_t u;
+}
+rsaKey;
+
+PyObject *rsaKey_new (PyObject *, PyObject *);
+PyObject *dsaKey_new (PyObject *, PyObject *);
+
+static void dsaKey_dealloc (dsaKey *);
+static PyObject *dsaKey_getattr (dsaKey *, char *);
+static PyObject *dsaKey__sign (dsaKey *, PyObject *);
+static PyObject *dsaKey__verify (dsaKey *, PyObject *);
+static PyObject *dsaKey_size (dsaKey *, PyObject *);
+static PyObject *dsaKey_has_private (dsaKey *, PyObject *);
+
+static void rsaKey_dealloc (rsaKey *);
+static PyObject *rsaKey_getattr (rsaKey *, char *);
+static PyObject *rsaKey__encrypt (rsaKey *, PyObject *);
+static PyObject *rsaKey__decrypt (rsaKey *, PyObject *);
+static PyObject *rsaKey__verify (rsaKey *, PyObject *);
+static PyObject *rsaKey__blind (rsaKey *, PyObject *);
+static PyObject *rsaKey__unblind (rsaKey *, PyObject *);
+static PyObject *rsaKey_size (rsaKey *, PyObject *);
+static PyObject *rsaKey_has_private (rsaKey *, PyObject *);
+
+static int
+dsaSign (dsaKey * key, mpz_t m, mpz_t k, mpz_t r, mpz_t s)
+{
+ mpz_t temp;
+ if (mpz_cmp_ui (k, 2) < 0 || mpz_cmp (k, key->q) >= 0)
+ {
+ return 1;
+ }
+ mpz_init (temp);
+ mpz_powm (r, key->g, k, key->p);
+ mpz_mod (r, r, key->q);
+ mpz_invert (s, k, key->q);
+ mpz_mul (temp, key->x, r);
+ mpz_add (temp, m, temp);
+ mpz_mul (s, s, temp);
+ mpz_mod (s, s, key->q);
+ mpz_clear (temp);
+ return 0;
+}
+
+static int
+dsaVerify (dsaKey * key, mpz_t m, mpz_t r, mpz_t s)
+{
+ int result;
+ mpz_t u1, u2, v1, v2, w;
+ if (mpz_cmp_ui (r, 0) <= 0 || mpz_cmp (r, key->q) >= 0 ||
+ mpz_cmp_ui (s, 0) <= 0 || mpz_cmp (s, key->q) >= 0)
+ return 0;
+ mpz_init (u1);
+ mpz_init (u2);
+ mpz_init (v1);
+ mpz_init (v2);
+ mpz_init (w);
+ mpz_invert (w, s, key->q);
+ mpz_mul (u1, m, w);
+ mpz_mod (u1, u1, key->q);
+ mpz_mul (u2, r, w);
+ mpz_mod (u2, u2, key->q);
+ mpz_powm (v1, key->g, u1, key->p);
+ mpz_powm (v2, key->y, u2, key->p);
+ mpz_mul (w, v1, v2);
+ mpz_mod (w, w, key->p);
+ mpz_mod (w, w, key->q);
+ if (mpz_cmp (r, w) == 0)
+ result = 1;
+ else
+ result = 0;
+ mpz_clear (u1);
+ mpz_clear (u2);
+ mpz_clear (v1);
+ mpz_clear (v2);
+ mpz_clear (w);
+ return result;
+}
+
+
+static int
+rsaEncrypt (rsaKey * key, mpz_t v)
+{
+ if (mpz_cmp (v, key->n) >= 0)
+ {
+ return 1;
+ }
+ mpz_powm (v, v, key->e, key->n);
+ return 0;
+}
+
+static int
+rsaDecrypt (rsaKey * key, mpz_t v)
+{
+ mpz_t m1, m2, h;
+ if (mpz_cmp (v, key->n) >= 0)
+ {
+ return 1;
+ }
+ if (mpz_size (key->d) == 0)
+ {
+ 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;
+}
+
+static int
+rsaBlind (rsaKey * key, mpz_t v, mpz_t b)
+{
+ if (mpz_cmp (v, key->n) >= 0)
+ {
+ return 1;
+ }
+ if (mpz_cmp (b, key->n) >= 0)
+ {
+ return 2;
+ }
+ mpz_powm (b, b, key->e, key->n);
+ mpz_mul (v, v, b);
+ mpz_mod (v, v, key->n);
+ return 0;
+}
+
+static int
+rsaUnBlind (rsaKey * key, mpz_t v, mpz_t b)
+{
+ if (mpz_cmp (v, key->n) >= 0)
+ {
+ return 1;
+ }
+ if (mpz_cmp (b, key->n) >= 0)
+ {
+ return 2;
+ }
+ if (!mpz_invert (b, b, key->n))
+ {
+ return 3;
+ }
+ mpz_mul (v, v, b);
+ mpz_mod (v, v, key->n);
+ return 0;
+}
+
+
+static PyTypeObject dsaKeyType = {
+ PyObject_HEAD_INIT (NULL) 0,
+ "dsaKey",
+ sizeof (dsaKey),
+ 0,
+ (destructor) dsaKey_dealloc, /* dealloc */
+ 0, /* print */
+ (getattrfunc) dsaKey_getattr, /* getattr */
+ 0, /* setattr */
+ 0, /* compare */
+ 0, /* repr */
+ 0, /* as_number */
+ 0, /* as_sequence */
+ 0, /* as_mapping */
+ 0, /* hash */
+ 0, /* call */
+};
+
+static PyMethodDef dsaKey__methods__[] = {
+ {"_sign", (PyCFunction) dsaKey__sign, METH_VARARGS,
+ "Sign the given long."},
+ {"_verify", (PyCFunction) dsaKey__verify, METH_VARARGS,
+ "Verify that the signature is valid."},
+ {"size", (PyCFunction) dsaKey_size, METH_VARARGS,
+ "Return the number of bits that this key can handle."},
+ {"has_private", (PyCFunction) dsaKey_has_private, METH_VARARGS,
+ "Return 1 or 0 if this key does/doesn't have a private key."},
+ {NULL, NULL, 0, NULL}
+};
+
+PyObject *fastmathError; /* raised on errors */
+
+static PyTypeObject rsaKeyType = {
+ PyObject_HEAD_INIT (NULL) 0,
+ "rsaKey",
+ sizeof (rsaKey),
+ 0,
+ (destructor) rsaKey_dealloc, /* dealloc */
+ 0, /* print */
+ (getattrfunc) rsaKey_getattr, /* getattr */
+ 0, /* setattr */
+ 0, /* compare */
+ 0, /* repr */
+ 0, /* as_number */
+ 0, /* as_sequence */
+ 0, /* as_mapping */
+ 0, /* hash */
+ 0, /* call */
+};
+
+static PyMethodDef rsaKey__methods__[] = {
+ {"_encrypt", (PyCFunction) rsaKey__encrypt, METH_VARARGS,
+ "Encrypt the given long."},
+ {"_decrypt", (PyCFunction) rsaKey__decrypt, METH_VARARGS,
+ "Decrypt the given long."},
+ {"_sign", (PyCFunction) rsaKey__decrypt, METH_VARARGS,
+ "Sign the given long."},
+ {"_verify", (PyCFunction) rsaKey__verify, METH_VARARGS,
+ "Verify that the signature is valid."},
+ {"_blind", (PyCFunction) rsaKey__blind, METH_VARARGS,
+ "Blind the given long."},
+ {"_unblind", (PyCFunction) rsaKey__unblind, METH_VARARGS,
+ "Unblind the given long."},
+ {"size", (PyCFunction) rsaKey_size, METH_VARARGS,
+ "Return the number of bits that this key can handle."},
+ {"has_private", (PyCFunction) rsaKey_has_private, METH_VARARGS,
+ "Return 1 or 0 if this key does/doesn't have a private key."},
+ {NULL, NULL, 0, NULL}
+};
+
+PyObject *
+dsaKey_new (PyObject * self, PyObject * args)
+{
+ PyLongObject *y = NULL, *g = NULL, *p = NULL, *q = NULL, *x = NULL;
+ dsaKey *key;
+ if (!PyArg_ParseTuple(args, "O!O!O!O!|O!", &PyLong_Type, &y,
+ &PyLong_Type, &g, &PyLong_Type, &p,
+ &PyLong_Type, &q, &PyLong_Type, &x))
+ return NULL;
+
+ key = PyObject_New (dsaKey, &dsaKeyType);
+ mpz_init (key->y);
+ mpz_init (key->g);
+ mpz_init (key->p);
+ mpz_init (key->q);
+ mpz_init (key->x);
+ longObjToMPZ (key->y, y);
+ longObjToMPZ (key->g, g);
+ longObjToMPZ (key->p, p);
+ longObjToMPZ (key->q, q);
+ if (x)
+ {
+ longObjToMPZ (key->x, x);
+ }
+ return (PyObject *) key;
+}
+
+static void
+dsaKey_dealloc (dsaKey * key)
+{
+ mpz_clear (key->y);
+ mpz_clear (key->g);
+ mpz_clear (key->p);
+ mpz_clear (key->q);
+ mpz_clear (key->x);
+ PyObject_Del (key);
+}
+
+static PyObject *
+dsaKey_getattr (dsaKey * key, char *attr)
+{
+ if (strcmp (attr, "y") == 0)
+ return mpzToLongObj (key->y);
+ else if (strcmp (attr, "g") == 0)
+ return mpzToLongObj (key->g);
+ else if (strcmp (attr, "p") == 0)
+ return mpzToLongObj (key->p);
+ else if (strcmp (attr, "q") == 0)
+ return mpzToLongObj (key->q);
+ else if (strcmp (attr, "x") == 0)
+ {
+ if (mpz_size (key->x) == 0)
+ {
+ PyErr_SetString (PyExc_AttributeError,
+ "dsaKey instance has no attribute 'x'");
+ return NULL;
+ }
+ return mpzToLongObj (key->x);
+ }
+ else
+ {
+ return Py_FindMethod (dsaKey__methods__, (PyObject *) key, attr);
+ }
+}
+
+PyObject *
+dsaKey__sign (dsaKey * key, PyObject * args)
+{
+ PyObject *lm, *lk, *lr, *ls;
+ mpz_t m, k, r, s;
+ int result;
+ if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &lm,
+ &PyLong_Type, &lk))
+ {
+ return NULL;
+ }
+ mpz_init (m);
+ mpz_init (k);
+ mpz_init (r);
+ mpz_init (s);
+ longObjToMPZ (m, (PyLongObject *) lm);
+ longObjToMPZ (k, (PyLongObject *) lk);
+ result = dsaSign (key, m, k, r, s);
+ if (result == 1)
+ {
+ PyErr_SetString (fastmathError, "K not between 2 and q");
+ return NULL;
+ }
+ lr = mpzToLongObj (r);
+ ls = mpzToLongObj (s);
+ mpz_clear (m);
+ mpz_clear (k);
+ mpz_clear (r);
+ mpz_clear (s);
+ return Py_BuildValue ("(NN)", lr, ls);
+}
+
+PyObject *
+dsaKey__verify (dsaKey * key, PyObject * args)
+{
+ PyObject *lm, *lr, *ls;
+ mpz_t m, r, s;
+ int result;
+ if (!PyArg_ParseTuple (args, "O!O!O!", &PyLong_Type, &lm,
+ &PyLong_Type, &lr, &PyLong_Type, &ls))
+ {
+ return NULL;
+ }
+ mpz_init (m);
+ mpz_init (r);
+ mpz_init (s);
+ longObjToMPZ (m, (PyLongObject *) lm);
+ longObjToMPZ (r, (PyLongObject *) lr);
+ longObjToMPZ (s, (PyLongObject *) ls);
+ result = dsaVerify (key, m, r, s);
+ mpz_clear (m);
+ mpz_clear (r);
+ mpz_clear (s);
+ if (result) {
+ Py_INCREF(Py_True);
+ return Py_True;
+ } else {
+ Py_INCREF(Py_False);
+ return Py_False;
+ }
+}
+
+PyObject *
+dsaKey_size (dsaKey * key, PyObject * args)
+{
+ if (!PyArg_ParseTuple (args, ""))
+ return NULL;
+ return Py_BuildValue ("i", mpz_sizeinbase (key->p, 2) - 1);
+}
+
+PyObject *
+dsaKey_has_private (dsaKey * key, PyObject * args)
+{
+ if (!PyArg_ParseTuple (args, ""))
+ return NULL;
+ if (mpz_size (key->x) == 0) {
+ Py_INCREF(Py_False);
+ return Py_False;
+ } else {
+ Py_INCREF(Py_True);
+ return Py_True;
+ }
+}
+
+PyObject *
+rsaKey_new (PyObject * self, PyObject * args)
+{
+ PyLongObject *n = NULL, *e = NULL, *d = NULL, *p = NULL, *q = NULL,
+ *u = NULL;
+ rsaKey *key;
+
+ 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, &u))
+ return NULL;
+
+ key = PyObject_New (rsaKey, &rsaKeyType);
+ mpz_init (key->n);
+ mpz_init (key->e);
+ 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)
+ {
+ return (PyObject *) key;
+ }
+ longObjToMPZ (key->d, d);
+ if (p && q)
+ {
+ longObjToMPZ (key->p, p);
+ longObjToMPZ (key->q, q);
+ if (u) {
+ longObjToMPZ (key->u, u);
+ } else {
+ mpz_invert (key->u, key->p, key->q);
+ }
+ }
+ return (PyObject *) key;
+}
+
+static void
+rsaKey_dealloc (rsaKey * key)
+{
+ mpz_clear (key->n);
+ mpz_clear (key->e);
+ mpz_clear (key->d);
+ mpz_clear (key->p);
+ mpz_clear (key->q);
+ mpz_clear (key->u);
+ PyObject_Del (key);
+}
+
+static PyObject *
+rsaKey_getattr (rsaKey * key, char *attr)
+{
+ if (strcmp (attr, "n") == 0)
+ return mpzToLongObj (key->n);
+ else if (strcmp (attr, "e") == 0)
+ return mpzToLongObj (key->e);
+ else if (strcmp (attr, "d") == 0)
+ {
+ if (mpz_size (key->d) == 0)
+ {
+ PyErr_SetString(PyExc_AttributeError,
+ "rsaKey instance has no attribute 'd'");
+ return NULL;
+ }
+ return mpzToLongObj (key->d);
+ }
+ else if (strcmp (attr, "p") == 0)
+ {
+ if (mpz_size (key->p) == 0)
+ {
+ PyErr_SetString(PyExc_AttributeError,
+ "rsaKey instance has no attribute 'p'");
+ return NULL;
+ }
+ return mpzToLongObj (key->p);
+ }
+ else if (strcmp (attr, "q") == 0)
+ {
+ if (mpz_size (key->q) == 0)
+ {
+ PyErr_SetString(PyExc_AttributeError,
+ "rsaKey instance has no attribute 'q'");
+ return NULL;
+ }
+ 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__,
+ (PyObject *) key, attr);
+ }
+}
+
+PyObject *
+rsaKey__encrypt (rsaKey * key, PyObject * args)
+{
+ PyObject *l, *r;
+ mpz_t v;
+ int result;
+ if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))
+ {
+ return NULL;
+ }
+ mpz_init (v);
+ longObjToMPZ (v, (PyLongObject *) l);
+ result = rsaEncrypt (key, v);
+ if (result == 1)
+ {
+ PyErr_SetString (fastmathError, "Plaintext too large");
+ return NULL;
+ }
+ r = (PyObject *) mpzToLongObj (v);
+ mpz_clear (v);
+ return Py_BuildValue ("N", r);
+}
+
+PyObject *
+rsaKey__decrypt (rsaKey * key, PyObject * args)
+{
+ PyObject *l, *r;
+ mpz_t v;
+ int result;
+ if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))
+ {
+ return NULL;
+ }
+ mpz_init (v);
+ longObjToMPZ (v, (PyLongObject *) l);
+ result = rsaDecrypt (key, v);
+ if (result == 1)
+ {
+ PyErr_SetString (fastmathError,
+ "Ciphertext too large");
+ return NULL;
+ }
+ else if (result == 2)
+ {
+ PyErr_SetString (fastmathError,
+ "Private key not available in this object");
+ return NULL;
+ }
+ r = mpzToLongObj (v);
+ mpz_clear (v);
+ return Py_BuildValue ("N", r);
+}
+
+PyObject *
+rsaKey__verify (rsaKey * key, PyObject * args)
+{
+ PyObject *l, *lsig;
+ mpz_t v, vsig;
+ if (!PyArg_ParseTuple(args, "O!O!",
+ &PyLong_Type, &l, &PyLong_Type, &lsig))
+ {
+ return NULL;
+ }
+ mpz_init (v);
+ mpz_init (vsig);
+ longObjToMPZ (v, (PyLongObject *) l);
+ longObjToMPZ (vsig, (PyLongObject *) lsig);
+ rsaEncrypt (key, vsig);
+ if (mpz_cmp (v, vsig) == 0) {
+ Py_INCREF(Py_True);
+ return Py_True;
+ }
+ else {
+ Py_INCREF(Py_False);
+ return Py_False;
+ }
+}
+
+PyObject *
+rsaKey__blind (rsaKey * key, PyObject * args)
+{
+ PyObject *l, *lblind, *r;
+ mpz_t v, vblind;
+ int result;
+ if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l,
+ &PyLong_Type, &lblind))
+ {
+ return NULL;
+ }
+ mpz_init (v);
+ mpz_init (vblind);
+ longObjToMPZ (v, (PyLongObject *) l);
+ longObjToMPZ (vblind, (PyLongObject *) lblind);
+ result = rsaBlind (key, v, vblind);
+ if (result == 1)
+ {
+ PyErr_SetString (fastmathError, "Message too large");
+ return NULL;
+ }
+ else if (result == 2)
+ {
+ PyErr_SetString (fastmathError, "Blinding factor too large");
+ return NULL;
+ }
+ r = (PyObject *) mpzToLongObj (v);
+ mpz_clear (v);
+ mpz_clear (vblind);
+ return Py_BuildValue ("N", r);
+}
+
+PyObject *
+rsaKey__unblind (rsaKey * key, PyObject * args)
+{
+ PyObject *l, *lblind, *r;
+ mpz_t v, vblind;
+ int result;
+ if (!PyArg_ParseTuple (args, "O!O!", &PyLong_Type, &l,
+ &PyLong_Type, &lblind))
+ {
+ return NULL;
+ }
+ mpz_init (v);
+ mpz_init (vblind);
+ longObjToMPZ (v, (PyLongObject *) l);
+ longObjToMPZ (vblind, (PyLongObject *) lblind);
+ result = rsaUnBlind (key, v, vblind);
+ if (result == 1)
+ {
+ PyErr_SetString (fastmathError, "Message too large");
+ return NULL;
+ }
+ else if (result == 2)
+ {
+ PyErr_SetString (fastmathError, "Blinding factor too large");
+ return NULL;
+ }
+ else if (result == 3)
+ {
+ PyErr_SetString (fastmathError, "Inverse doesn't exist");
+ return NULL;
+ }
+ r = (PyObject *) mpzToLongObj (v);
+ mpz_clear (v);
+ mpz_clear (vblind);
+ return Py_BuildValue ("N", r);
+}
+
+PyObject *
+rsaKey_size (rsaKey * key, PyObject * args)
+{
+ if (!PyArg_ParseTuple (args, ""))
+ return NULL;
+ return Py_BuildValue ("i", mpz_sizeinbase (key->n, 2) - 1);
+}
+
+PyObject *
+rsaKey_has_private (rsaKey * key, PyObject * args)
+{
+ if (!PyArg_ParseTuple (args, ""))
+ return NULL;
+ if (mpz_size (key->d) == 0) {
+ Py_INCREF(Py_False);
+ return Py_False;
+ } else {
+ Py_INCREF(Py_True);
+ return Py_True;
+ }
+}
+
+
+PyObject *
+isPrime (PyObject * self, PyObject * args)
+{
+ PyObject *l;
+ mpz_t n;
+ int result;
+
+ if (!PyArg_ParseTuple (args, "O!", &PyLong_Type, &l))
+ {
+ return NULL;
+ }
+ mpz_init (n);
+ longObjToMPZ (n, (PyLongObject *) l);
+
+ result = mpz_probab_prime_p(n, 5);
+
+ mpz_clear (n);
+
+ if (result == 0) {
+ Py_INCREF(Py_False);
+ return Py_False;
+ } else {
+ Py_INCREF(Py_True);
+ return Py_True;
+ }
+}
+
+
+static PyMethodDef _fastmath__methods__[] = {
+ {"dsa_construct", dsaKey_new, METH_VARARGS},
+ {"rsa_construct", rsaKey_new, METH_VARARGS},
+ {"isPrime", isPrime, METH_VARARGS},
+ {NULL, NULL}
+};
+
+void
+init_fastmath (void)
+{
+ PyObject *_fastmath_module;
+ PyObject *_fastmath_dict;
+
+ rsaKeyType.ob_type = &PyType_Type;
+ dsaKeyType.ob_type = &PyType_Type;
+ _fastmath_module = Py_InitModule ("_fastmath", _fastmath__methods__);
+ _fastmath_dict = PyModule_GetDict (_fastmath_module);
+ fastmathError = PyErr_NewException ("_fastmath.error", NULL, NULL);
+ PyDict_SetItemString (_fastmath_dict, "error", fastmathError);
+}