⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sslhandshakeprotocol.java

📁 这是linux下ssl vpn的实现程序
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 *  SSL-Explorer
 *
 *  Copyright (C) 2003-2006 3SP LTD. All Rights Reserved
 *
 *  This program is free software; you can redistribute it and/or
 *  modify it under the terms of the GNU General Public License
 *  as published by the Free Software Foundation; either version 2 of
 *  the License, or (at your option) any later version.
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public
 *  License along with this program; if not, write to the Free Software
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
			
package com.maverick.ssl;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.math.BigInteger;

/* DEBUG */ import org.apache.commons.logging.*;
import com.maverick.crypto.asn1.ASN1Sequence;
import com.maverick.crypto.asn1.DERInputStream;
import com.maverick.crypto.asn1.x509.CertificateException;
import com.maverick.crypto.asn1.x509.X509Certificate;
import com.maverick.crypto.asn1.x509.X509CertificateStructure;
import com.maverick.crypto.digests.MD5Digest;
import com.maverick.crypto.digests.SHA1Digest;
import com.maverick.crypto.publickey.PublicKey;
import com.maverick.crypto.publickey.Rsa;
import com.maverick.crypto.publickey.RsaPublicKey;

class SSLHandshakeProtocol {

  final static int HANDSHAKE_PROTOCOL_MSG = 22;

  final static int HELLO_REQUEST_MSG = 0;
  final static int CLIENT_HELLO_MSG = 1;
  final static int SERVER_HELLO_MSG = 2;

  final static int CERTIFICATE_MSG = 11;
  final static int KEY_EXCHANGE_MSG = 12;

  final static int CERTIFICATE_REQUEST_MSG = 13;
  final static int SERVER_HELLO_DONE_MSG = 14;

  final static int CERTIFICATE_VERIFY_MSG = 15;
  final static int CLIENT_KEY_EXCHANGE_MSG = 16;
  final static int FINISHED_MSG = 20;

  final static int HANDSHAKE_PENDING_OR_COMPLETE = -1;

  SSLContext context;
  SSLTransport socket;

  MD5Digest handshakeMD5 = new MD5Digest();
  SHA1Digest handshakeSHA1 = new SHA1Digest();

  // The session components as selected by the server
  SSLCipherSuiteID cipherSuiteID;
  int compressionID;
  byte[] sessionID;
  int majorVersion;
  int minorVersion;
  byte[] clientRandom;
  byte[] serverRandom;
  byte[] premasterSecret;
  byte[] masterSecret;

  X509Certificate x509;

  SSLCipherSuite pendingCipherSuite;
  boolean wantsClientAuth = false;
  int currentHandshakeStep = HANDSHAKE_PENDING_OR_COMPLETE;

/* DEBUG */ Log log = LogFactory.getLog(SSLHandshakeProtocol.class);

  public SSLHandshakeProtocol(SSLTransport socket, SSLContext context) throws
      IOException {
    this.socket = socket;
    this.context = context;

  }

  boolean isComplete() {
    return currentHandshakeStep == HANDSHAKE_PENDING_OR_COMPLETE;
  }

  void processMessage(byte[] fragment, int off, int len) throws SSLException {

    ByteArrayInputStream reader = new ByteArrayInputStream(fragment, off, len);

    // Update the handshake hashes
    updateHandshakeHashes(fragment);

    while (reader.available() > 0 && !isComplete()) {

      int type = reader.read();

      int length = (reader.read() & 0xFF) << 16
          | (reader.read() & 0xFF) << 8
          | (reader.read() & 0xFF);

/* DEBUG */ log.debug("Handshake protocol is processing type "
/* DEBUG */      + type + " with " + length + " bytes of message data");

      byte[] msg = new byte[length];
      try {
        reader.read(msg);
      }
      catch (IOException ex) {
        throw new SSLException(SSLException.INTERNAL_ERROR,
                               ex.getMessage() == null ? ex.getClass().getName() :
                               ex.getMessage());
      }

      switch (type) {
        case HELLO_REQUEST_MSG:

          /* DEBUG */ log.debug("Received HELLO request");
          /**
           * If we receive a hello request then a handshake must be
           * re-negotiated. But ignore it if were already performing
           * a handshake operation
           */
          if (currentHandshakeStep == HANDSHAKE_PENDING_OR_COMPLETE) {
            startHandshake();
          }
          break;

        case SERVER_HELLO_MSG:

          /* DEBUG */ log.debug("Received server HELLO message");

          if (currentHandshakeStep != CLIENT_HELLO_MSG) {
            throw new SSLException(SSLException.PROTOCOL_VIOLATION,
                "Server HELLO message received but not expected ("
                + currentHandshakeStep + ")");
          }

          onServerHelloMsg(msg);
          break;

        case CERTIFICATE_MSG:

          /* DEBUG */ log.debug("Received server certificate");

          if (currentHandshakeStep != SERVER_HELLO_MSG) {
            throw new SSLException(SSLException.PROTOCOL_VIOLATION,
                "Certificate message received but not expected ("
                + currentHandshakeStep + ")");
          }
          onCertificateMsg(msg);
          break;

        case KEY_EXCHANGE_MSG:

          /* DEBUG */ log.debug(
          /* DEBUG */     "Received server key exchange [Unsupported operation]");

          throw new SSLException(SSLException.UNSUPPORTED_OPERATION,
              "We currently dont support server key exchange!");

        case CERTIFICATE_REQUEST_MSG:

          /* DEBUG */ log.debug(
          /* DEBUG */     "Received client certificate request [Unsupported operation]");

          wantsClientAuth = true;
          break;

        case SERVER_HELLO_DONE_MSG:

          /* DEBUG */ log.debug("Received server HELLO DONE");

          if (currentHandshakeStep != CERTIFICATE_MSG) {
            throw new SSLException(SSLException.PROTOCOL_VIOLATION,
                "Server HELLO DONE message received but not expected ("
                + currentHandshakeStep + ")");
          }

          if(wantsClientAuth) {

            /* DEBUG */log.debug("Sending no certificate alert");
            socket.sendMessage(SSLTransport.ALERT_PROTOCOL,
                        new byte[] { (byte) SSLTransport.WARNING_ALERT,
                            (byte) SSLException.NO_CERTIFICATE});
          }
          onServerHelloDoneMsg();
          break;

        case FINISHED_MSG:

          /* DEBUG */ log.debug("Received server FINISHED");

          if (currentHandshakeStep != FINISHED_MSG) {
            throw new SSLException(SSLException.PROTOCOL_VIOLATION);
          }

          currentHandshakeStep = HANDSHAKE_PENDING_OR_COMPLETE;

          break;

        default:

      }
    }
  }

