copy RSA from PyCrypto into the allmydata/ tree, we'll use it eventually

This commit is contained in:
Brian Warner 2007-08-15 17:36:39 -07:00
parent 8088044bf3
commit 6c24848797
5 changed files with 1255 additions and 1 deletions

View File

@ -85,7 +85,8 @@ setup(name='allmydata-tahoe',
packages=["allmydata", "allmydata.test", "allmydata.util",
"allmydata.scripts",
"allmydata.Crypto", "allmydata.Crypto.Cipher",
"allmydata.Crypto.Hash", "allmydata.Crypto.Util"],
"allmydata.Crypto.Hash", "allmydata.Crypto.Util",
"allmydata.Crypto.PublicKey"],
package_dir={ "allmydata": "src/allmydata",},
scripts = ["bin/allmydata-tahoe"],
package_data={ 'allmydata': ['web/*.xhtml', 'web/*.html', 'web/*.css'] },
@ -98,5 +99,7 @@ setup(name='allmydata-tahoe',
Extension("allmydata.Crypto.Hash.SHA256",
include_dirs=["src/allmydata/Crypto"],
sources=["src/allmydata/Crypto/SHA256.c"]),
Extension("allmydata.Crypto.PublicKey._fastmath",
sources=["src/allmydata/Crypto/_fastmath.c"]),
],
)

View File

@ -0,0 +1,257 @@
#
# 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

View File

@ -0,0 +1,17 @@
"""Public-key encryption and signature algorithms.
Public-key encryption uses two different keys, one for encryption and
one for decryption. The encryption key can be made public, and the
decryption key is kept private. Many public-key algorithms can also
be used to sign messages, and some can *only* be used for signatures.
Crypto.PublicKey.DSA Digital Signature Algorithm. (Signature only)
Crypto.PublicKey.ElGamal (Signing and encryption)
Crypto.PublicKey.RSA (Signing, encryption, and blinding)
Crypto.PublicKey.qNEW (Signature only)
"""
__all__ = ['RSA']
__revision__ = "$Id: __init__.py,v 1.4 2003/04/03 20:27:13 akuchling Exp $"

View File

@ -0,0 +1,173 @@
#
# 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__()

View File

@ -0,0 +1,804 @@
/*
* _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);
}