PageRenderTime 36ms CodeModel.GetById 1ms app.highlight 28ms RepoModel.GetById 1ms app.codeStats 1ms

/gdata/Crypto/PublicKey/RSA.py

http://radioappz.googlecode.com/
Python | 256 lines | 236 code | 7 blank | 13 comment | 3 complexity | dfa2af03e881af60bd2ca69b3a78cc85 MD5 | raw file
  1#
  2#   RSA.py : RSA encryption/decryption
  3#
  4#  Part of the Python Cryptography Toolkit
  5#
  6# Distribute and use freely; there are no restrictions on further
  7# dissemination and usage except those imposed by the laws of your
  8# country of residence.  This software is provided "as is" without
  9# warranty of fitness for use or suitability for any purpose, express
 10# or implied. Use at your own risk or not at all.
 11#
 12
 13__revision__ = "$Id: RSA.py,v 1.20 2004/05/06 12:52:54 akuchling Exp $"
 14
 15from Crypto.PublicKey import pubkey
 16from Crypto.Util import number
 17
 18try:
 19    from Crypto.PublicKey import _fastmath
 20except ImportError:
 21    _fastmath = None
 22
 23class error (Exception):
 24    pass
 25
 26def generate(bits, randfunc, progress_func=None):
 27    """generate(bits:int, randfunc:callable, progress_func:callable)
 28
 29    Generate an RSA key of length 'bits', using 'randfunc' to get
 30    random data and 'progress_func', if present, to display
 31    the progress of the key generation.
 32    """
 33    obj=RSAobj()
 34
 35    # Generate the prime factors of n
 36    if progress_func:
 37        progress_func('p,q\n')
 38    p = q = 1L
 39    while number.size(p*q) < bits:
 40        p = pubkey.getPrime(bits/2, randfunc)
 41        q = pubkey.getPrime(bits/2, randfunc)
 42
 43    # p shall be smaller than q (for calc of u)
 44    if p > q:
 45        (p, q)=(q, p)
 46    obj.p = p
 47    obj.q = q
 48
 49    if progress_func:
 50        progress_func('u\n')
 51    obj.u = pubkey.inverse(obj.p, obj.q)
 52    obj.n = obj.p*obj.q
 53
 54    obj.e = 65537L
 55    if progress_func:
 56        progress_func('d\n')
 57    obj.d=pubkey.inverse(obj.e, (obj.p-1)*(obj.q-1))
 58
 59    assert bits <= 1+obj.size(), "Generated key is too small"
 60
 61    return obj
 62
 63def construct(tuple):
 64    """construct(tuple:(long,) : RSAobj
 65    Construct an RSA object from a 2-, 3-, 5-, or 6-tuple of numbers.
 66    """
 67
 68    obj=RSAobj()
 69    if len(tuple) not in [2,3,5,6]:
 70        raise error, 'argument for construct() wrong length'
 71    for i in range(len(tuple)):
 72        field = obj.keydata[i]
 73        setattr(obj, field, tuple[i])
 74    if len(tuple) >= 5:
 75        # Ensure p is smaller than q 
 76        if obj.p>obj.q:
 77            (obj.p, obj.q)=(obj.q, obj.p)
 78
 79    if len(tuple) == 5:
 80        # u not supplied, so we're going to have to compute it.
 81        obj.u=pubkey.inverse(obj.p, obj.q)
 82
 83    return obj
 84
 85class RSAobj(pubkey.pubkey):
 86    keydata = ['n', 'e', 'd', 'p', 'q', 'u']
 87    def _encrypt(self, plaintext, K=''):
 88        if self.n<=plaintext:
 89            raise error, 'Plaintext too large'
 90        return (pow(plaintext, self.e, self.n),)
 91
 92    def _decrypt(self, ciphertext):
 93        if (not hasattr(self, 'd')):
 94            raise error, 'Private key not available in this object'
 95        if self.n<=ciphertext[0]:
 96            raise error, 'Ciphertext too large'
 97        return pow(ciphertext[0], self.d, self.n)
 98
 99    def _sign(self, M, K=''):
