OLD | NEW |
(Empty) | |
| 1 # -*- coding: utf-8 -*- |
| 2 # |
| 3 # PubKey/RSA/_slowmath.py : Pure Python implementation of the RSA portions of _
fastmath |
| 4 # |
| 5 # Written in 2008 by Dwayne C. Litzenberger <dlitz@dlitz.net> |
| 6 # |
| 7 # =================================================================== |
| 8 # The contents of this file are dedicated to the public domain. To |
| 9 # the extent that dedication to the public domain is not available, |
| 10 # everyone is granted a worldwide, perpetual, royalty-free, |
| 11 # non-exclusive license to exercise all rights associated with the |
| 12 # contents of this file for any purpose whatsoever. |
| 13 # No rights are reserved. |
| 14 # |
| 15 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 16 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 17 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 18 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 19 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 20 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 21 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 22 # SOFTWARE. |
| 23 # =================================================================== |
| 24 |
| 25 """Pure Python implementation of the RSA-related portions of Crypto.PublicKey._f
astmath.""" |
| 26 |
| 27 __revision__ = "$Id$" |
| 28 |
| 29 __all__ = ['rsa_construct'] |
| 30 |
| 31 import sys |
| 32 |
| 33 if sys.version_info[0] == 2 and sys.version_info[1] == 1: |
| 34 from Crypto.Util.py21compat import * |
| 35 from Crypto.Util.number import size, inverse, GCD |
| 36 |
| 37 class error(Exception): |
| 38 pass |
| 39 |
| 40 class _RSAKey(object): |
| 41 def _blind(self, m, r): |
| 42 # compute r**e * m (mod n) |
| 43 return m * pow(r, self.e, self.n) |
| 44 |
| 45 def _unblind(self, m, r): |
| 46 # compute m / r (mod n) |
| 47 return inverse(r, self.n) * m % self.n |
| 48 |
| 49 def _decrypt(self, c): |
| 50 # compute c**d (mod n) |
| 51 if not self.has_private(): |
| 52 raise TypeError("No private key") |
| 53 if (hasattr(self,'p') and hasattr(self,'q') and hasattr(self,'u')): |
| 54 m1 = pow(c, self.d % (self.p-1), self.p) |
| 55 m2 = pow(c, self.d % (self.q-1), self.q) |
| 56 h = m2 - m1 |
| 57 if (h<0): |
| 58 h = h + self.q |
| 59 h = h*self.u % self.q |
| 60 return h*self.p+m1 |
| 61 return pow(c, self.d, self.n) |
| 62 |
| 63 def _encrypt(self, m): |
| 64 # compute m**d (mod n) |
| 65 return pow(m, self.e, self.n) |
| 66 |
| 67 def _sign(self, m): # alias for _decrypt |
| 68 if not self.has_private(): |
| 69 raise TypeError("No private key") |
| 70 return self._decrypt(m) |
| 71 |
| 72 def _verify(self, m, sig): |
| 73 return self._encrypt(sig) == m |
| 74 |
| 75 def has_private(self): |
| 76 return hasattr(self, 'd') |
| 77 |
| 78 def size(self): |
| 79 """Return the maximum number of bits that can be encrypted""" |
| 80 return size(self.n) - 1 |
| 81 |
| 82 def rsa_construct(n, e, d=None, p=None, q=None, u=None): |
| 83 """Construct an RSAKey object""" |
| 84 assert isinstance(n, long) |
| 85 assert isinstance(e, long) |
| 86 assert isinstance(d, (long, type(None))) |
| 87 assert isinstance(p, (long, type(None))) |
| 88 assert isinstance(q, (long, type(None))) |
| 89 assert isinstance(u, (long, type(None))) |
| 90 obj = _RSAKey() |
| 91 obj.n = n |
| 92 obj.e = e |
| 93 if d is None: |
| 94 return obj |
| 95 obj.d = d |
| 96 if p is not None and q is not None: |
| 97 obj.p = p |
| 98 obj.q = q |
| 99 else: |
| 100 # Compute factors p and q from the private exponent d. |
| 101 # We assume that n has no more than two factors. |
| 102 # See 8.2.2(i) in Handbook of Applied Cryptography. |
| 103 ktot = d*e-1 |
| 104 # The quantity d*e-1 is a multiple of phi(n), even, |
| 105 # and can be represented as t*2^s. |
| 106 t = ktot |
| 107 while t%2==0: |
| 108 t=divmod(t,2)[0] |
| 109 # Cycle through all multiplicative inverses in Zn. |
| 110 # The algorithm is non-deterministic, but there is a 50% chance |
| 111 # any candidate a leads to successful factoring. |
| 112 # See "Digitalized Signatures and Public Key Functions as Intractable |
| 113 # as Factorization", M. Rabin, 1979 |
| 114 spotted = 0 |
| 115 a = 2 |
| 116 while not spotted and a<100: |
| 117 k = t |
| 118 # Cycle through all values a^{t*2^i}=a^k |
| 119 while k<ktot: |
| 120 cand = pow(a,k,n) |
| 121 # Check if a^k is a non-trivial root of unity (mod n) |
| 122 if cand!=1 and cand!=(n-1) and pow(cand,2,n)==1: |
| 123 # We have found a number such that (cand-1)(cand+1)=0 (mod n
). |
| 124 # Either of the terms divides n. |
| 125 obj.p = GCD(cand+1,n) |
| 126 spotted = 1 |
| 127 break |
| 128 k = k*2 |
| 129 # This value was not any good... let's try another! |
| 130 a = a+2 |
| 131 if not spotted: |
| 132 raise ValueError("Unable to compute factors p and q from exponent d.
") |
| 133 # Found ! |
| 134 assert ((n % obj.p)==0) |
| 135 obj.q = divmod(n,obj.p)[0] |
| 136 if u is not None: |
| 137 obj.u = u |
| 138 else: |
| 139 obj.u = inverse(obj.p, obj.q) |
| 140 return obj |
| 141 |
| 142 class _DSAKey(object): |
| 143 def size(self): |
| 144 """Return the maximum number of bits that can be encrypted""" |
| 145 return size(self.p) - 1 |
| 146 |
| 147 def has_private(self): |
| 148 return hasattr(self, 'x') |
| 149 |
| 150 def _sign(self, m, k): # alias for _decrypt |
| 151 # SECURITY TODO - We _should_ be computing SHA1(m), but we don't because
that's the API. |
| 152 if not self.has_private(): |
| 153 raise TypeError("No private key") |
| 154 if not (1L < k < self.q): |
| 155 raise ValueError("k is not between 2 and q-1") |
| 156 inv_k = inverse(k, self.q) # Compute k**-1 mod q |
| 157 r = pow(self.g, k, self.p) % self.q # r = (g**k mod p) mod q |
| 158 s = (inv_k * (m + self.x * r)) % self.q |
| 159 return (r, s) |
| 160 |
| 161 def _verify(self, m, r, s): |
| 162 # SECURITY TODO - We _should_ be computing SHA1(m), but we don't because
that's the API. |
| 163 if not (0 < r < self.q) or not (0 < s < self.q): |
| 164 return False |
| 165 w = inverse(s, self.q) |
| 166 u1 = (m*w) % self.q |
| 167 u2 = (r*w) % self.q |
| 168 v = (pow(self.g, u1, self.p) * pow(self.y, u2, self.p) % self.p) % self.
q |
| 169 return v == r |
| 170 |
| 171 def dsa_construct(y, g, p, q, x=None): |
| 172 assert isinstance(y, long) |
| 173 assert isinstance(g, long) |
| 174 assert isinstance(p, long) |
| 175 assert isinstance(q, long) |
| 176 assert isinstance(x, (long, type(None))) |
| 177 obj = _DSAKey() |
| 178 obj.y = y |
| 179 obj.g = g |
| 180 obj.p = p |
| 181 obj.q = q |
| 182 if x is not None: obj.x = x |
| 183 return obj |
| 184 |
| 185 |
| 186 # vim:set ts=4 sw=4 sts=4 expandtab: |
| 187 |
OLD | NEW |