  private void sendMessage(int type, byte[] data) throws SSLException {

    ByteArrayOutputStream msg = new ByteArrayOutputStream();

    try {
      msg.write(type);
      msg.write( (data.length >> 16) & 0xFF);
      msg.write( (data.length >> 8) & 0xFF);
      msg.write(data.length);
      msg.write(data);
    }
    catch (IOException ex) {
      throw new SSLException(SSLException.INTERNAL_ERROR,
                             ex.getMessage() == null ? ex.getClass().getName() :
                             ex.getMessage());
    }

    byte[] m = msg.toByteArray();

    // Update the handshake hashes if its anything but the FINISHED_MSG
    if (type != FINISHED_MSG) {
      updateHandshakeHashes(m);

    }
    socket.sendMessage(HANDSHAKE_PROTOCOL_MSG, m);
  }

  public void startHandshake() throws SSLException {

    if (currentHandshakeStep != HANDSHAKE_PENDING_OR_COMPLETE) {
      throw new SSLException(
          SSLException.PROTOCOL_VIOLATION,
          "Handshake cannot be started as a handshake operation is in progress");
    }

/* DEBUG */ log.debug("Starting SSL Handshake");

    sendClientHello();
  }

  private void calculateMasterSecret() throws SSLException {

/* DEBUG */ log.debug("Calculating master secret");

    try {
      MD5Digest md5 = new MD5Digest();
      SHA1Digest sha1 = new SHA1Digest();

      ByteArrayOutputStream out = new ByteArrayOutputStream();

      String[] mixers = new String[] {
          "A", "BB", "CCC"};

      for (int i = 0; i < mixers.length; i++) {
        md5.reset();
        sha1.reset();
        sha1.update(mixers[i].getBytes(), 0, mixers[i].getBytes().length);
        sha1.update(premasterSecret, 0, premasterSecret.length);
        sha1.update(clientRandom, 0, clientRandom.length);
        sha1.update(serverRandom, 0, serverRandom.length);

        md5.update(premasterSecret, 0, premasterSecret.length);
        byte[] tmp = new byte[sha1.getDigestSize()];
        sha1.doFinal(tmp, 0);

        md5.update(tmp, 0, tmp.length);

        tmp = new byte[md5.getDigestSize()];
        md5.doFinal(tmp, 0);

        out.write(tmp);

      }

      masterSecret = out.toByteArray();
    }
    catch (IOException ex) {
      throw new SSLException(SSLException.INTERNAL_ERROR,
                             ex.getMessage() == null ? ex.getClass().getName() :
                             ex.getMessage());
    }

  }

  private void calculatePreMasterSecret() {

/* DEBUG */ log.debug("Generating pre-master secret");

    premasterSecret = new byte[48];
    context.getRND().nextBytes(premasterSecret);
    premasterSecret[0] = (byte) SSLTransport.VERSION_MAJOR;
    premasterSecret[1] = (byte) SSLTransport.VERSION_MINOR;

  }

  private void debugBytes(byte[] b, String s) {

    System.out.print(s + ": ");

    for (int i = 0; i < b.length; i++) {

      System.out.print(Integer.toHexString( (int) (b[i] & 0xFF)));

    }

    System.out.println();

  }

  private void onServerHelloDoneMsg() throws SSLException {

    // Generate the premaster secret
    calculatePreMasterSecret();

    byte[] secret = null;

    try {

      // Encrypt the premaster secret
      BigInteger input = new BigInteger(1, premasterSecret);

      PublicKey key = x509.getPublicKey();

      if (key instanceof RsaPublicKey) {

        BigInteger padded = Rsa.padPKCS1(input, 0x02, 128,
                                         new com.maverick.crypto.security.
                                         SecureRandom());
        BigInteger s = Rsa.doPublic(padded, ( (RsaPublicKey) key).getModulus(),
                                    ( (RsaPublicKey) key).getPublicExponent());

        secret = s.toByteArray();

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -