Some notes related to this assignment.
Double Password Authentication
Few things to keep in mind in this exercise (mainly with regards to
DataInputStream/DataOutputStream
class:
- You can use writeUTF to write Strings (readUTF
to read) [e.g., out.writeUTF(x)]
- You can use writeInt,
writeDouble, etc. to write Integers and
Doubles (readInt,
readDouble)
- Another way to do is to convert everything to byte arrays and use
write. Here you will need to worry about passing the
length information for each value you pass - it may be tedious
- As the digest value is a byte array, you may simply want to use
write. When you use write
to pass a byte array, reading the same array at the server requires you to
also know the size of the byte array. So before you pass the digest value, you
could pass the length of the byte array that stores the digest value (using
writeInt) and then the digest itself. At the other
end you can read the length value (using readInt)
and then use that to create the byte array that can be used to store the
appropriate size of bytes read from the input stream. Here is a sample you
could do for the digest value passed.
Client |
Server |
out.writeInt(digestValue.length);
out.write(digestValue);
out.flush();//digestValue is of type
byte[] |
int length = in.readInt();
byte[] protected = new byte[length];
in.readFully(protected);//reads the number of bytes equal to
length of protected |
- Note that you need to pass the original values (username, time value,
etc.) and the digest. At the server you have to re-compute the digest the same
way you computed the at the client side using the original values. Then, you
need to compare the digest value received from the client with the newly
computed digest. Here is one way you can check if the two digests are equal:
MessageDigest.isEqual(recomputedDigest, receivedDigest);
ElGamal Signature
Keys
-
Create a random prime number p
-
Choose g and d - both less than p
-
Calculate
y
=
g^d
mod p
-
Private key is d, public key is
(y,
g, p)
Signing message m
- Choose k that is relatively prime to (p-1)
- Compute a
= g^k
mod
p
- Compute b
= ((m-da)/k)
mod (p-1)
Verifying the signature
- Check if the following equality holds
(y^a).(a^b)
mod p
= g^m
mod p
Note "(y^a).(a^b)
mod p"
is equivalent to "[(y^a)
mod p]
[(a^b)
mod p]
mod p"
Some issues
- Since you are working with BigInteger class - be
careful. For instance, to calculate (p-1) (call it
pMinusOne), you could do the following
BigInteger pOne = BigInteger.valueOf(1);
BigInteger pMinusOne = p.substract(pOne) //
where p is the random number
- Note that k should be relatively prime to (p-1)
loop {
BigInteger k = new BigInterger (???); // check
existing code of this type
} until k is relatively prime to (p-1)
To check "BigInteger k is relatively prime to
BigInteger p" you can do the following:
k.gcd(pMinusOne).equals(pOne) ==
true;