/*
 * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
 * agreements. See the NOTICE file distributed with this work for additional information regarding
 * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance with the License. You may obtain a
 * copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software distributed under the License
 * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing permissions and limitations under
 * the License.
 */
package org.apache.geode.internal.cache.tier.sockets;

import static org.apache.geode.internal.cache.tier.sockets.Handshake.CREDENTIALS_DHENCRYPT;
import static org.apache.geode.internal.cache.tier.sockets.Handshake.PRIVATE_KEY_ALIAS_PROP;
import static org.apache.geode.internal.cache.tier.sockets.Handshake.PRIVATE_KEY_FILE_PROP;
import static org.apache.geode.internal.cache.tier.sockets.Handshake.PRIVATE_KEY_PASSWD_PROP;
import static org.apache.geode.internal.cache.tier.sockets.Handshake.PUBLIC_KEY_FILE_PROP;
import static org.apache.geode.internal.cache.tier.sockets.Handshake.PUBLIC_KEY_PASSWD_PROP;
import static org.apache.geode.internal.cache.tier.sockets.Handshake.REPLY_AUTH_NOT_REQUIRED;
import static org.apache.geode.internal.cache.tier.sockets.Handshake.REPLY_OK;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Properties;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.KeyAgreement;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.spec.DHParameterSpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import org.apache.geode.DataSerializer;
import org.apache.geode.LogWriter;
import org.apache.geode.annotations.internal.MakeNotStatic;
import org.apache.geode.distributed.DistributedSystem;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.internal.ByteArrayDataInput;
import org.apache.geode.internal.HeapDataOutputStream;
import org.apache.geode.internal.Version;
import org.apache.geode.internal.cache.tier.Encryptor;
import org.apache.geode.internal.logging.InternalLogWriter;
import org.apache.geode.security.AuthenticationFailedException;
import org.apache.geode.security.GemFireSecurityException;

public class EncryptorImpl implements Encryptor {
  // Parameters for the Diffie-Hellman key exchange
  private static final BigInteger dhP =
      new BigInteger("13528702063991073999718992897071702177131142188276542919088770094024269"
          + "73079899070080419278066109785292538223079165925365098181867673946"
          + "34756714063947534092593553024224277712367371302394452615862654308"
          + "11180902979719649450105660478776364198726078338308557022096810447"
          + "3500348898008043285865193451061481841186553");

  private static final BigInteger dhG =
      new BigInteger("13058345680719715096166513407513969537624553636623932169016704425008150"
          + "56576152779768716554354314319087014857769741104157332735258102835"
          + "93126577393912282416840649805564834470583437473176415335737232689"
          + "81480201869671811010996732593655666464627559582258861254878896534"
          + "1273697569202082715873518528062345259949959");

  private static final int dhL = 1023;

  private Cipher _encrypt;
  private Cipher _decrypt;

  private PublicKey clientPublicKey;

  private String clientSKAlgo;

  @MakeNotStatic
  private static PrivateKey dhPrivateKey;

  @MakeNotStatic
  private static PublicKey dhPublicKey;

  @MakeNotStatic
  private static String dhSKAlgo;

  // Members for server authentication using digital signature

  // Members for server authentication using digital signature

  @MakeNotStatic
  private static String certificateFilePath;

  @MakeNotStatic
  private static HashMap certificateMap;

  @MakeNotStatic
  private static String privateKeyAlias;

  @MakeNotStatic
  private static String privateKeySubject;

  @MakeNotStatic
  private static PrivateKey privateKeyEncrypt;

  @MakeNotStatic
  private static String privateKeySignAlgo;

  @MakeNotStatic
  private static SecureRandom random;

  private byte appSecureMode = (byte) 0;

  private LogWriter logWriter;


  EncryptorImpl(EncryptorImpl encryptor) {
    this.appSecureMode = encryptor.appSecureMode;
    this.logWriter = encryptor.logWriter;
  }

  public EncryptorImpl(LogWriter logWriter) {
    this.logWriter = logWriter;
  }


  void setAppSecureMode(byte appSecureMode) {
    this.appSecureMode = appSecureMode;
  }

