/gdata/Crypto/PublicKey/ElGamal.py

http://radioappz.googlecode.com/ · Python · 132 lines · 114 code · 4 blank · 14 comment · 1 complexity · f5d8f8175fe8d8dcda898dc1e995c294 MD5 · raw file

  1. #
  2. # ElGamal.py : ElGamal encryption/decryption and signatures
  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: ElGamal.py,v 1.9 2003/04/04 19:44:26 akuchling Exp $"
  13. from Crypto.PublicKey.pubkey import *
  14. from Crypto.Util import number
  15. class error (Exception):
  16. pass
  17. # Generate an ElGamal key with N bits
  18. def generate(bits, randfunc, progress_func=None):
  19. """generate(bits:int, randfunc:callable, progress_func:callable)
  20. Generate an ElGamal key of length 'bits', using 'randfunc' to get
  21. random data and 'progress_func', if present, to display
  22. the progress of the key generation.
  23. """
  24. obj=ElGamalobj()
  25. # Generate prime p
  26. if progress_func:
  27. progress_func('p\n')
  28. obj.p=bignum(getPrime(bits, randfunc))
  29. # Generate random number g
  30. if progress_func:
  31. progress_func('g\n')
  32. size=bits-1-(ord(randfunc(1)) & 63) # g will be from 1--64 bits smaller than p
  33. if size<1:
  34. size=bits-1
  35. while (1):
  36. obj.g=bignum(getPrime(size, randfunc))
  37. if obj.g < obj.p:
  38. break
  39. size=(size+1) % bits
  40. if size==0:
  41. size=4
  42. # Generate random number x
  43. if progress_func:
  44. progress_func('x\n')
  45. while (1):
  46. size=bits-1-ord(randfunc(1)) # x will be from 1 to 256 bits smaller than p
  47. if size>2:
  48. break
  49. while (1):
  50. obj.x=bignum(getPrime(size, randfunc))
  51. if obj.x < obj.p:
  52. break
  53. size = (size+1) % bits
  54. if size==0:
  55. size=4
  56. if progress_func:
  57. progress_func('y\n')
  58. obj.y = pow(obj.g, obj.x, obj.p)
  59. return obj
  60. def construct(tuple):
  61. """construct(tuple:(long,long,long,long)|(long,long,long,long,long)))
  62. : ElGamalobj
  63. Construct an ElGamal key from a 3- or 4-tuple of numbers.
  64. """
  65. obj=ElGamalobj()
  66. if len(tuple) not in [3,4]:
  67. raise error, 'argument for construct() wrong length'
  68. for i in range(len(tuple)):
  69. field = obj.keydata[i]
  70. setattr(obj, field, tuple[i])
  71. return obj
  72. class ElGamalobj(pubkey):
  73. keydata=['p', 'g', 'y', 'x']
  74. def _encrypt(self, M, K):
  75. a=pow(self.g, K, self.p)
  76. b=( M*pow(self.y, K, self.p) ) % self.p
  77. return ( a,b )
  78. def _decrypt(self, M):
  79. if (not hasattr(self, 'x')):
  80. raise error, 'Private key not available in this object'
  81. ax=pow(M[0], self.x, self.p)
  82. plaintext=(M[1] * inverse(ax, self.p ) ) % self.p
  83. return plaintext
  84. def _sign(self, M, K):
  85. if (not hasattr(self, 'x')):
  86. raise error, 'Private key not available in this object'
  87. p1=self.p-1
  88. if (GCD(K, p1)!=1):
  89. raise error, 'Bad K value: GCD(K,p-1)!=1'
  90. a=pow(self.g, K, self.p)
  91. t=(M-self.x*a) % p1
  92. while t<0: t=t+p1
  93. b=(t*inverse(K, p1)) % p1
  94. return (a, b)
  95. def _verify(self, M, sig):
  96. v1=pow(self.y, sig[0], self.p)
  97. v1=(v1*pow(sig[0], sig[1], self.p)) % self.p
  98. v2=pow(self.g, M, self.p)
  99. if v1==v2:
  100. return 1
  101. return 0
  102. def size(self):
  103. "Return the maximum number of bits that can be handled by this key."
  104. return number.size(self.p) - 1
  105. def has_private(self):
  106. """Return a Boolean denoting whether the object contains
  107. private components."""
  108. if hasattr(self, 'x'):
  109. return 1
  110. else:
  111. return 0
  112. def publickey(self):
  113. """Return a new key object containing only the public information."""
  114. return construct((self.p, self.g, self.y))
  115. object=ElGamalobj