/gdata/Crypto/PublicKey/RSA.py
http://radioappz.googlecode.com/ · Python · 256 lines · 179 code · 41 blank · 36 comment · 26 complexity · dfa2af03e881af60bd2ca69b3a78cc85 MD5 · raw file
- #
- # 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 Crypto.PublicKey import pubkey
- from Crypto.Util import number
- try:
- from Crypto.PublicKey import _fastmath
- except ImportError:
- _fastmath = None
- 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