  public static byte[] decryptBytes(byte[] data, Cipher decrypt) throws Exception {
    return decrypt.doFinal(data);
  }

  protected Cipher getDecryptCipher(String dhSKAlgo, PublicKey publicKey) throws Exception {
    if (_decrypt == null) {
      KeyAgreement ka = KeyAgreement.getInstance("DH");
      ka.init(dhPrivateKey);
      ka.doPhase(publicKey, true);

      Cipher decrypt;

      int keysize = getKeySize(dhSKAlgo);
      int blocksize = getBlockSize(dhSKAlgo);

      if (keysize == -1 || blocksize == -1) {
        SecretKey sKey = ka.generateSecret(dhSKAlgo);
        decrypt = Cipher.getInstance(dhSKAlgo);
        decrypt.init(Cipher.DECRYPT_MODE, sKey);
      } else {
        String algoStr = getDhAlgoStr(dhSKAlgo);

        byte[] sKeyBytes = ka.generateSecret();
        SecretKeySpec sks = new SecretKeySpec(sKeyBytes, 0, keysize, algoStr);
        IvParameterSpec ivps = new IvParameterSpec(sKeyBytes, keysize, blocksize);

        decrypt = Cipher.getInstance(algoStr + "/CBC/PKCS5Padding");
        decrypt.init(Cipher.DECRYPT_MODE, sks, ivps);
      }

      _decrypt = decrypt;
    }
    return _decrypt;
  }

  /**
   * Populate the available server public keys into a local static HashMap. This method is not
   * thread safe.
   */
  public static void initCertsMap(Properties props) throws Exception {

    certificateMap = new HashMap();
    certificateFilePath = props.getProperty(PUBLIC_KEY_FILE_PROP);
    if (certificateFilePath != null && certificateFilePath.length() > 0) {
      KeyStore ks = KeyStore.getInstance("JKS");
      String keyStorePass = props.getProperty(PUBLIC_KEY_PASSWD_PROP);
      char[] passPhrase = (keyStorePass != null ? keyStorePass.toCharArray() : null);
      FileInputStream keystorefile = new FileInputStream(certificateFilePath);
      try {
        ks.load(keystorefile, passPhrase);
      } finally {
        keystorefile.close();
      }
      Enumeration aliases = ks.aliases();
      while (aliases.hasMoreElements()) {
        String alias = (String) aliases.nextElement();
        Certificate cert = ks.getCertificate(alias);
        if (cert instanceof X509Certificate) {
          String subject = ((X509Certificate) cert).getSubjectDN().getName();
          certificateMap.put(subject, cert);
        }
      }
    }
  }

  /**
   * Load the private key of the server. This method is not thread safe.
   */
  public static void initPrivateKey(Properties props) throws Exception {

    String privateKeyFilePath = props.getProperty(PRIVATE_KEY_FILE_PROP);
    privateKeyAlias = "";
    privateKeyEncrypt = null;
    if (privateKeyFilePath != null && privateKeyFilePath.length() > 0) {
      KeyStore ks = KeyStore.getInstance("PKCS12");
      privateKeyAlias = props.getProperty(PRIVATE_KEY_ALIAS_PROP);
      if (privateKeyAlias == null) {
        privateKeyAlias = "";
      }
      String keyStorePass = props.getProperty(PRIVATE_KEY_PASSWD_PROP);
      char[] passPhrase = (keyStorePass != null ? keyStorePass.toCharArray() : null);
      FileInputStream privateKeyFile = new FileInputStream(privateKeyFilePath);
      try {
        ks.load(privateKeyFile, passPhrase);
      } finally {
        privateKeyFile.close();
      }
      Key key = ks.getKey(privateKeyAlias, passPhrase);
      Certificate keyCert = ks.getCertificate(privateKeyAlias);
      if (key instanceof PrivateKey && keyCert instanceof X509Certificate) {
        privateKeyEncrypt = (PrivateKey) key;
        privateKeySignAlgo = ((X509Certificate) keyCert).getSigAlgName();
        privateKeySubject = ((X509Certificate) keyCert).getSubjectDN().getName();
      }
    }
  }

