使用自签名证书和SSLEngine(JSSE)的SSL握手 [英] SSL Handshaking Using Self-Signed Certs and SSLEngine (JSSE)

查看:925
本文介绍了使用自签名证书和SSLEngine(JSSE)的SSL握手的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的任务是实现一个可以在同一端口上处理SSL和非SSL消息的自定义/独立Java Web服务器。

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

我已经实现了一个NIO服务器,它非常适用于非SSL请求。我对SSL片段感到兴奋,并且可以使用一些指导。

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.

为了区分SSL和非SSL消息,我检查入站请求的第一个字节,看它是否是SSL / TLS消息。示例:

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);
   }

在parseTLS()方法中,我实例化一个SSLEngine:

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);

一旦SSLEngine被实例化,我使用unwrap / wrap方法直接使用代码处理入站数据官方 JSSE样本

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);

握手的第一部分似乎工作正常。客户端发送一个握手消息,服务器响应一条带有4条记录的消息:

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 ****

SSLEngine解包客户端请求并解析记录,但wrap方法产生0字节,握手状态为OK / NEED_UNWRAP。换句话说,没有什么可以让我回到客户端,握手就会嘎然而止。

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.

这是我被困的地方。

在调试器中,我可以看到SSLEngine,特别是ServerHandshaker,没有找到任何对等证书。当我从客户端查看长度为0字节的证书记录时,这是相当明显的。但是为什么呢?

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?

我只能假设HelloServer响应有问题,但我似乎无法指责它。服务器似乎正在发送有效的证书,但客户端没有发回任何内容。我的密钥库有问题吗?还是信托商店?或者它与我实例化SSLEngine的方式有关?我很难过。

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.

其他几点:


  • 密钥库和信任库在上面的代码snippit中引用的是使用以下教程创建的:
    http://www.techbrainwave.com/?p = 953

  • 我使用Firefox 10和IE 9作为测试服务器的客户端。两个Web客户端的结果相同。

  • 我正在使用随附的Sun / Oracle JDK 6和Java安全套接字扩展(JSSE)。

我期待您的任何指导,但请不要告诉我,我很疯狂或使用Netty或Grizzly或其他现有解决方案。它现在不是一个选项。我只是想了解我做错了什么。

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.

提前致谢!

推荐答案

你有NEED_UNWRAP,所以要解开。这反过来可能会给你BUFFER_UNDERFLOW,这意味着你必须进行读取并重试解包。

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.

同样当你得到NEED_WRAP时,做一个换行:反过来可能给你BUFFER_OVERFLOW,这意味着你必须进行写操作并重试包装。

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.

这篇关于使用自签名证书和SSLEngine(JSSE)的SSL握手的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