//XOR.java
import java.util.Scanner;
import java.security.SecureRandom;
import java.math.BigInteger;

class XOR{

   public static void main (String args[]) 
	{
      try {

      //Read a line from keyboard
      Scanner in = new Scanner(System.in); //define scanner for input
      String messageString;  

      System.out.println("Please enter the message:");
      messageString=in.nextLine(); //read a line
      System.out.println("Original Message: "+ messageString);

      BigInteger message = convertStringToBigInteger(messageString);		

     //Set up a secure random number generator
      SecureRandom random = SecureRandom.getInstance("SHA1PRNG"); 
      int seed = 10;  
      random.setSeed(seed);  //initilize the random number generator

      //Generate Key (Warning! botched)
      byte [] keyStream = new byte[2];
      random.nextBytes(keyStream); //generate random bytes in put in keyStream
      BigInteger key = new BigInteger(keyStream);


      //XOR encryption -- Sender's (Alice's) end
       BigInteger cipherText = message.xor(key);

      //Convert ciphertext to a string so that we can print it
     
      System.out.println("plaintext (in binary):" + message.toString(2));
      System.out.println("key (in binary):" + key.toString(2));
      System.out.println("ciphertext (in binary):" + cipherText.toString(2));
      System.out.println("Ciphertext (in characters): "+ convertBigIntegerToString(cipherText));
      
      //XOR decryption -- Receiver's end (Bob's end) 
      BigInteger receivedMessage = cipherText.xor(key);
      String receivedMessageString = convertBigIntegerToString(receivedMessage);		
      System.out.println("Received Message: "+ receivedMessageString);
      }
      catch (Exception e) {
         e.printStackTrace();
      }
   }


//This is a method to convert a String to BigInteger by
//packing each character into a BigInteger
//Input: String
//Output: BigInteger
public static BigInteger convertStringToBigInteger(String s)
{
      BigInteger b = new BigInteger("0");
      for (int i = 0; i < s.length(); i++)
         {
         Integer code = new Integer((int)s.charAt(i));
         BigInteger c = new BigInteger(code.toString());
         b = b.shiftLeft(8);
         b = b.or(c);
         }
  return b;
}


//This is a method to convert a BigInteger to String
//by converting each byte into a character and forming 
//a string of characters.
//Input: BigInteger
//Output: String

public static String  convertBigIntegerToString(BigInteger b)
  { 
  String s = new String();
  while (b.compareTo(BigInteger.ZERO) == 1)
         {
         BigInteger c = new BigInteger("11111111", 2);
         int cb = (b.and(c)).intValue();
         Character cv= new Character((char)cb);
         s = (cv.toString()).concat(s);
         b = b.shiftRight(8);
         }
    return s;
  }
}