  /**
   * Initialize the Diffie-Hellman keys. This method is not thread safe
   */
  public static void initDHKeys(DistributionConfig config) throws Exception {

    dhSKAlgo = config.getSecurityClientDHAlgo();
    dhPrivateKey = null;
    dhPublicKey = null;
    // Initialize the keys when either the host is a client that has
    // non-blank setting for DH symmetric algo, or this is a server
    // that has authenticator defined.
    if ((dhSKAlgo != null
        && dhSKAlgo.length() > 0) /* || securityService.isClientSecurityRequired() */) {
      KeyPairGenerator keyGen = KeyPairGenerator.getInstance("DH");
      DHParameterSpec dhSpec = new DHParameterSpec(dhP, dhG, dhL);
      keyGen.initialize(dhSpec);
      KeyPair keypair = keyGen.generateKeyPair();

      // Get the generated public and private keys
      dhPrivateKey = keypair.getPrivate();
      dhPublicKey = keypair.getPublic();

      random = new SecureRandom();
      // Force the random generator to seed itself.
      byte[] someBytes = new byte[48];
      random.nextBytes(someBytes);
    }
  }

  @Override
  public byte[] decryptBytes(byte[] data) throws Exception {
    if (this.appSecureMode == CREDENTIALS_DHENCRYPT) {
      String algo = null;
      if (this.clientSKAlgo != null) {
        algo = this.clientSKAlgo;
      } else {
        algo = dhSKAlgo;
      }
      Cipher c = getDecryptCipher(algo, this.clientPublicKey);
      return decryptBytes(data, c);
    } else {
      return data;
    }
  }



  @Override
  public byte[] encryptBytes(byte[] data) throws Exception {
    if (this.appSecureMode == CREDENTIALS_DHENCRYPT) {
      String algo = null;
      if (this.clientSKAlgo != null) {
        algo = this.clientSKAlgo;
      } else {
        algo = dhSKAlgo;
      }
      return encryptBytes(data, getEncryptCipher(algo, this.clientPublicKey));
    } else {
      return data;
    }
  }

  public static byte[] encryptBytes(byte[] data, Cipher encrypt) throws Exception {
    return encrypt.doFinal(data);
  }

  protected Cipher getEncryptCipher(String dhSKAlgo, PublicKey publicKey) throws Exception {
    if (_encrypt == null) {
      KeyAgreement ka = KeyAgreement.getInstance("DH");
      ka.init(dhPrivateKey);
      ka.doPhase(publicKey, true);

      Cipher encrypt;

      int keysize = getKeySize(dhSKAlgo);
      int blocksize = getBlockSize(dhSKAlgo);

      if (keysize == -1 || blocksize == -1) {
        SecretKey sKey = ka.generateSecret(dhSKAlgo);
        encrypt = Cipher.getInstance(dhSKAlgo);
        encrypt.init(Cipher.ENCRYPT_MODE, sKey);
      } else {
        String dhAlgoStr = getDhAlgoStr(dhSKAlgo);

        byte[] sKeyBytes = ka.generateSecret();
        SecretKeySpec sks = new SecretKeySpec(sKeyBytes, 0, keysize, dhAlgoStr);
        IvParameterSpec ivps = new IvParameterSpec(sKeyBytes, keysize, blocksize);

        encrypt = Cipher.getInstance(dhAlgoStr + "/CBC/PKCS5Padding");
        encrypt.init(Cipher.ENCRYPT_MODE, sks, ivps);
      }
      _encrypt = encrypt;
    }
    return _encrypt;
  }

  boolean isEnabled() {
    return dhSKAlgo != null && dhSKAlgo.length() > 0;
  }

