Write a program to demonstrate the use of hashing using MD5 and SHA scheme and the
MessageDigest class. i haven’t done java i really need to get this project done
i attached the the files thanks
CSCE 4550/ 5550 Introduction to Computer Security
Final Project
Total Points: 150
Due Date: Dec 6, 2013
1. Message Digest [25 Points]
Write a program to demonstrate the use of hashing using MD5 and SHA scheme and the
MessageDigest class.
Your program should allow a user to enter a string; the program then hashes it and output
the result.
You will need to consult Java API documentation to learn how to use java classes. You
can download and install the documentation yourself, or you can access them from this
URL: http://java.sun.com/j2se/1.4.2/docs/api/index.html
2. Various Crypto Techniques [125 Points]
The objective of this exercise is to use Java features to write some security mechanisms
that can be used in applications. You will be using the classes from Java Cryptographic
Extension to implement them.
You will need to consult Java API documentation. You can download and install the
documentation yourself, or you can access them from this URL:
http://java.sun.com/j2se/1.4.2/docs/api/index.html
Java books that you can reference
Inside Java 2 Platform Security, 2nd Edition, L. Gong, G. Ellision, M. Dageforde
Java Security, Scott Oaks, O’Reilly
For each part of the assignment, skeleton Java code has been provided. These skeletons
will NOT compile. You will need to make modifications on them before they can be
successfully compiled and run.
A) Authentication
For the first part of the assignment, you should use the skeleton Java code to implement
double-strength password login using message digest. The following diagram illustrates
the double strength password.
Note that you need to generate 2 random numbers and 2 timestamps.
There are three classes defined:
Protection, which provides three functions makeBytes, makeDigest (version 1),
and makeDigest (version 2).
o makeBytes takes in a long integer and a double, then converts them into a
single byte array. makeBytes has already been implemented for you.
o makeDigest (version 1) takes in a byte array, a timestamp, and a random
number, then generates a digest using SHA. This function has already
been implemented for you.
o makeDigest (version 2) takes in a user name, a password, a timestamp,
and
a random number, then generates a digest using SHA. You need to
implement this function. You may have to consult MessageDigest API in
the documentation.
ProtectedClient, which implements the client. There are two functions: main and
sendAuthentication.
o main is the starting point of the client program and has already been
implemented for you. Make sure the host variable is set to the correct
server address (it is currently set to cse.unt.edu).
o sendAuthentication is the function that you need to implement. It takes in
user name, password, and an output stream as the function inputs. In this
function, you should implement double-strength password authentication
and send to the server by writing to the variable ‘out’. Consult
DataOutputStream API on how to write different data types to ‘out’.
ProtectedServer, which implements the server. There are three functions: main,
lookupPassword, and authenticate.
o main is the starting point of the server program and has already been
implemented for you. It creates a server process that waits for an
incoming connection. Once a connection is established, authenticate is
called to authenticate the user. If the user successfully authenticate, your
program should print out “Client logged in.”
o lookupPassword, which simply returns the password of the user stored on
the server.
o authenticate is the function which you need to implement to authenticate
the user trying to log in. Consult DataInputStream API on how to read
data from the ‘in’ stream. The function should return either true or false
depending on whether the user is authenticated.
B) Signature
In this part of the assignment, you are to implement the ElGamal Signature scheme
described below.
The ElGamal Signature scheme is similar to the Diffie-Hellman scheme. It relies on the
difficulty of solving the discrete logarithm problem. Choose a prime p and two random
numbers g and d both less than p. Compute y = gd mod p. The public key is the triplet (y,
g, p); the private key is d.
Suppose Alice wants to send Bob a signed contract m. She chooses a number k that is
relatively prime to p – 1 and has not been used before. She computes a = mk mod p and
then uses the Extended Euclidean Algorithm to find b such that
m = (da + kb) mod p – 1
The pair (a, b) is the signature.
To verify the signature, check that yaab mod p = gm mod p
EXAMPLE: Alice and Bob decide to use the El Gamal digital signature scheme. Alice
chooses p = 29, g = 3, and dAlice = 6, yielding y = 4. She wants to send Bob the signed
contract X (23). She chooses k = 5, which is relatively prime to 28. She computes
a = 35 mod 29 = 11
and then uses the Extended Euclidean Algorithm to solve for b:
23 = (6 x 11 + 5 x b) mod 28
This yields b = 25. She sends Bob the message m = 23 and the signature (11, 25).
Bob obtains the message and wants to verify the signature. He computes
yaab mod p = 4111125 mod 29 = 8
and
gm mod p = 323 mod 29 = 8
Because the two match, Alice signed the message.
If someone learns k, the corresponding message m, and the signature (a, b), then she can
use the Extended Euclidean Algorithm to recover x, Alice’s public key.
EXAMPLE: Bob happens to learn that Alice signed the last message using k = 5. He
immediately solves the following equation for d:
m = (da + kb) mod p – 1 →23 = (11d + 5 x 25) mod 28
which yields d = 6. This is Alice’s private key.
There are two classes in this assignment, ElGamalAlice and ElGamalBob, corresponding
to the sender (Alice) and the receiver (Bob). The main functions for both the classes have
been written for you. Your assignment is to write various functions that implement
ElGamal key generation and signature creation algorithms (for Alice), and signature
verification algorithm (for Bob). The functions you have to implement are indicated in
the source files.
C) Encryption
In this part of the assignment, the client program CipherClient should (1) generate a DES
key and stores the key in a file, (2) encrypts the given String object using that key and
sends the encrypted object over the socket to the server. The server program
CipherServer then uses the key that was previously generated by the client to decrypt the
incoming object. The server obtains the key simply by reading it from the same file that
the client previously generated. The server should then print out the decrypted message.
For this part of the assignment, you will need to consult external sources and
documentations on how to generate a DES key, write to or read from a file, and perform
encryption/decryption of an object.
Most of the needed information should be available at:
http://java.sun.com/products/jce/doc/guide/API_users_guide.html
D) Public-Key System
In this part of the assignment, you will need to demonstrate the use of RSA Public-key
system to exchange messages that achieve confidentiality and integrity/authentication as
well as the combination of both. You can assume a simple way of sharing public keys
between the two communicating parties. You can reuse the basic code provided for above
for this assignment.
E) X.509 certificates
In this part of the assignment, you will need to demonstrate the use of X.509 certificate to
exchange messages that achieve confidentiality. The client loads the server’s certificate
and proceeds to verify its authenticity and validity. This includes checking the expiration
date and verifying if the certificate was signed using the private key that corresponds to
the specified public key. Also, you need to print the content of the certificate you
received. If the certificate received is valid, proceed to exchange confidential messages
between the two parties. You can reuse the code previously provided for part C.
You will need to create an X.509 certificate for the Server, using RSA as the key
generation algorithm. This certificate can be self-signed and it should have your name.
You can use keytool for this purpose. keytool is installed as part of the standard Java
SDK/Runtime library, and is located in its bin subfolder. Refer to the keytool’s
documentation for further instructions.
http://download.oracle.com/javase/1.5.0/docs/tooldocs/windows/keytool.html
Finally, answer these questions in the report.
What are the limitations of using self-signed certificates? What are they useful for?
Project Submission: Submit a single ZIP file with your UNT email ID as its filename
via the Blackboard system. The package should contain all your source files and a
readme file including the answers to the above questions. You also need to demonstrate
your programs to the TA in person, where you may be asked to explain about different
parts of your code. The date for demo will be announced later.
ProjectHints
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-1) mod (p-1)
Where k-1 is computed as follows: k-1 =k.modInverse(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;
Cipher
Three things to do here.
1. Generating DES Key
The link provided in the question sheet has information and examples regarding how to
create one. Some Classes that you need to understand are
Key and KeyGenerator
check out getInstance(??), init(new SecureRandom()) and generateKey()
functions of class KeyGenerator.
2. Storing keys in a file
You could do it a number of ways. Here is one:
ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream(“KeyFile.xx”));
That is, you create an object output stream to an output file name KeyFile.xx.
Since it is an object output stream you can now write the Key object that has your key. Assuming
you have
Key k = …. // creates the key using the KeyGenerator object that is using some instance of
encryption algorithm, DES here.
out.writeObject(k); // will store your key object in the file.
At the server, you can now do:
Key k = (Key) in.readObject(); // to read from object in which is an ObjectInputStream
You can use an ObjectOutputStream object to also communicate to the server. However,
instead of a file (through FileOutputStream), you now need to associate the socket ( it is
given) with the ObjectOutputStream object. If s is the Socket object you have created
then you can do the following:
ObjectOutputStream outSocket = new ObjectOutputStream(s.getOutputStream());
Note that Socket objects are used to form a communication channel to another machine
by associating with it a port and the host address.
2. Cipher – Encrypting and Decrypting and then outputting the digest
To encrypt a message using Cipher class using a DES algorithm you can do the
following.
Cipher cipher = Cipher.getInstance(“DES/ECB/PKCS5Padding”);
cipher.init(Cipher.ENCRYPT_MODE, k);
This sets the cipher object to Encrypt mode with the specified key k (a Key object). You can do
the same two statements in the server to initialize a cipher object to Cipher.DECRYPT_MODE
You can now use the CipherOutputStream (CipherInputStream in server)
Note that in the documentation at the URL provided to you sey the following about the
CipherOutputStream class:
A CipherOutputStream is composed of an OutputStream and a Cipher so that write() methods
first process the data before writing them out to the underlying OutputStream. The cipher must
be fully initialized before being used by a CipherOutputStream.
For example, if the cipher is initialized for encryption, the CipherOutputStream will attempt to
encrypt data before writing out the encrypted data.
Hence, you can create a CipherOutputStream object to pass the encrypted value to the server.
You can now easily create an CipherOutputStream object:
CipherOutputStream cipherOut = new CipherOutputStream(sSocket, cipher);
Now you can use cipherOut.write(byte []) to send the message encrypted using DES to the server
– as cipherOut is now associated with sSocket object. Note that the input to the write function is a
byte stream so if you have a String message you need to get the bytes.
On the Server side, you can use “CipherInputStream cipherIn = ..” (similar to
CipherInputStream) and then use cipherIn.read() to read the message bytes.
Final Project Skeleton/CipherClient.java
Final Project Skeleton/CipherClient.java
import
java
.
io
.
*
;
import
java
.
net
.
*
;
import
java
.
security
.
*
;
import
javax
.
crypto
.
*
;
public
class
CipherClient
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
message
=
“The quick brown fox jumps over the lazy dog.”
;
String
host
=
“paradox.sis.pitt.edu”
;
int
port
=
7999
;
Socket
s
=
new
Socket
(
host
,
port
);
// YOU NEED TO DO THESE STEPS:
// -Generate a DES key.
// -Store it in a file.
// -Use the key to encrypt the message above and send it over socket s to the server.
}
}
Final Project Skeleton/CipherServer.java
Final Project Skeleton/CipherServer.java
import
java
.
io
.
*
;
import
java
.
net
.
*
;
import
java
.
security
.
*
;
import
javax
.
crypto
.
*
;
public
class
CipherServer
{
public
static
void
main
(
String
[]
args
)
throws
Exception
{
int
port
=
7999
;
ServerSocket
server
=
new
ServerSocket
(
port
);
Socket
s
=
server
.
accept
();
// YOU NEED TO DO THESE STEPS:
// -Read the key from the file generated by the client.
// -Use the key to decrypt the incoming message from socket s.
// -Print out the decrypt String to see if it matches the orignal message.
}
}
Final Project Skeleton/ElGamalAlice.java
Final Project Skeleton/ElGamalAlice.java
import
java
.
io
.
*
;
import
java
.
net
.
*
;
import
java
.
security
.
*
;
import
java
.
math
.
BigInteger
;
public
class
ElGamalAlice
{
private
static
BigInteger
computeY
(
BigInteger
p
,
BigInteger
g
,
BigInteger
d
)
{
// IMPLEMENT THIS FUNCTION;
}
private
static
BigInteger
computeK
(
BigInteger
p
)
{
// IMPLEMENT THIS FUNCTION;
}
private
static
BigInteger
computeA
(
BigInteger
p
,
BigInteger
g
,
BigInteger
k
)
{
// IMPLEMENT THIS FUNCTION;
}
private
static
BigInteger
computeB
(
String
message
,
BigInteger
d
,
BigInteger
a
,
BigInteger
k
,
BigInteger
p
)
{
// IMPLEMENT THIS FUNCTION;
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
message
=
“The quick brown fox jumps over the lazy dog.”
;
String
host
=
“paradox.sis.pitt.edu”
;
int
port
=
7999
;
Socket
s
=
new
Socket
(
host
,
port
);
ObjectOutputStream
os
=
new
ObjectOutputStream
(
s
.
getOutputStream
());
// You should consult BigInteger class in Java API documentation to find out what it is.
BigInteger
y
,
g
,
p
;
// public key
BigInteger
d
;
// private key
int
mStrength
=
1024
;
// key bit length
SecureRandom
mSecureRandom
=
new
SecureRandom
();
// a cryptographically strong pseudo-random number
// Create a BigInterger with mStrength bit length that is highly likely to be prime.
// (The ’16’ determines the probability that p is prime. Refer to BigInteger documentation.)
p
=
new
BigInteger
(
mStrength
,
16
,
mSecureRandom
);
// Create a randomly generated BigInteger of length mStrength-1
g
=
new
BigInteger
(
mStrength
–
1
,
mSecureRandom
);
d
=
new
BigInteger
(
mStrength
–
1
,
mSecureRandom
);
y
=
computeY
(
p
,
g
,
d
);
// At this point, you have both the public key and the private key. Now compute the signature.
BigInteger
k
=
computeK
(
p
);
BigInteger
a
=
computeA
(
p
,
g
,
k
);
BigInteger
b
=
computeB
(
message
,
d
,
a
,
k
,
p
);
// send public key
os
.
writeObject
(
y
);
os
.
writeObject
(
g
);
os
.
writeObject
(
p
);
// send message
os
.
writeObject
(
message
);
// send signature
os
.
writeObject
(
a
);
os
.
writeObject
(
b
);
s
.
close
();
}
}
Final Project Skeleton/ElGamalBob.java
Final Project Skeleton/ElGamalBob.java
import
java
.
io
.
*
;
import
java
.
net
.
*
;
import
java
.
security
.
*
;
import
java
.
math
.
BigInteger
;
public
class
ElGamalBob
{
private
static
boolean
verifySignature
(
BigInteger
y
,
BigInteger
g
,
BigInteger
p
,
BigInteger
a
,
BigInteger
b
,
String
message
)
{
// IMPLEMENT THIS FUNCTION;
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
int
port
=
7999
;
ServerSocket
s
=
new
ServerSocket
(
port
);
Socket
client
=
s
.
accept
();
ObjectInputStream
is
=
new
ObjectInputStream
(
client
.
getInputStream
());
// read public key
BigInteger
y
=
(
BigInteger
)
is
.
readObject
();
BigInteger
g
=
(
BigInteger
)
is
.
readObject
();
BigInteger
p
=
(
BigInteger
)
is
.
readObject
();
// read message
String
message
=
(
String
)
is
.
readObject
();
// read signature
BigInteger
a
=
(
BigInteger
)
is
.
readObject
();
BigInteger
b
=
(
BigInteger
)
is
.
readObject
();
boolean
result
=
verifySignature
(
y
,
g
,
p
,
a
,
b
,
message
);
System
.
out
.
println
(
message
);
if
(
result
==
true
)
System
.
out
.
println
(
“Signature verified.”
);
else
System
.
out
.
println
(
“Signature verification failed.”
);
s
.
close
();
}
}
Final Project Skeleton/ProtectedClient.java
Final Project Skeleton/ProtectedClient.java
import
java
.
io
.
*
;
import
java
.
net
.
*
;
import
java
.
security
.
*
;
import
java
.
util
.
Date
;
public
class
ProtectedClient
{
public
void
sendAuthentication
(
String
user
,
String
password
,
OutputStream
outStream
)
throws
IOException
,
NoSuchAlgorithmException
{
DataOutputStream
out
=
new
DataOutputStream
(
outStream
);
// IMPLEMENT THIS FUNCTION.
out
.
flush
();
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
String
host
=
“cse.unt.edu”
;
int
port
=
7999
;
String
user
=
“George”
;
String
password
=
“abc123”
;
Socket
s
=
new
Socket
(
host
,
port
);
ProtectedClient
client
=
new
ProtectedClient
();
client
.
sendAuthentication
(
user
,
password
,
s
.
getOutputStream
());
s
.
close
();
}
}
Final Project Skeleton/ProtectedServer.java
Final Project Skeleton/ProtectedServer.java
import
java
.
io
.
*
;
import
java
.
net
.
*
;
import
java
.
security
.
*
;
public
class
ProtectedServer
{
public
boolean
authenticate
(
InputStream
inStream
)
throws
IOException
,
NoSuchAlgorithmException
{
DataInputStream
in
=
new
DataInputStream
(
inStream
);
// IMPLEMENT THIS FUNCTION.
}
protected
String
lookupPassword
(
String
user
)
{
return
“abc123”
;
}
public
static
void
main
(
String
[]
args
)
throws
Exception
{
int
port
=
7999
;
ServerSocket
s
=
new
ServerSocket
(
port
);
Socket
client
=
s
.
accept
();
ProtectedServer
server
=
new
ProtectedServer
();
if
(
server
.
authenticate
(
client
.
getInputStream
()))
System
.
out
.
println
(
“Client logged in.”
);
else
System
.
out
.
println
(
“Client failed to log in.”
);
s
.
close
();
}
}
Final Project Skeleton/Protection.java
Final Project Skeleton/Protection.java
import
java
.
io
.
*
;
import
java
.
security
.
*
;
public
class
Protection
{
public
static
byte
[]
makeBytes
(
long
t
,
double
q
)
{
try
{
ByteArrayOutputStream
byteOut
=
new
ByteArrayOutputStream
();
DataOutputStream
dataOut
=
new
DataOutputStream
(
byteOut
);
dataOut
.
writeLong
(
t
);
dataOut
.
writeDouble
(
q
);
return
byteOut
.
toByteArray
();
}
catch
(
IOException
e
)
{
return
new
byte
[
0
];
}
}
public
static
byte
[]
makeDigest
(
byte
[]
mush
,
long
t2
,
double
q2
)
throws
NoSuchAlgorithmException
{
MessageDigest
md
=
MessageDigest
.
getInstance
(
“SHA”
);
md
.
update
(
mush
);
md
.
update
(
makeBytes
(
t2
,
q2
));
return
md
.
digest
();
}
public
static
byte
[]
makeDigest
(
String
user
,
String
password
,
long
t1
,
double
q1
)
throws
NoSuchAlgorithmException
{
// IMPLEMENT THIS FUNCTION.
}
}