SSL Handshaking Using Self-Signed Certs and SSLEngine (JSSE)

北城以北 提交于 2019-11-27 01:29:35

问题


I have been tasked to implement a custom/standalone Java webserver that can process SSL and non-SSL messages on the same port.

I have implemented an NIO server and its working quite well for non-SSL requests. I am having a heck of a time with the SSL piece and could really use some guidance.

Here's what I have done so far.

In order to distinguish between SSL and non-SSL messages, I check the first byte of the inbound request to see if it is a SSL/TLS message. Example:

   byte a = read(buf);
   if (totalBytesRead==1 && (a>19 && a<25)){
       parseTLS(buf);
   }

In the parseTLS() method I instantiate an SSLEngine like this:

   java.security.KeyStore ks = java.security.KeyStore.getInstance("JKS");
   java.security.KeyStore ts = java.security.KeyStore.getInstance("JKS");

   ks.load(new java.io.FileInputStream(keyStoreFile), passphrase);
   ts.load(new java.io.FileInputStream(trustStoreFile), passphrase);

   KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
   kmf.init(ks, passphrase);

   TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
   tmf.init(ts);

   SSLContext sslc = SSLContext.getInstance("TLS");     
   sslc.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);


   SSLEngine serverEngine = sslc.createSSLEngine();
   serverEngine.setUseClientMode(false);
   serverEngine.setEnableSessionCreation(true);
   serverEngine.setWantClientAuth(true);

Once the SSLEngine is instantiated, I process the inbound data using the unwrap/wrap methods using code straight out of the official JSSE Samples:

   log("----");

   serverResult = serverEngine.unwrap(inNetData, inAppData);
   log("server unwrap: ", serverResult);
   runDelegatedTasks(serverResult, serverEngine);

   log("----");

   serverResult = serverEngine.wrap(outAppData, outNetData);
   log("server wrap: ", serverResult);
   runDelegatedTasks(serverResult, serverEngine);

The first part of the handshake seems to work just fine. The client sends a handshake message and the server responds with a message with 4 records:

handshake (22)
- server_hello (2) 
- certificate (11) 
- server_key_exchange (12)
- certificate_request (13) 
- server_hello_done (14)

Next, the client sends a message with three parts:

handshake (22)
 - certificate (11)
 - client_key_exchange (16)

change_cipher_spec (20)
 - client_hello (1)

handshake (22)
 *** Encrypted Message ****

The SSLEngine unwraps the client request and parses the records but the wrap method produces 0 bytes with a handshake status of OK/NEED_UNWRAP. In other words, there's nothing for me to send back to the client and the handshake comes to a screeching halt.

This is where I am stuck.

In the debugger, I can see that the SSLEngine, specifically the ServerHandshaker, doesn't find any peer certs. This is rather obvious when I look at the certificate record from the client which is 0 bytes long. But why?

I can only assume that there's something wrong with the HelloServer response but I can't seem to put my finger on it. The server seems to be sending a valid cert but the client isn't sending anything back. Is there a problem with my keystore? Or is it the truststore? Or does it have something to do with the way I'm instantiating the SSLEngine? I'm stumped.

Couple other points:

  • The keystore and truststore referenced in the code snippit above were created using the following tutorial: http://www.techbrainwave.com/?p=953
  • I'm using Firefox 10 and IE 9 as the client to test the server. Same results for both web clients.
  • I'm using Sun/Oracle JDK 6 and Java Secure Socket Extension (JSSE) that comes bundled with it.

I look forward to any guidance you might have but please don't tell me I'm nuts or to use Netty or Grizzly or some other existing solution. Its just not an option at this time. I just want to understand what I'm doing wrong.

Thanks in Advance!


回答1:


You got NEED_UNWRAP, so do an unwrap. That in turn might give you BUFFER_UNDERFLOW, which means you have to do a read and retry the unwrap.

Similarly when you get NEED_WRAP, do a wrap: that in turn might give you BUFFER_OVERFLOW, which means you have to do a write and retry the wrap.

That wrap or unwrap might in turn might tell you to do another operation: wrap or unwrap.

Just do what it tells you to do.



来源:https://stackoverflow.com/questions/9604532/ssl-handshaking-using-self-signed-certs-and-sslengine-jsse

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!