  byte writeEncryptedCredential(DataOutputStream dos, DataInputStream dis,
      HeapDataOutputStream heapdos) throws IOException {
    byte acceptanceCode;
    try {
      logWriter.fine("HandShake: using Diffie-Hellman key exchange with algo " + dhSKAlgo);
      boolean requireAuthentication =
          (certificateFilePath != null && certificateFilePath.length() > 0);
      if (requireAuthentication) {
        logWriter.fine("HandShake: server authentication using digital " + "signature required");
      }
      // Credentials with encryption indicator
      heapdos.writeByte(CREDENTIALS_DHENCRYPT);
      this.appSecureMode = CREDENTIALS_DHENCRYPT;
      heapdos.writeBoolean(requireAuthentication);
      // Send the symmetric encryption algorithm name
      DataSerializer.writeString(dhSKAlgo, heapdos);
      // Send the DH public key
      byte[] keyBytes = dhPublicKey.getEncoded();
      DataSerializer.writeByteArray(keyBytes, heapdos);
      byte[] clientChallenge = null;
      if (requireAuthentication) {
        // Authentication of server should be with the client supplied
        // challenge
        clientChallenge = new byte[64];
        random.nextBytes(clientChallenge);
        DataSerializer.writeByteArray(clientChallenge, heapdos);
      }
      heapdos.flush();
      dos.write(heapdos.toByteArray());
      dos.flush();

      // Expect the alias and signature in the reply
      acceptanceCode = dis.readByte();
      if (acceptanceCode == REPLY_OK) {
        // Get the public key of the other side
        keyBytes = DataSerializer.readByteArray(dis);
        if (requireAuthentication) {
          String subject = DataSerializer.readString(dis);
          byte[] signatureBytes = DataSerializer.readByteArray(dis);
          if (!certificateMap.containsKey(subject)) {
            throw new AuthenticationFailedException(
                String.format("HandShake failed to find public key for server with subject %s",
                    subject));
          }

          // Check the signature with the public key
          X509Certificate cert = (X509Certificate) certificateMap.get(subject);
          Signature sig = Signature.getInstance(cert.getSigAlgName());
          sig.initVerify(cert);
          sig.update(clientChallenge);
          // Check the challenge string
          if (!sig.verify(signatureBytes)) {
            throw new AuthenticationFailedException(
                "Mismatch in client " + "challenge bytes. Malicious server?");
          }
          logWriter.fine("HandShake: Successfully verified the " + "digital signature from server");
        }

        // Read server challenge bytes
        byte[] serverChallenge = DataSerializer.readByteArray(dis);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFact = KeyFactory.getInstance("DH");
        // PublicKey pubKey = keyFact.generatePublic(x509KeySpec);
        this.clientPublicKey = keyFact.generatePublic(x509KeySpec);

        try (HeapDataOutputStream hdos = new HeapDataOutputStream(Version.CURRENT)) {
          // Add the challenge string
          DataSerializer.writeByteArray(serverChallenge, hdos);
          // byte[] encBytes = encrypt.doFinal(hdos.toByteArray());
          byte[] encBytes =
              encryptBytes(hdos.toByteArray(), getEncryptCipher(dhSKAlgo, this.clientPublicKey));
          DataSerializer.writeByteArray(encBytes, dos);
        }
      }
    } catch (IOException ex) {
      throw ex;
    } catch (GemFireSecurityException ex) {
      throw ex;
    } catch (Exception ex) {
      throw new AuthenticationFailedException("HandShake failed in Diffie-Hellman key exchange",
          ex);
    }
    return acceptanceCode;
  }

