Example #1
0
 private void exchangeKeys() {
   try {
     output.write(modulus.toByteArray());
     byte[] buffer = new byte[ciphertextBlockSize];
     input.read(buffer);
     recipModulus = new BigInteger(1, buffer);
   } catch (IOException ioe) {
     System.err.println("Error establishing keys");
   }
 }
  public static void main(String[] args) throws Exception {
    // prompt user to enter a port number

    System.out.print("Enter the port number: ");
    Scanner scan = new Scanner(System.in);
    int port = scan.nextInt();
    scan.nextLine();
    System.out.print("Enter the host name: ");
    String hostName = scan.nextLine();

    // Initialize a key pair generator with the SKIP parameters we sepcified, and genrating a pair
    // This will take a while: 5...15 seconrds

    System.out.println("Generating a Diffie-Hellman keypair: ");
    KeyPairGenerator kpg = KeyPairGenerator.getInstance("DH");
    kpg.initialize(PARAMETER_SPEC);
    KeyPair keyPair = kpg.genKeyPair();
    System.out.println("key pair has been made...");

    // one the key pair has been generated, we want to listen on
    // a given port for a connection to come in
    // once we get a connection, we will get two streams, One for input
    // and one for output
    // open a port and wait for a connection

    ServerSocket ss = new ServerSocket(port);
    System.out.println("Listeining on port " + port + " ...");
    Socket socket = ss.accept();

    // use to output and input primitive data type

    DataOutputStream out = new DataOutputStream(socket.getOutputStream());

    // next thing to do is send our public key and receive client's
    // this corresponds to server step 3 and step 4 in the diagram

    System.out.println("Sending my public key...");
    byte[] keyBytes = keyPair.getPublic().getEncoded();
    out.writeInt(keyBytes.length);
    out.write(keyBytes);
    System.out.println("Server public key bytes: " + CryptoUtils.toHex(keyBytes));

    // receive the client's public key

    System.out.println("Receiving client's public key...");
    DataInputStream in = new DataInputStream(socket.getInputStream());
    keyBytes = new byte[in.readInt()];
    in.readFully(keyBytes);

    // create client's public key

    KeyFactory kf = KeyFactory.getInstance("DH");
    X509EncodedKeySpec x509Spec = new X509EncodedKeySpec(keyBytes);
    PublicKey clientPublicKey = kf.generatePublic(x509Spec);

    // print out client's public key bytes

    System.out.println(
        "Client public key bytes: " + CryptoUtils.toHex(clientPublicKey.getEncoded()));

    // we can now use the client's public key and
    // our own private key to perform the key agreement

    System.out.println("Performing the key agreement ... ");
    KeyAgreement ka = KeyAgreement.getInstance("DH");
    ka.init(keyPair.getPrivate());
    ka.doPhase(clientPublicKey, true);

    // in a chat application, each character is sendt over the wire, separetly encrypted,
    // Instead of using ECB, we are goin to use CFB, with a block size of 8 bits(1byte)
    // to send each character. We will encrypt the same character in a different way
    // each time. But in order to use CFB8, we need an IVof 8 bytes. We will create
    // that IV randomly and and send it to the client. It doesn't matter if somoene
    // eavesdrops on the IV when it is sent over the wire. it's not sensitive info

    // creating the IV and sending it corresponds to step 6 and 7

    byte[] iv = new byte[8];
    SecureRandom sr = new SecureRandom();
    sr.nextBytes(iv);
    out.write(iv);

    // we generate the secret byte array we share with the client and use it
    // to create the session key (Step 8)

    byte[] sessionKeyBytes = ka.generateSecret();

    // create the session key

    SecretKeyFactory skf = SecretKeyFactory.getInstance("DESede");
    DESedeKeySpec DESedeSpec = new DESedeKeySpec(sessionKeyBytes);
    SecretKey sessionKey = skf.generateSecret(DESedeSpec);

    // printout session key bytes

    System.out.println("Session key bytes: " + CryptoUtils.toHex(sessionKey.getEncoded()));

    // now use tha that session key and IV to create a CipherInputStream. We will use them to read
    // all character
    // that are sent to us by the client

    System.out.println("Creating the cipher stream ...");
    Cipher decrypter = Cipher.getInstance("DESede/CFB8/NoPadding");
    IvParameterSpec spec = new IvParameterSpec(iv);
    decrypter.init(Cipher.DECRYPT_MODE, sessionKey, spec);
    CipherInputStream cipherIn = new CipherInputStream(socket.getInputStream(), decrypter);

    // we just keep reading the input and print int to the screen, until -1 sent over

    int theCharacter = 0;
    theCharacter = cipherIn.read();
    while (theCharacter != -1) {
      System.out.print((char) theCharacter);
      theCharacter = cipherIn.read();
    }
    // once -1 is received we want to close up our stream and exit

    cipherIn.close();
    in.close();
    out.close();
    socket.close();
  }
Example #3
0
  public void actionPerformed(ActionEvent e) {
    Object source = e.getSource();
    // Client pressed enter in the message entry field-send it
    if (source == enterField) {
      // Get the message
      message = e.getActionCommand();
      try {
        // Encipher the message
        if (message.length() > plaintextBlockSize)
          message = message.substring(0, plaintextBlockSize);
        byte[] ciphertext =
            Ciphers.RSAEncipherWSalt(message.getBytes(), BigIntegerMath.THREE, recipModulus, sr);
        // Send to the server
        output.write(ciphertext);
        output.flush();
        // Display same message in client output area
        displayArea.append("\n" + message);
        enterField.setText("");
      } catch (IOException ioe) {
        displayArea.append("\nError writing message");
      }
    } else if (source == connectButton) {
      if (connection != null) { // Already connected-button press now means disconnect
        try {
          // Send final message of 0
          byte[] lastMsg = new byte[1];
          lastMsg[0] = 0;
          output.write(Ciphers.RSAEncipherWSalt(lastMsg, BigIntegerMath.THREE, recipModulus, sr));
          output.flush();
          // close connection and IO streams, change some components
          closeAll();
        } catch (IOException ioe) {
          displayArea.append("\nError closing connection");
        }
      } else { // Not connected-connect
        // Get name of server to connect to
        chatServer = serverField.getText();
        displayArea.setText("Attempting connection to " + chatServer);
        try {
          // Set up the socket
          connection = new Socket(chatServer, 55555);

          displayArea.append("\nConnected to: " + connection.getInetAddress().getHostName());

          // Set up the IO streams
          output = new DataOutputStream(connection.getOutputStream());
          output.flush();
          input = new DataInputStream(connection.getInputStream());

          // Exchange public keys with the server-send yours, get theirs
          exchangeKeys();

          // Change appearance/functionality of some components
          serverField.setEditable(false);
          connectButton.setLabel("Disconnect from server above");
          enterField.setEnabled(true);
          // Set up a thread to listen for the connection
          listener =
              new Thread(
                  new Runnable() {
                    public void run() {
                      go();
                    }
                  });
          listener.start();
        } catch (IOException ioe) {
          displayArea.append("\nError connecting to " + chatServer);
        }
      }
    }
  }