/* VServer.java- gets the hash from the VClient,generates the keys,
 *               signs the hash, sends the public key and the signature
 *               to the VClient
 *
 *Vera Arsova,2004
 *********************************************************************/
import java.net.*;
import java.io.*;
import java.io.ByteArrayOutputStream;
import java.lang.*;
import java.util.Random;
import java.security.*;

import java.util.*;
import java.lang.Object;
import java.lang.*;
import java.lang.Byte;
import java.security.spec.*;
import java.math.*;
//import java.security.NoSuchAlgorithmException;
import java.security.KeyPair;

import javax.crypto.*;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.*;

public class VServer {
     // Returns the signature for the given buffer of bytes using the private key.
    public static byte[] createSignature(PrivateKey key, byte[] buffer) {
        try {
	    System.out.println("the algoritm " + key.getAlgorithm());
	    Signature sig = Signature.getInstance("RSA");
            System.out.println("tuka sum");
	    sig.initSign(key);
            sig.update(buffer, 0, buffer.length);
            return sig.sign();
        } catch (SignatureException e) {
        } catch (InvalidKeyException e) {
        } catch (NoSuchAlgorithmException e) {
        }
        return null;
    }
    public static void main(String[] args) throws Exception {
	DatagramSocket socket = new DatagramSocket();
	DatagramPacket packet = null;
	InetAddress adresce = InetAddress.getByName("perryville");
        ServerSocket serverSocket = null;
        try {
            serverSocket = new ServerSocket(4444);
        } catch (IOException e) {
            System.err.println("Could not listen on port: 4444.");
            System.exit(1);
        }
	
        Socket clientSocket = null;
        try {
            clientSocket = serverSocket.accept();
        } catch (IOException e) {
            System.err.println("Accept failed.");
            System.exit(1);
        }
	socket = new DatagramSocket(4444);
        PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
        BufferedReader in = new BufferedReader(
				new InputStreamReader(
				clientSocket.getInputStream()));

        String inputLine, outputLine;
	BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));

	inputLine= in.readLine();   
	System.out.println("the inputLine(client): "+inputLine);
	System.out.println("this is the verify username");
	
	String username = in.readLine();
	System.out.println("the user name is: "+username);
	
	//geting the hash in byte[]
	byte[] hash = new byte[20];
	try {
	    packet = new DatagramPacket(hash,hash.length);
	    socket.receive(packet);
	    byte[] reseved = new byte[10];
	    reseved = packet.getData();
	    hash = packet.getData();
	    System.out.println("the hash is  " + hash);
	}catch (IOException e){
	    System.out.println("nemoze jabi ga" );}
	System.out.println("The hashed message looks like this : ");
	for (int i=0; i<hash.length; i++) {
	    String hex = Integer.toHexString(hash[i]);
		if (hex.length() == 1) hex = "0" + hex;
		hex=hex.substring(hex.length()-2);
		System.out.print(hex);}
	String t = " ";
	System.out.println(t);
	String has = in.readLine();
	System.out.println("the has is " + has);
	
	 /***************************************
	 *
         * sending the public key in bytes
         ***************************************/
	
	//Generating the keys
	System.out.println("\n Start generating RSA key");
	KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
	System.out.println("Provider: " + keyGen.getProvider());
	System.out.println("Provider: " + keyGen.getProvider().getInfo());
	keyGen.initialize(1024);
	KeyPair key = keyGen.generateKeyPair(); 
	PrivateKey privateKey = key.getPrivate();
        PublicKey publicKey = key.getPublic();
	
	System.out.println("the Public Key is : "+publicKey);
        byte[] publicKeyBytes = publicKey.getEncoded();
	int k = publicKeyBytes.length;
	System.out.println("duzinata na klucot e " + k);
	out.println(k);
	System.out.println("Finish generating RSA key  "+publicKeyBytes);
	//out.println("ajde dojdiii");
	InetAddress adresce2 = packet.getAddress();
	int port = packet.getPort();
	DatagramPacket packet2 = new DatagramPacket(publicKeyBytes,publicKeyBytes.length,adresce2,port);
	socket.send(packet2);
	System.out.println("the packet with the public key is sent " );

	/********************************************
         *
         *the signing and sending it to the client
         ********************************************/
	byte[] signature = new byte[162];
	try {
	    System.out.println("the algoritm e u picku materinu");
	    Provider p = new org.bouncycastle.jce.provider.BouncyCastleProvider();
	    Signature sig = Signature.getInstance("SHA-1/RSA",p);
	    System.out.println("*******the sig is " + sig);
	    sig.initSign(privateKey);
            sig.update(hash, 0, hash.length);
	    signature = sig.sign();
            System.out.println("the signature is " + sig.sign()+ "and is " + signature);
        } catch (SignatureException e) {
        } catch (InvalidKeyException e) {
        } catch (NoSuchAlgorithmException e) {
        }
	DatagramPacket packetSign = new DatagramPacket(signature,signature.length,adresce2,port);
	socket.send(packetSign);
	System.out.println("the length is " + signature.length + " THE SIGN " + signature);
	

        out.close();
        in.close();
        clientSocket.close();
        serverSocket.close();
	socket.close();
    }
}