  byte writeEncryptedCredentials(DataOutputStream dos, DataInputStream dis,
      Properties p_credentials, HeapDataOutputStream heapdos) throws IOException {
    byte acceptanceCode;
    try {
      logWriter.fine("HandShake: using Diffie-Hellman key exchange with algo " + dhSKAlgo);
      boolean requireAuthentication =
          (certificateFilePath != null && certificateFilePath.length() > 0);
      if (requireAuthentication) {
        logWriter.fine("HandShake: server authentication using digital signature required");
      }
      // Credentials with encryption indicator
      heapdos.writeByte(CREDENTIALS_DHENCRYPT);
      heapdos.writeBoolean(requireAuthentication);
      // Send the symmetric encryption algorithm name
      DataSerializer.writeString(dhSKAlgo, heapdos);
      // Send the DH public key
      byte[] keyBytes = dhPublicKey.getEncoded();
      DataSerializer.writeByteArray(keyBytes, heapdos);
      byte[] clientChallenge = null;
      if (requireAuthentication) {
        // Authentication of server should be with the client supplied
        // challenge
        clientChallenge = new byte[64];
        random.nextBytes(clientChallenge);
        DataSerializer.writeByteArray(clientChallenge, heapdos);
      }
      heapdos.flush();
      dos.write(heapdos.toByteArray());
      dos.flush();

      // Expect the alias and signature in the reply
      acceptanceCode = dis.readByte();
      if (acceptanceCode == REPLY_OK) {
        // Get the public key of the other side
        keyBytes = DataSerializer.readByteArray(dis);
        if (requireAuthentication) {
          String subject = DataSerializer.readString(dis);
          byte[] signatureBytes = DataSerializer.readByteArray(dis);
          if (!certificateMap.containsKey(subject)) {
            throw new AuthenticationFailedException(
                String.format("HandShake failed to find public key for server with subject %s",
                    subject));
          }

          // Check the signature with the public key
          X509Certificate cert = (X509Certificate) certificateMap.get(subject);
          Signature sig = Signature.getInstance(cert.getSigAlgName());
          sig.initVerify(cert);
          sig.update(clientChallenge);
          // Check the challenge string
          if (!sig.verify(signatureBytes)) {
            throw new AuthenticationFailedException(
                "Mismatch in client " + "challenge bytes. Malicious server?");
          }
          logWriter.fine("HandShake: Successfully verified the " + "digital signature from server");
        }

        byte[] challenge = DataSerializer.readByteArray(dis);
        X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFact = KeyFactory.getInstance("DH");
        // PublicKey pubKey = keyFact.generatePublic(x509KeySpec);
        this.clientPublicKey = keyFact.generatePublic(x509KeySpec);



        HeapDataOutputStream hdos = new HeapDataOutputStream(Version.CURRENT);
        try {
          DataSerializer.writeProperties(p_credentials, hdos);
          // Also add the challenge string
          DataSerializer.writeByteArray(challenge, hdos);

          // byte[] encBytes = encrypt.doFinal(hdos.toByteArray());
          byte[] encBytes =
              encryptBytes(hdos.toByteArray(), getEncryptCipher(dhSKAlgo, this.clientPublicKey));
          DataSerializer.writeByteArray(encBytes, dos);
        } finally {
          hdos.close();
        }
      }
    } catch (IOException ex) {
      throw ex;
    } catch (GemFireSecurityException ex) {
      throw ex;
    } catch (Exception ex) {
      throw new AuthenticationFailedException("HandShake failed in Diffie-Hellman key exchange",
          ex);
    }
    return acceptanceCode;
  }

