Prerequisites:
- Cyclic Groups
- Discrete Logarithm Problem
- ElGamal Encryption System
ElGamal Signature Scheme is a Signature Authentication Algorithm, with the security level as same as that of Discrete Logarithm (DLP), we will see this as we move forward.
For illustrative purposes, we will consider Alice
as the signer and Bob
as the verifier.
There are different steps involved while signing or verifying data/signatures respectively with ElGamal, let's list them first and then study each of them in detail:
- Key Generation: Alice generates a pair of public and private keys. Shares the public key
(g, y, p)
. - Signature Generation: Alice uses her private key to generate the signature of a message
m
with the help of another variabler
(r
is public). Shares signatures
,r
, andm
. - Signature Verification: Bob then uses Alice's public key to do computation on
s
and checks if it matches withHash(m)
, if yes then the signature is valid, otherwise it isn't.
This step is done by the signer- Alice. Alice's Public and Private keys are generated using the following steps:
- Selects a Cyclic Group
G
of orderp
and generatorg
- Chooses a random integer
x
such that1 < x < p-2
.x
is the private key. - Calculates
- Shares
y
,p
,g
as public key
Here is a python-2.7 implementation of the above step:
def key_gen(bit_size):
p = getPrime(bit_size)
g = 2
x = random.randint(2, p-3)
y = pow(g, x, p)
return (y, p, g)
In this step, Alice does the following:
- Selects a random integer
k
such that1 < k < p-2
andGCD(k, p-1) = 1
- Calculates
r
as: - Calculates hash of the message
m
to be signed asH(m)
, whereH()
is a secure hashing algorithm agreed upon by both signer and verifier. - Calculates signature
s
as - Shares
r
,s
,m
Here is a python-2.7 implementation of the above step: (Please note that the below example is only for illustrative purposes; md5 should not be used as a hash function)
def sign(message, y, p, g):
h = hashlib.md5(message).hexdigest()
while True:
k = random.randint(2, p-2)
if GCD(k, p-1) == 1:
break
r = pow(g, k, p)
s = ((h-(x*r))*inverse(k, p-1)) % (p-1)
return (r, s, message)
Bob, after receiving public key and signature values, computes the following for verification:
- Computes H(m)
- Checks if
, if it is True, then the signature is successfully verified, if not, then the oracle throws an Exception
- Proof
Here is a python-2.7 implementation of the above step:
def verify(message, s, r, y, p, g):
try:
assert r > 0 and r < p
assert s > 0 and s < p-1
h = hashlib.md5(message).hexdigest()
assert pow(g, h, p) == (pow(r, s, p)*pow(y, r, p)) % p
print "Signature successfully verified!"
except:
raise VerificationError("Invalid Signature!")
Check out a trivial implementation/example of ElGamal Signature signing and verification here- example.py