/gdata/Crypto/PublicKey/qNEW.py

http://radioappz.googlecode.com/ · Python · 170 lines · 113 code · 22 blank · 35 comment · 29 complexity · ca05375af13f05f9c8da0eb09c3a499d MD5 · raw file

  1. #
  2. # qNEW.py : The q-NEW signature algorithm.
  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. __revision__ = "$Id: qNEW.py,v 1.8 2003/04/04 15:13:35 akuchling Exp $"
  13. from Crypto.PublicKey import pubkey
  14. from Crypto.Util.number import *
  15. from Crypto.Hash import SHA
  16. class error (Exception):
  17. pass
  18. HASHBITS = 160 # Size of SHA digests
  19. def generate(bits, randfunc, progress_func=None):
  20. """generate(bits:int, randfunc:callable, progress_func:callable)
  21. Generate a qNEW key of length 'bits', using 'randfunc' to get
  22. random data and 'progress_func', if present, to display
  23. the progress of the key generation.
  24. """
  25. obj=qNEWobj()
  26. # Generate prime numbers p and q. q is a 160-bit prime
  27. # number. p is another prime number (the modulus) whose bit
  28. # size is chosen by the caller, and is generated so that p-1
  29. # is a multiple of q.
  30. #
  31. # Note that only a single seed is used to
  32. # generate p and q; if someone generates a key for you, you can
  33. # use the seed to duplicate the key generation. This can
  34. # protect you from someone generating values of p,q that have
  35. # some special form that's easy to break.
  36. if progress_func:
  37. progress_func('p,q\n')
  38. while (1):
  39. obj.q = getPrime(160, randfunc)
  40. # assert pow(2, 159L)<obj.q<pow(2, 160L)
  41. obj.seed = S = long_to_bytes(obj.q)
  42. C, N, V = 0, 2, {}
  43. # Compute b and n such that bits-1 = b + n*HASHBITS
  44. n= (bits-1) / HASHBITS
  45. b= (bits-1) % HASHBITS ; powb=2L << b
  46. powL1=pow(long(2), bits-1)
  47. while C<4096:
  48. # The V array will contain (bits-1) bits of random
  49. # data, that are assembled to produce a candidate
  50. # value for p.
  51. for k in range(0, n+1):
  52. V[k]=bytes_to_long(SHA.new(S+str(N)+str(k)).digest())
  53. p = V[n] % powb
  54. for k in range(n-1, -1, -1):
  55. p= (p << long(HASHBITS) )+V[k]
  56. p = p+powL1 # Ensure the high bit is set
  57. # Ensure that p-1 is a multiple of q
  58. p = p - (p % (2*obj.q)-1)
  59. # If p is still the right size, and it's prime, we're done!
  60. if powL1<=p and isPrime(p):
  61. break
  62. # Otherwise, increment the counter and try again
  63. C, N = C+1, N+n+1
  64. if C<4096:
  65. break # Ended early, so exit the while loop
  66. if progress_func:
  67. progress_func('4096 values of p tried\n')
  68. obj.p = p
  69. power=(p-1)/obj.q
  70. # Next parameter: g = h**((p-1)/q) mod p, such that h is any
  71. # number <p-1, and g>1. g is kept; h can be discarded.
  72. if progress_func:
  73. progress_func('h,g\n')
  74. while (1):
  75. h=bytes_to_long(randfunc(bits)) % (p-1)
  76. g=pow(h, power, p)
  77. if 1<h<p-1 and g>1:
  78. break
  79. obj.g=g
  80. # x is the private key information, and is
  81. # just a random number between 0 and q.
  82. # y=g**x mod p, and is part of the public information.
  83. if progress_func:
  84. progress_func('x,y\n')
  85. while (1):
  86. x=bytes_to_long(randfunc(20))
  87. if 0 < x < obj.q:
  88. break
  89. obj.x, obj.y=x, pow(g, x, p)
  90. return obj
  91. # Construct a qNEW object
  92. def construct(tuple):
  93. """construct(tuple:(long,long,long,long)|(long,long,long,long,long)
  94. Construct a qNEW object from a 4- or 5-tuple of numbers.
  95. """
  96. obj=qNEWobj()
  97. if len(tuple) not in [4,5]:
  98. raise error, 'argument for construct() wrong length'
  99. for i in range(len(tuple)):
  100. field = obj.keydata[i]
  101. setattr(obj, field, tuple[i])
  102. return obj
  103. class qNEWobj(pubkey.pubkey):
  104. keydata=['p', 'q', 'g', 'y', 'x']
  105. def _sign(self, M, K=''):
  106. if (self.q<=K):
  107. raise error, 'K is greater than q'
  108. if M<0:
  109. raise error, 'Illegal value of M (<0)'
  110. if M>=pow(2,161L):
  111. raise error, 'Illegal value of M (too large)'
  112. r=pow(self.g, K, self.p) % self.q
  113. s=(K- (r*M*self.x % self.q)) % self.q
  114. return (r,s)
  115. def _verify(self, M, sig):
  116. r, s = sig
  117. if r<=0 or r>=self.q or s<=0 or s>=self.q:
  118. return 0
  119. if M<0:
  120. raise error, 'Illegal value of M (<0)'
  121. if M<=0 or M>=pow(2,161L):
  122. return 0
  123. v1 = pow(self.g, s, self.p)
  124. v2 = pow(self.y, M*r, self.p)
  125. v = ((v1*v2) % self.p)
  126. v = v % self.q
  127. if v==r:
  128. return 1
  129. return 0
  130. def size(self):
  131. "Return the maximum number of bits that can be handled by this key."
  132. return 160
  133. def has_private(self):
  134. """Return a Boolean denoting whether the object contains
  135. private components."""
  136. return hasattr(self, 'x')
  137. def can_sign(self):
  138. """Return a Boolean value recording whether this algorithm can generate signatures."""
  139. return 1
  140. def can_encrypt(self):
  141. """Return a Boolean value recording whether this algorithm can encrypt data."""
  142. return 0
  143. def publickey(self):
  144. """Return a new key object containing only the public information."""
  145. return construct((self.p, self.q, self.g, self.y))
  146. object = qNEWobj