  void readEncryptedCredentials(DataInputStream dis, DataOutputStream dos, DistributedSystem system,
      boolean requireAuthentication) throws Exception {
    this.appSecureMode = CREDENTIALS_DHENCRYPT;
    boolean sendAuthentication = dis.readBoolean();
    InternalLogWriter securityLogWriter = (InternalLogWriter) system.getSecurityLogWriter();
    // Get the symmetric encryption algorithm to be used
    this.clientSKAlgo = DataSerializer.readString(dis);
    // Get the public key of the other side
    byte[] keyBytes = DataSerializer.readByteArray(dis);
    byte[] challenge = null;
    // PublicKey pubKey = null;
    if (requireAuthentication) {
      // Generate PublicKey from encoded form
      X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
      KeyFactory keyFact = KeyFactory.getInstance("DH");
      this.clientPublicKey = keyFact.generatePublic(x509KeySpec);

      // Send the public key to other side
      keyBytes = dhPublicKey.getEncoded();
      challenge = new byte[64];
      random.nextBytes(challenge);

      // If the server has to also authenticate itself then
      // sign the challenge from client.
      if (sendAuthentication) {
        // Get the challenge string from client
        byte[] clientChallenge = DataSerializer.readByteArray(dis);
        if (privateKeyEncrypt == null) {
          throw new AuthenticationFailedException(
              "Server private key not available for creating signature.");
        }
        // Sign the challenge from client and send it to the client
        Signature sig = Signature.getInstance(privateKeySignAlgo);
        sig.initSign(privateKeyEncrypt);
        sig.update(clientChallenge);
        byte[] signedBytes = sig.sign();
        dos.writeByte(REPLY_OK);
        DataSerializer.writeByteArray(keyBytes, dos);
        // DataSerializer.writeString(privateKeyAlias, dos);
        DataSerializer.writeString(privateKeySubject, dos);
        DataSerializer.writeByteArray(signedBytes, dos);
        securityLogWriter.fine("HandShake: sent the signed client challenge");
      } else {
        // These two lines should not be moved before the if{} statement in
        // a common block for both if...then...else parts. This is to handle
        // the case when an AuthenticationFailedException is thrown by the
        // if...then part when sending the signature.
        dos.writeByte(REPLY_OK);
        DataSerializer.writeByteArray(keyBytes, dos);
      }
      // Now send the server challenge
      DataSerializer.writeByteArray(challenge, dos);
      securityLogWriter.fine("HandShake: sent the public key and challenge");
      dos.flush();

      // Read and decrypt the credentials
      byte[] encBytes = DataSerializer.readByteArray(dis);
      Cipher c = getDecryptCipher(this.clientSKAlgo, this.clientPublicKey);
      byte[] credentialBytes = decryptBytes(encBytes, c);
      ByteArrayDataInput dinp = new ByteArrayDataInput(credentialBytes);
      // credentials = DataSerializer.readProperties(dinp);//Hitesh: we don't send in handshake
      // now
      byte[] challengeRes = DataSerializer.readByteArray(dinp);
      // Check the challenge string
      if (!Arrays.equals(challenge, challengeRes)) {
        throw new AuthenticationFailedException(
            "Mismatch in challenge bytes. Malicious client?");
      }
      dinp.close();
    } else {
      if (sendAuthentication) {
        // Read and ignore the client challenge
        DataSerializer.readByteArray(dis);
      }
      dos.writeByte(REPLY_AUTH_NOT_REQUIRED);
      dos.flush();
    }
  }