100        return (self._decrypt((M,)),)
101
102    def _verify(self, M, sig):
103        m2=self._encrypt(sig[0])
104        if m2[0]==M:
105            return 1
106        else: return 0
107
108    def _blind(self, M, B):
109        tmp = pow(B, self.e, self.n)
110        return (M * tmp) % self.n
111
112    def _unblind(self, M, B):
113        tmp = pubkey.inverse(B, self.n)
114        return  (M * tmp) % self.n
115
116    def can_blind (self):
117        """can_blind() : bool
118        Return a Boolean value recording whether this algorithm can
119        blind data.  (This does not imply that this
120        particular key object has the private information required to
121        to blind a message.)
122        """
123        return 1
124
125    def size(self):
126        """size() : int
127        Return the maximum number of bits that can be handled by this key.
128        """
129        return number.size(self.n) - 1
130
131    def has_private(self):
132        """has_private() : bool
133        Return a Boolean denoting whether the object contains
134        private components.
135        """
136        if hasattr(self, 'd'):
137            return 1
138        else: return 0
139
140    def publickey(self):
141        """publickey(): RSAobj
142        Return a new key object containing only the public key information.
143        """
144        return construct((self.n, self.e))
145
146class RSAobj_c(pubkey.pubkey):
147    keydata = ['n', 'e', 'd', 'p', 'q', 'u']
148
149    def __init__(self, key):
150        self.key = key
151
152    def __getattr__(self, attr):
153        if attr in self.keydata:
154            return getattr(self.key, attr)
155        else:
156            if self.__dict__.has_key(attr):
157                self.__dict__[attr]
158            else:
159                raise AttributeError, '%s instance has no attribute %s' % (self.__class__, attr)
160
161    def __getstate__(self):
162        d = {}
163        for k in self.keydata:
164            if hasattr(self.key, k):
165                d[k]=getattr(self.key, k)
166        return d
167
168    def __setstate__(self, state):
169        n,e = state['n'], state['e']
170        if not state.has_key('d'):
171            self.key = _fastmath.rsa_construct(n,e)
172        else:
173            d = state['d']
174            if not state.has_key('q'):
175                self.key = _fastmath.rsa_construct(n,e,d)
176            else:
177                p, q, u = state['p'], state['q'], state['u']
178                self.key = _fastmath.rsa_construct(n,e,d,p,q,u)
179
180    def _encrypt(self, plain, K):
181        return (self.key._encrypt(plain),)
182
183    def _decrypt(self, cipher):
184        return self.key._decrypt(cipher[0])
185
186    def _sign(self, M, K):
187        return (self.key._sign(M),)
188
189    def _verify(self, M, sig):
190        return self.key._verify(M, sig[0])
191
192    def _blind(self, M, B):
193        return self.key._blind(M, B)
194
195    def _unblind(self, M, B):
196        return self.key._unblind(M, B)
197
198    def can_blind (self):
199        return 1
200
201    def size(self):
202        return self.key.size()
203
204    def has_private(self):
205        return self.key.has_private()
206
207    def publickey(self):
208        return construct_c((self.key.n, self.key.e))
209
210def generate_c(bits, randfunc, progress_func = None):
211    # Generate the prime factors of n
212    if progress_func:
213        progress_func('p,q\n')
214
215    p = q = 1L
216    while number.size(p*q) < bits:
217        p = pubkey.getPrime(bits/2, randfunc)
218        q = pubkey.getPrime(bits/2, randfunc)
219
220    # p shall be smaller than q (for calc of u)
221    if p > q:
222        (p, q)=(q, p)
223    if progress_func:
224        progress_func('u\n')
225    u=pubkey.inverse(p, q)
226    n=p*q
227
228    e = 65537L
229    if progress_func:
230        progress_func('d\n')
231    d=pubkey.inverse(e, (p-1)*(q-1))
232    key = _fastmath.rsa_construct(n,e,d,p,q,u)
233    obj = RSAobj_c(key)
234
235##    print p
236##    print q
237##    print number.size(p), number.size(q), number.size(q*p),
238##    print obj.size(), bits
239    assert bits <= 1+obj.size(), "Generated key is too small"
240    return obj
241
242
243def construct_c(tuple):
244    key = apply(_fastmath.rsa_construct, tuple)
245    return RSAobj_c(key)
246
247object = RSAobj
248
249generate_py = generate
250construct_py = construct
251
252if _fastmath:
253    #print "using C version of RSA"
254    generate = generate_c
255    construct = construct_c
256    error = _fastmath.error