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

📄 sslenginesimpledemo.java

📁 Sun公司官方网站上下载的JDK文档
💻 JAVA
字号:
/* * %W% %E% * * Copyright (c) 2004 Sun Microsystems, Inc. All Rights Reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * -Redistribution of source code must retain the above copyright *  notice, this list of conditions and the following disclaimer. * * -Redistribution in binary form must reproduce the above copyright *  notice, this list of conditions and the following disclaimer in the *  documentation and/or other materials provided with the *  distribution. * * Neither the name of Sun Microsystems, Inc. or the names of * contributors may be used to endorse or promote products derived from * this software without specific prior written permission. * * This software is provided "AS IS," without a warranty of any kind. * ALL EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, * INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A * PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN * MIDROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR * ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR * DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN * OR ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR * FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE * DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY, * ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF * SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. * * You acknowledge that this software is not designed, licensed or * intended for use in the design, construction, operation or * maintenance of any nuclear facility. *//** * A SSLEngine usage example which simplifies the presentation * by removing the I/O and multi-threading concerns. * * The demo creates two SSLEngines, simulating a client and server. * The "transport" layer consists two ByteBuffers:  think of them * as directly connected pipes. * * Note, this is a *very* simple example: real code will be much more * involved.  For example, different threading and I/O models could be * used, transport mechanisms could close unexpectedly, and so on. * * When this application runs, notice that several messages * (wrap/unwrap) pass before any application data is consumed or * produced.  (For more information, please see the SSL/TLS * specifications.)  There may several steps for a successful handshake, * so it's typical to see the following series of operations: * *	client		server		message *	======		======		======= *	wrap()		...		ClientHello *	...		unwrap()	ClientHello *	...		wrap()		ServerHello/Certificate *	unwrap()	...		ServerHello/Certificate *	wrap()		...		ClientKeyExchange *	wrap()		...		ChangeCipherSpec *	wrap()		...		Finished *	...		unwrap()	ClientKeyExchange *	...		unwrap()	ChangeCipherSpec *	...		unwrap()	Finished *	...		wrap()		ChangeCipherSpec *	...		wrap()		Finished *	unwrap()	...		ChangeCipherSpec *	unwrap()	...		Finished */import javax.net.ssl.*;import javax.net.ssl.SSLEngineResult.*;import java.io.*;import java.security.*;import java.nio.*;public class SSLEngineSimpleDemo {    /*     * Enables logging of the SSLEngine operations.     */    private static boolean logging = true;    /*     * Enables the JSSE system debugging system property:     *     *     -Djavax.net.debug=all     *     * This gives a lot of low-level information about operations underway,     * including specific handshake messages, and might be best examined     * after gaining some familiarity with this application.     */    private static boolean debug = false;    private SSLContext sslc;    private SSLEngine clientEngine;	// client Engine    private ByteBuffer clientOut;	// write side of clientEngine    private ByteBuffer clientIn;	// read side of clientEngine    private SSLEngine serverEngine;	// server Engine    private ByteBuffer serverOut;	// write side of serverEngine    private ByteBuffer serverIn;	// read side of serverEngine    /*     * For data transport, this example uses local ByteBuffers.  This     * isn't really useful, but the purpose of this example is to show     * SSLEngine concepts, not how to do network transport.     */    private ByteBuffer cTOs;		// "reliable" transport client->server    private ByteBuffer sTOc;		// "reliable" transport server->client    /*     * The following is to set up the keystores.     */    private static String keyStoreFile = "testkeys";    private static String trustStoreFile = "testkeys";    private static String passwd = "passphrase";    /*     * Main entry point for this demo.     */    public static void main(String args[]) throws Exception {	if (debug) {	    System.setProperty("javax.net.debug", "all");	}	SSLEngineSimpleDemo demo = new SSLEngineSimpleDemo();	demo.runDemo();	System.out.println("Demo Completed.");    }    /*     * Create an initialized SSLContext to use for this demo.     */    public SSLEngineSimpleDemo() throws Exception {	KeyStore ks = KeyStore.getInstance("JKS");	KeyStore ts = KeyStore.getInstance("JKS");	char[] passphrase = "passphrase".toCharArray();	ks.load(new FileInputStream(keyStoreFile), passphrase);	ts.load(new FileInputStream(trustStoreFile), passphrase);	KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");	kmf.init(ks, passphrase);	TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");	tmf.init(ts);	SSLContext sslCtx = SSLContext.getInstance("TLS");	sslCtx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);	sslc = sslCtx;    }    /*     * Run the demo.     *     * Sit in a tight loop, both engines calling wrap/unwrap regardless     * of whether data is available or not.  We do this until both engines     * report back they are closed.     *     * The main loop handles all of the I/O phases of the SSLEngine's     * lifetime:     *     *     initial handshaking     *     application data transfer     *     engine closing     *     * One could easily separate these phases into separate     * sections of code.     */    private void runDemo() throws Exception {	boolean dataDone = false;	createSSLEngines();	createBuffers();	SSLEngineResult clientResult;	// results from client's last operation	SSLEngineResult serverResult;	// results from server's last operation	/*	 * Examining the SSLEngineResults could be much more involved,	 * and may alter the overall flow of the application.	 *	 * For example, if we received a BUFFER_OVERFLOW when trying	 * to write to the output pipe, we could reallocate a larger	 * pipe, but instead we wait for the peer to drain it.	 */	while (!isEngineClosed(clientEngine) ||		!isEngineClosed(serverEngine)) {	    log("================");	    clientResult = clientEngine.wrap(clientOut, cTOs);	    log("client wrap: ", clientResult);	    runDelegatedTasks(clientResult, clientEngine);	    serverResult = serverEngine.wrap(serverOut, sTOc);	    log("server wrap: ", serverResult);	    runDelegatedTasks(serverResult, serverEngine);	    cTOs.flip();	    sTOc.flip();	    log("----");	    clientResult = clientEngine.unwrap(sTOc, clientIn);	    log("client unwrap: ", clientResult);	    runDelegatedTasks(clientResult, clientEngine);	    serverResult = serverEngine.unwrap(cTOs, serverIn);	    log("server unwrap: ", serverResult);	    runDelegatedTasks(serverResult, serverEngine);	    cTOs.compact();	    sTOc.compact();	    /*	     * After we've transfered all application data between the client	     * and server, we close the clientEngine's outbound stream.	     * This generates a close_notify handshake message, which the	     * server engine receives and responds by closing itself.	     *	     * In normal operation, each SSLEngine should call	     * closeOutbound().  To protect against truncation attacks,	     * SSLEngine.closeInbound() should be called whenever it has	     * determined that no more input data will ever be	     * available (say a closed input stream).	     */	    if (!dataDone && (clientOut.limit() == serverIn.position()) &&		    (serverOut.limit() == clientIn.position())) {		/*		 * A sanity check to ensure we got what was sent.		 */		checkTransfer(serverOut, clientIn);		checkTransfer(clientOut, serverIn);		log("\tClosing clientEngine's *OUTBOUND*...");		clientEngine.closeOutbound();		// serverEngine.closeOutbound();		dataDone = true;	    }	}    }    /*     * Using the SSLContext created during object creation,     * create/configure the SSLEngines we'll use for this demo.     */    private void createSSLEngines() throws Exception {	/*	 * Configure the serverEngine to act as a server in the SSL/TLS	 * handshake.  Also, require SSL client authentication.	 */	serverEngine = sslc.createSSLEngine();	serverEngine.setUseClientMode(false);	serverEngine.setNeedClientAuth(true);	/*	 * Similar to above, but using client mode instead.	 */	clientEngine = sslc.createSSLEngine("client", 80);	clientEngine.setUseClientMode(true);    }    /*     * Create and size the buffers appropriately.     */    private void createBuffers() {	/*	 * We'll assume the buffer sizes are the same	 * between client and server.	 */	SSLSession session = clientEngine.getSession();	int appBufferMax = session.getApplicationBufferSize();	int netBufferMax = session.getPacketBufferSize();	/*	 * We'll make the input buffers a bit bigger than the max needed	 * size, so that unwrap()s following a successful data transfer	 * won't generate BUFFER_OVERFLOWS.	 *	 * We'll use a mix of direct and indirect ByteBuffers for	 * tutorial purposes only.  In reality, only use direct	 * ByteBuffers when they give a clear performance enhancement.	 */	clientIn = ByteBuffer.allocate(appBufferMax + 50);	serverIn = ByteBuffer.allocate(appBufferMax + 50);	cTOs = ByteBuffer.allocateDirect(netBufferMax);	sTOc = ByteBuffer.allocateDirect(netBufferMax);	clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes());	serverOut = ByteBuffer.wrap("Hello Client, I'm Server".getBytes());    }    /*     * If the result indicates that we have outstanding tasks to do,     * go ahead and run them in this thread.     */    private static void runDelegatedTasks(SSLEngineResult result,	    SSLEngine engine) throws Exception {	if (result.getHandshakeStatus() == HandshakeStatus.NEED_TASK) {	    Runnable runnable;	    while ((runnable = engine.getDelegatedTask()) != null) {		log("\trunning delegated task...");		runnable.run();	    }	    HandshakeStatus hsStatus = engine.getHandshakeStatus();	    if (hsStatus == HandshakeStatus.NEED_TASK) {		throw new Exception(		    "handshake shouldn't need additional tasks");	    }	    log("\tnew HandshakeStatus: " + hsStatus);	}    }    private static boolean isEngineClosed(SSLEngine engine) {	return (engine.isOutboundDone() && engine.isInboundDone());    }    /*     * Simple check to make sure everything came across as expected.     */    private static void checkTransfer(ByteBuffer a, ByteBuffer b)	    throws Exception {	a.flip();	b.flip();	if (!a.equals(b)) {	    throw new Exception("Data didn't transfer cleanly");	} else {	    log("\tData transferred cleanly");	}	a.position(a.limit());	b.position(b.limit());	a.limit(a.capacity());	b.limit(b.capacity());    }    /*     * Logging code     */    private static boolean resultOnce = true;    private static void log(String str, SSLEngineResult result) {	if (!logging) {	    return;	}	if (resultOnce) {	    resultOnce = false;	    System.out.println("The format of the SSLEngineResult is: \n" +		"\t\"getStatus() / getHandshakeStatus()\" +\n" +		"\t\"bytesConsumed() / bytesProduced()\"\n");	}	HandshakeStatus hsStatus = result.getHandshakeStatus();	log(str +	    result.getStatus() + "/" + hsStatus + ", " +	    result.bytesConsumed() + "/" + result.bytesProduced() +	    " bytes");	if (hsStatus == HandshakeStatus.FINISHED) {	    log("\t...ready for application data");	}    }    private static void log(String str) {	if (logging) {	    System.out.println(str);	}    }}

⌨️ 快捷键说明

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