  static Properties getDecryptedCredentials(DataInputStream dis, DataOutputStream dos,
      DistributedSystem system, boolean requireAuthentication, Properties credentials)
      throws IOException, NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException,
      SignatureException, NoSuchPaddingException, InvalidAlgorithmParameterException,
      IllegalBlockSizeException, BadPaddingException, ClassNotFoundException {
    boolean sendAuthentication = dis.readBoolean();
    InternalLogWriter securityLogWriter = (InternalLogWriter) system.getSecurityLogWriter();
    // Get the symmetric encryption algorithm to be used
    String skAlgo = DataSerializer.readString(dis);
    // Get the public key of the other side
    byte[] keyBytes = DataSerializer.readByteArray(dis);
    byte[] challenge = null;
    PublicKey pubKey = null;
    if (requireAuthentication) {
      // Generate PublicKey from encoded form
      X509EncodedKeySpec x509KeySpec = new X509EncodedKeySpec(keyBytes);
      KeyFactory keyFact = KeyFactory.getInstance("DH");
      pubKey = keyFact.generatePublic(x509KeySpec);

      // Send the public key to other side
      keyBytes = dhPublicKey.getEncoded();
      challenge = new byte[64];
      random.nextBytes(challenge);

      // If the server has to also authenticate itself then
      // sign the challenge from client.
      if (sendAuthentication) {
        // Get the challenge string from client
        byte[] clientChallenge = DataSerializer.readByteArray(dis);
        if (privateKeyEncrypt == null) {
          throw new AuthenticationFailedException(
              "Server private key not available for creating signature.");
        }
        // Sign the challenge from client and send it to the client
        Signature sig = Signature.getInstance(privateKeySignAlgo);
        sig.initSign(privateKeyEncrypt);
        sig.update(clientChallenge);
        byte[] signedBytes = sig.sign();
        dos.writeByte(REPLY_OK);
        DataSerializer.writeByteArray(keyBytes, dos);
        // DataSerializer.writeString(privateKeyAlias, dos);
        DataSerializer.writeString(privateKeySubject, dos);
        DataSerializer.writeByteArray(signedBytes, dos);
        securityLogWriter.fine("HandShake: sent the signed client challenge");
      } else {
        // These two lines should not be moved before the if{} statement in
        // a common block for both if...then...else parts. This is to handle
        // the case when an AuthenticationFailedException is thrown by the
        // if...then part when sending the signature.
        dos.writeByte(REPLY_OK);
        DataSerializer.writeByteArray(keyBytes, dos);
      }
      // Now send the server challenge
      DataSerializer.writeByteArray(challenge, dos);
      securityLogWriter.fine("HandShake: sent the public key and challenge");
      dos.flush();

      // Read and decrypt the credentials
      byte[] encBytes = DataSerializer.readByteArray(dis);
      KeyAgreement ka = KeyAgreement.getInstance("DH");
      ka.init(dhPrivateKey);
      ka.doPhase(pubKey, true);

      Cipher decrypt;

      int keysize = getKeySize(skAlgo);
      int blocksize = getBlockSize(skAlgo);

      if (keysize == -1 || blocksize == -1) {
        SecretKey sKey = ka.generateSecret(skAlgo);
        decrypt = Cipher.getInstance(skAlgo);
        decrypt.init(Cipher.DECRYPT_MODE, sKey);
      } else {
        String algoStr = getDhAlgoStr(skAlgo);

        byte[] sKeyBytes = ka.generateSecret();
        SecretKeySpec sks = new SecretKeySpec(sKeyBytes, 0, keysize, algoStr);
        IvParameterSpec ivps = new IvParameterSpec(sKeyBytes, keysize, blocksize);

        decrypt = Cipher.getInstance(algoStr + "/CBC/PKCS5Padding");
        decrypt.init(Cipher.DECRYPT_MODE, sks, ivps);
      }

      byte[] credentialBytes = decrypt.doFinal(encBytes);
      ByteArrayDataInput dinp = new ByteArrayDataInput(credentialBytes);
      credentials = DataSerializer.readProperties(dinp);
      byte[] challengeRes = DataSerializer.readByteArray(dinp);
      // Check the challenge string
      if (!Arrays.equals(challenge, challengeRes)) {
        throw new AuthenticationFailedException(
            "Mismatch in challenge bytes. Malicious client?");
      }
      dinp.close();
    } else {
      if (sendAuthentication) {
        // Read and ignore the client challenge
        DataSerializer.readByteArray(dis);
      }
      dos.writeByte(REPLY_AUTH_NOT_REQUIRED);
      dos.flush();
    }
    return credentials;
  }


  private static int getKeySize(String skAlgo) {
    // skAlgo contain both algo and key size info
    int colIdx = skAlgo.indexOf(':');
    String algoStr;
    int algoKeySize = 0;
    if (colIdx >= 0) {
      algoStr = skAlgo.substring(0, colIdx);
      algoKeySize = Integer.parseInt(skAlgo.substring(colIdx + 1));
    } else {
      algoStr = skAlgo;
    }
    int keysize = -1;
    if (algoStr.equalsIgnoreCase("DESede")) {
      keysize = 24;
    } else if (algoStr.equalsIgnoreCase("Blowfish")) {
      keysize = algoKeySize > 128 ? algoKeySize / 8 : 16;
    } else if (algoStr.equalsIgnoreCase("AES")) {
      keysize = (algoKeySize != 192 && algoKeySize != 256) ? 16 : algoKeySize / 8;
    }
    return keysize;
  }

  private static String getDhAlgoStr(String skAlgo) {
    int colIdx = skAlgo.indexOf(':');
    String algoStr;
    if (colIdx >= 0) {
      algoStr = skAlgo.substring(0, colIdx);
    } else {
      algoStr = skAlgo;
    }
    return algoStr;
  }

  private static int getBlockSize(String skAlgo) {
    int blocksize = -1;
    String algoStr = getDhAlgoStr(skAlgo);
    if (algoStr.equalsIgnoreCase("DESede")) {
      blocksize = 8;
    } else if (algoStr.equalsIgnoreCase("Blowfish")) {
      blocksize = 8;
    } else if (algoStr.equalsIgnoreCase("AES")) {
      blocksize = 16;
    }
    return blocksize;
  }


}
