All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cn.tom.transport.ssl.SSLHandshakeClient Maven / Gradle / Ivy

The newest version!
package cn.tom.transport.ssl;

import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.security.KeyStore;
import java.util.Iterator;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.SSLEngineResult;
import javax.net.ssl.SSLEngineResult.HandshakeStatus;
import javax.net.ssl.SSLEngineResult.Status;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManagerFactory;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SSLHandshakeClient {
    private static Logger logger = LoggerFactory.getLogger(SSLHandshakeClient.class);
    private SocketChannel sc;
    private SSLEngine sslEngine;
    private Selector selector;
    private HandshakeStatus hsStatus;
    private Status status;
    private ByteBuffer myNetData;
    private ByteBuffer myAppData;
    private ByteBuffer peerNetData;
    private ByteBuffer peerAppData;
    private ByteBuffer dummy = ByteBuffer.wrap(new byte[]{1,2,3});
    public void run() throws Exception {
        char[] password = "123456".toCharArray();
        KeyStore trustStore = KeyStore.getInstance("JKS");
        InputStream in = this.getClass().getResourceAsStream("clienttruststore.jks");
        trustStore.load(in, password);
        TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(trustStore);
        SSLContext sslContext = SSLContext.getInstance("SSL");
        sslContext.init(null, tmf.getTrustManagers(), null);
        sslEngine = sslContext.createSSLEngine();
        sslEngine.setUseClientMode(true);
        SSLSession session = sslEngine.getSession();
        myAppData = ByteBuffer.allocate(session.getApplicationBufferSize());
        myNetData = ByteBuffer.allocate(session.getPacketBufferSize());
        peerAppData = ByteBuffer.allocate(session.getApplicationBufferSize());
        peerNetData = ByteBuffer.allocate(session.getPacketBufferSize());
        peerNetData.clear();
        SocketChannel channel = SocketChannel.open();
        channel.configureBlocking(false);
        selector = Selector.open();
        channel.register(selector, SelectionKey.OP_CONNECT);
        channel.connect(new InetSocketAddress("localhost", 443));
        sslEngine.beginHandshake();
        hsStatus = sslEngine.getHandshakeStatus();
        System.out.println(hsStatus == HandshakeStatus.NEED_UNWRAP);
        System.out.println(hsStatus == HandshakeStatus.NEED_WRAP);
        while (true) {
            selector.select();
            Iterator it = selector.selectedKeys().iterator();
            while (it.hasNext()) {
                SelectionKey selectionKey = it.next();
                it.remove();
                handleSocketEvent(selectionKey);
            }
        }
    }
    private void handleSocketEvent(SelectionKey key) throws IOException {
        if (key.isConnectable()) {
            sc = (SocketChannel) key.channel();
            if (sc.isConnectionPending()) {
                sc.finishConnect();
            }
            doHandshake();
            sc.register(selector, SelectionKey.OP_READ);
        }
        if (key.isReadable()) {
            sc = (SocketChannel) key.channel();
            doHandshake();
            if (hsStatus == HandshakeStatus.FINISHED) {
                logger.info("Client handshake completes... ...");
                key.cancel();
                sc.close();
            }
        }
    }
    private void doHandshake() throws IOException {
        SSLEngineResult result;
        int count = 0;
        while (hsStatus != HandshakeStatus.FINISHED) {
            logger.info("handshake status: " + hsStatus);
            switch (hsStatus) {
            case NEED_TASK:
                Runnable runnable;
                while ((runnable = sslEngine.getDelegatedTask()) != null) {
                    runnable.run();
                }
                hsStatus = sslEngine.getHandshakeStatus();
                break;
            case NEED_UNWRAP:
                count = sc.read(peerNetData);
                if (count < 0) {
                    logger.info("no data is read for unwrap.");
                    break;
                } else {
                    logger.info("data read: " + count);
                }
                peerNetData.flip();
                peerAppData.clear();
                do {
                    result = sslEngine.unwrap(peerNetData, peerAppData);
                    logger.info("Unwrapping:\n" + result);
                    // During an handshake renegotiation we might need to
                    // perform
                    // several unwraps to consume the handshake data.
                } while (result.getStatus() == SSLEngineResult.Status.OK
                        && result.getHandshakeStatus() == SSLEngineResult.HandshakeStatus.NEED_UNWRAP
                        && result.bytesProduced() == 0);
                if (peerAppData.position() == 0 && result.getStatus() == SSLEngineResult.Status.OK
                        && peerNetData.hasRemaining()) {
                    result = sslEngine.unwrap(peerNetData, peerAppData);
                    logger.info("Unwrapping:\n" + result);
                }
                hsStatus = result.getHandshakeStatus();
                status = result.getStatus();
                assert status != status.BUFFER_OVERFLOW : "buffer not overflow." + status.toString();
                // Prepare the buffer to be written again.
                peerNetData.compact();
                // And the app buffer to be read.
                peerAppData.flip();
                break;
            case NEED_WRAP:
                myNetData.clear();
                
                result = sslEngine.wrap(dummy, myNetData);
                hsStatus = result.getHandshakeStatus();
                status = result.getStatus();
                while (status != Status.OK) {
                    logger.info("status: " + status);
                    switch (status) {
                    case BUFFER_OVERFLOW:
                        break;
                    case BUFFER_UNDERFLOW:
                        break;
                    }
                }
                myNetData.flip();
                count = sc.write(myNetData);
                if (count <= 0) {
                    logger.info("No data is written.");
                } else {
                    logger.info("Written data: " + count);
                }
                break;
            }
        }
    }
    public static void main(String[] args) throws Exception {
        new SSLHandshakeClient().run();
    }
}  




© 2015 - 2024 Weber Informatics LLC | Privacy Policy