OLD | NEW |
(Empty) | |
| 1 |
| 2 # |
| 3 # DSA.py : Digital Signature Algorithm |
| 4 # |
| 5 # Part of the Python Cryptography Toolkit |
| 6 # |
| 7 # Written by Andrew Kuchling, Paul Swartz, and others |
| 8 # |
| 9 # =================================================================== |
| 10 # The contents of this file are dedicated to the public domain. To |
| 11 # the extent that dedication to the public domain is not available, |
| 12 # everyone is granted a worldwide, perpetual, royalty-free, |
| 13 # non-exclusive license to exercise all rights associated with the |
| 14 # contents of this file for any purpose whatsoever. |
| 15 # No rights are reserved. |
| 16 # |
| 17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 18 # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 19 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 20 # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS |
| 21 # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN |
| 22 # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
| 23 # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
| 24 # SOFTWARE. |
| 25 # =================================================================== |
| 26 # |
| 27 |
| 28 __revision__ = "$Id$" |
| 29 |
| 30 from Crypto.PublicKey.pubkey import * |
| 31 from Crypto.Util import number |
| 32 from Crypto.Util.number import bytes_to_long, long_to_bytes |
| 33 from Crypto.Hash import SHA |
| 34 from Crypto.Util.py3compat import * |
| 35 |
| 36 class error (Exception): |
| 37 pass |
| 38 |
| 39 def generateQ(randfunc): |
| 40 S=randfunc(20) |
| 41 hash1=SHA.new(S).digest() |
| 42 hash2=SHA.new(long_to_bytes(bytes_to_long(S)+1)).digest() |
| 43 q = bignum(0) |
| 44 for i in range(0,20): |
| 45 c=bord(hash1[i])^bord(hash2[i]) |
| 46 if i==0: |
| 47 c=c | 128 |
| 48 if i==19: |
| 49 c= c | 1 |
| 50 q=q*256+c |
| 51 while (not isPrime(q)): |
| 52 q=q+2 |
| 53 if pow(2,159L) < q < pow(2,160L): |
| 54 return S, q |
| 55 raise RuntimeError('Bad q value generated') |
| 56 |
| 57 def generate_py(bits, randfunc, progress_func=None): |
| 58 """generate(bits:int, randfunc:callable, progress_func:callable) |
| 59 |
| 60 Generate a DSA key of length 'bits', using 'randfunc' to get |
| 61 random data and 'progress_func', if present, to display |
| 62 the progress of the key generation. |
| 63 """ |
| 64 |
| 65 if bits<160: |
| 66 raise ValueError('Key length < 160 bits') |
| 67 obj=DSAobj() |
| 68 # Generate string S and prime q |
| 69 if progress_func: |
| 70 progress_func('p,q\n') |
| 71 while (1): |
| 72 S, obj.q = generateQ(randfunc) |
| 73 n=divmod(bits-1, 160)[0] |
| 74 C, N, V = 0, 2, {} |
| 75 b=(obj.q >> 5) & 15 |
| 76 powb=pow(bignum(2), b) |
| 77 powL1=pow(bignum(2), bits-1) |
| 78 while C<4096: |
| 79 for k in range(0, n+1): |
| 80 V[k]=bytes_to_long(SHA.new(S+bstr(N)+bstr(k)).digest()) |
| 81 W=V[n] % powb |
| 82 for k in range(n-1, -1, -1): |
| 83 W=(W<<160L)+V[k] |
| 84 X=W+powL1 |
| 85 p=X-(X%(2*obj.q)-1) |
| 86 if powL1<=p and isPrime(p): |
| 87 break |
| 88 C, N = C+1, N+n+1 |
| 89 if C<4096: |
| 90 break |
| 91 if progress_func: |
| 92 progress_func('4096 multiples failed\n') |
| 93 |
| 94 obj.p = p |
| 95 power=divmod(p-1, obj.q)[0] |
| 96 if progress_func: |
| 97 progress_func('h,g\n') |
| 98 while (1): |
| 99 h=bytes_to_long(randfunc(bits)) % (p-1) |
| 100 g=pow(h, power, p) |
| 101 if 1<h<p-1 and g>1: |
| 102 break |
| 103 obj.g=g |
| 104 if progress_func: |
| 105 progress_func('x,y\n') |
| 106 while (1): |
| 107 x=bytes_to_long(randfunc(20)) |
| 108 if 0 < x < obj.q: |
| 109 break |
| 110 obj.x, obj.y = x, pow(g, x, p) |
| 111 return obj |
| 112 |
| 113 class DSAobj: |
| 114 pass |
| 115 |
OLD | NEW |