@@ -110,6 +110,9 @@ class error (Exception):
110110def generate (bits , randfunc , progress_func = None ):
111111 """Randomly generate a fresh, new ElGamal key.
112112
113+ The key will be safe for use for both encryption and signature
114+ (although it should be used for **only one** purpose).
115+
113116 :Parameters:
114117 bits : int
115118 Key length, or size (in bits) of the modulus *p*.
@@ -131,37 +134,48 @@ def generate(bits, randfunc, progress_func=None):
131134 :Return: An ElGamal key object (`ElGamalobj`).
132135 """
133136 obj = ElGamalobj ()
134- # Generate prime p
137+ # Generate a safe prime p
138+ # See Algorithm 4.86 in Handbook of Applied Cryptography
135139 if progress_func :
136140 progress_func ('p\n ' )
137- obj .p = bignum (getPrime (bits , randfunc ))
138- # Generate random number g
141+ while 1 :
142+ q = bignum (getPrime (bits - 1 , randfunc ))
143+ obj .p = 2 * q + 1
144+ if number .isPrime (obj .p , randfunc = randfunc ):
145+ break
146+ # Generate generator g
147+ # See Algorithm 4.80 in Handbook of Applied Cryptography
148+ # Note that the order of the group is n=p-1=2q, where q is prime
139149 if progress_func :
140150 progress_func ('g\n ' )
141- size = bits - 1 - (ord (randfunc (1 )) & 63 ) # g will be from 1--64 bits smaller than p
142- if size < 1 :
143- size = bits - 1
144- while (1 ):
145- obj .g = bignum (getPrime (size , randfunc ))
146- if obj .g < obj .p :
151+ while 1 :
152+ # We must avoid g=2 because of Bleichenbacher's attack described
153+ # in "Generating ElGamal signatures without knowning the secret key",
154+ # 1996
155+ #
156+ obj .g = number .getRandomRange (3 , obj .p , randfunc )
157+ safe = 1
158+ if pow (obj .g , 2 , obj .p )== 1 :
159+ safe = 0
160+ if safe and pow (obj .g , q , obj .p )== 1 :
161+ safe = 0
162+ # Discard g if it divides p-1 because of the attack described
163+ # in Note 11.67 (iii) in HAC
164+ if safe and divmod (obj .p - 1 , obj .g )[1 ]== 0 :
165+ safe = 0
166+ # g^{-1} must not divide p-1 because of Khadir's attack
167+ # described in "Conditions of the generator for forging ElGamal
168+ # signature", 2011
169+ ginv = number .inverse (obj .g , obj .p )
170+ if safe and divmod (obj .p - 1 , ginv )[1 ]== 0 :
171+ safe = 0
172+ if safe :
147173 break
148- size = (size + 1 ) % bits
149- if size == 0 :
150- size = 4
151- # Generate random number x
174+ # Generate private key x
152175 if progress_func :
153176 progress_func ('x\n ' )
154- while (1 ):
155- size = bits - 1 - ord (randfunc (1 )) # x will be from 1 to 256 bits smaller than p
156- if size > 2 :
157- break
158- while (1 ):
159- obj .x = bignum (getPrime (size , randfunc ))
160- if obj .x < obj .p :
161- break
162- size = (size + 1 ) % bits
163- if size == 0 :
164- size = 4
177+ obj .x = number .getRandomRange (2 , obj .p - 1 , randfunc )
178+ # Generate public key y
165179 if progress_func :
166180 progress_func ('y\n ' )
167181 obj .y = pow (obj .g , obj .x , obj .p )
@@ -326,6 +340,8 @@ def _sign(self, M, K):
326340 return (a , b )
327341
328342 def _verify (self , M , sig ):
343+ if sig [0 ]< 1 or sig [0 ]> p - 1 :
344+ return 0
329345 v1 = pow (self .y , sig [0 ], self .p )
330346 v1 = (v1 * pow (sig [0 ], sig [1 ], self .p )) % self .p
331347 v2 = pow (self .g , M , self .p )
0 commit comments