对于我正在处理的应用,我需要使用TLS上的TCP套接字.我已经通过了几十个例子,虽然我没有遇到握手问题,但我似乎无法通过任何方式读取输入流(尝试了很多,包括readline(),读取到字符数组等).每次我尝试,应用程序冻结在那个位置.如果我调试,它永远不会进入下一行代码.
在尝试的解决方案中,我决定转而使用SSLEngine,因为这应该是针对SSL的java.nio的Java 1.5答案.但是,我找到了一个例子(这里:http://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/samples/sslengine/SSLEngineSimpleDemo.java),这有点令人困惑我,我没有成功实施它.当我尝试时,unwrap()调用产生一个空缓冲区,我知道(在命令行上使用OpenSSL),有问题的服务将数据推回管道.
建议是受欢迎的,我已经烧掉了太多时间.这是相关的代码:
SSLEngine engine = sslContext.createSSLEngine(uri.getHost(), uri.getPort());
engine.setUseClientMode(true);
engine.beginHandshake();
SSLSession session = engine.getSession();
int bufferMax = session.getPacketBufferSize();
int appBufferMax = session.getApplicationBufferSize() + 50;
ByteBuffer cTo = ByteBuffer.allocateDirect(bufferMax);
ByteBuffer sTo = ByteBuffer.allocateDirect(bufferMax);
ByteBuffer out = ByteBuffer.wrap(sessionId.getBytes());
ByteBuffer in = ByteBuffer.allocate(appBufferMax);
debug("sending secret");
SSLEngineResult rslt = engine.wrap(out, cTo);
debug("first result: " + rslt.toString());
sTo.flip();
rslt = engine.unwrap(sTo, in);
debug("next result" + rslt.toString());
Run Code Online (Sandbox Code Playgroud) 我在我的代理服务器上启用了SSL,发现性能已经从每秒大约17,000个请求降低到每秒5k请求.我按照Netty的安全聊天示例中的代码进行操作,我认为我没有做过任何不同的事情.
我写了一个虚拟服务器,看看我是否在我的代理上犯了一些错误.在正常的http模式下运行虚拟SSL服务器每秒可以提供大约50k的请求.当我在虚拟服务器上启用SSL时,每秒降低到28k个请求.
有什么我做错了吗?有什么我想念的吗?
我正在使用JDK 6编译代码,在JDK 7u4上运行.我也在使用Netty-3.5.0.我正在使用zeusbench进行测试.测试参数为:zeusbench -n 10000 -c 100 -k -C RC4_SHA"https:///"
资料来源:http://pastebin.com/iahqr3zT
编辑1:我通过JProfiler运行虚拟服务器.管道工厂中的SSLContext.createSSLEngine调用(平均)需要55,005微秒(该平均值是从该方法的540次调用计算得出的).
channelConnected中的SslHandler.handshake调用(平均)需要46,284微秒(该平均值是从该方法的540次调用计算得出的).
我知道Netty可以对createSSLEngine的调用做些什么,但SslHandler.handshake可以更好地调整吗?它的使用时间几乎和发动机本身一样长.
我看到SSLEngine有一个奇怪的问题,想知道我的代码或SSLEngine是否有问题。这是我看到事物的顺序
最重要的问题:如何彻底调试?如何以某种方式“看到”每条消息?我可以很容易地捕获字节流,但是是否有一些库可以将其解析为SSL握手对象?
第298行(记录先前的握手状态)到第328行(在此将异常与信息一起抛出)是此处的相关代码
堆栈跟踪为
2019-06-21 08:58:24,562 [-] [webpiecesThreadPool6] Caller+1 at org.webpieces.util.threading.SessionExecutorImpl$RunnableWithKey.run(SessionExecutorImpl.java:123)
ERROR: Uncaught Exception
java.lang.IllegalStateException: Engine issue. hsStatus=NEED_WRAP status=OK previous hsStatus=NEED_WRAP
at org.webpieces.ssl.impl.AsyncSSLEngine3Impl.sendHandshakeMessageImpl(AsyncSSLEngine3Impl.java:328)
at org.webpieces.ssl.impl.AsyncSSLEngine3Impl.sendHandshakeMessage(AsyncSSLEngine3Impl.java:286)
at org.webpieces.ssl.impl.AsyncSSLEngine3Impl.doHandshakeWork(AsyncSSLEngine3Impl.java:133)
at org.webpieces.ssl.impl.AsyncSSLEngine3Impl.doHandshakeLoop(AsyncSSLEngine3Impl.java:246)
at org.webpieces.ssl.impl.AsyncSSLEngine3Impl.unwrapPacket(AsyncSSLEngine3Impl.java:210)
at org.webpieces.ssl.impl.AsyncSSLEngine3Impl.doWork(AsyncSSLEngine3Impl.java:109)
at org.webpieces.ssl.impl.AsyncSSLEngine3Impl.feedEncryptedPacket(AsyncSSLEngine3Impl.java:82)
at org.webpieces.nio.impl.ssl.SslTCPChannel$SocketDataListener.incomingData(SslTCPChannel.java:175)
at org.webpieces.nio.impl.threading.ThreadDataListener$1.run(ThreadDataListener.java:26)
at org.webpieces.util.threading.SessionExecutorImpl$RunnableWithKey.run(SessionExecutorImpl.java:121)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?我该如何真正深入研究呢?我的喜好是一个库,它使用字节并吐出代表每个握手消息或解密数据包的ssl对象(带有原始加密内容附带的任何标头信息)。
具体来说,这是上面提到的代码
HandshakeStatus previousStatus = sslEngine.getHandshakeStatus();
//CLOSE and all the threads that call feedPlainPacket can have contention on wrapping to encrypt and
//must synchronize on sslEngine.wrap …Run Code Online (Sandbox Code Playgroud) Java 11 随TLSv1.3支持发布,默认使用。
它在 HTTPS 和 SSL 套接字的上下文中工作正常,但似乎在使用时SSLEngine由于TLSv1.3行为的变化而存在额外的障碍。
因此,通过NIOusing有一个强大的通信实现,SSLEngine当TLSv1.3启用时不再起作用。没有明显的错误,以异常或 SSL 错误的形式,两个节点只会来回发送 wrap/unwrap 消息并最终超时。
我对使用 TLSv1.2 的 SSLEngine 和使用 TLSv1.3 的 SSLEngine 之间的行为变化的确切列表感兴趣,如果可能的话,还有它们之间的迁移清单。不幸的是,Java 11 的 SSLEngine javadocs 没有这些信息——Java 11 中没有新方法,也没有对 TLSv1.3 的引用。
我想将netty用于启用了TLS并使用(wss://)架构的websockets.
所以我想我应该这样工作:WebSocketServerHandler现在应该扩展SslHandler.所以我基本上只需要在WebSocketServerPipelineFactory中设置一个SSLEngine .我可以将引擎传递给安全处理程序:
SSLEngine sslEngine = SSLContext.getDefault().createSSLEngine();
pipeline.addLast("handler", new WebSocketServerHandler(sslEngine));
Run Code Online (Sandbox Code Playgroud)
这种方法通常是正确的吗(如果方法是正确的) - 如何设置SSLEngine(我的证书和私钥/公钥作为可用文件).我找不到任何例子!
谢谢.
这是我的代码:
WebClient.create().post()
.uri(URI.create(url))
.header("Authorization",
"Basic " + Base64Utils.encodeToString(("username:password").getBytes(UTF_8)))
.body(Mono.just(requestBody), Object.class)
.retrieve()
.bodyToMono(responseType)
Run Code Online (Sandbox Code Playgroud)
我同时从多个线程调用这个函数。当我在一次运行中只调用它大约 20~30 次时,它工作得很好。但是当我在大约 2 分钟内调用它 500~600 次(对于同一个 URL)时,它会抛出
javax.net.ssl.SSLException: SSLEngine closed already
at io.netty.handler.ssl.SslHandler.wrap(...)(Unknown Source)
Run Code Online (Sandbox Code Playgroud)
编辑
我尝试只创建一个实例WebClient,但它仍然抛出相同的异常
我在这里找到了一个如何实现Java SSLEngine的例子.不幸的是,服务器的源代码不完整.你知道我在哪里可以找到教程中的完整源代码吗?
当我在 Java 应用程序上运行客户端握手进程以建立 SSL 连接时,我会SSLException第二次调用 wrap 方法。我知道在这一点上,客户端将CLientKeyExchange和发送ChangeCipherSpec到服务器。我从异常中得到的错误消息是“一般 SSLEngine 问题”。也许我需要发送的证书有问题?
这是异常堆栈的详细信息:
Details: General SSLEngine problem
Trace detail #0: com.sun.net.ssl.internal.ssl.Handshaker.checkThrown(Handshaker.java:994)
Trace detail #1: com.sun.net.ssl.internal.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:459)
Trace detail #2: com.sun.net.ssl.internal.ssl.SSLEngineImpl.writeAppRecord(SSLEngineImpl.java:1058)
Trace detail #3: com.sun.net.ssl.internal.ssl.SSLEngineImpl.wrap(SSLEngineImpl.java:1030)
Trace detail #4: javax.net.ssl.SSLEngine.wrap(SSLEngine.java:411)
Trace detail #5: epic.clarity.extract.CRSslSocketHandler.doHandshake(CRSslSocketHandler.java:333)
Trace detail #6: epic.clarity.extract.CRSslSocketHandler.readAndUnwrap(CRSslSocketHandler.java:282)
Trace detail #7: epic.clarity.extract.CRSslSocketHandler.doHandshake(CRSslSocketHandler.java:322)
Trace detail #8: epic.clarity.extract.CRSslSocketHandler.readAndUnwrap(CRSslSocketHandler.java:282)
Trace detail #9: epic.clarity.extract.CRSslSocketHandler.doHandshake(CRSslSocketHandler.java:322)
Trace detail #10: epic.clarity.extract.CRSslSocketHandler.ReadExtFile(CRSslSocketHandler.java:159)
Run Code Online (Sandbox Code Playgroud)
这是我的代码,握手开始于Read方法:
public class CRSslSocketHandler extends CRSocketHandler{
private SSLEngine _engine;
private SSLEngineResult.HandshakeStatus hsStatus;
/**
* …Run Code Online (Sandbox Code Playgroud) 我正在编写一个使用SSLEngine和NIO的应用程序,我编写了客户端和服务器.客户端能够连接到服务器,在他连接后,我希望他能够执行会话恢复/重新协商,但目前没有运气..
由于使用SSLEngine的代码非常大(SSLEngine的使用非常复杂!),我将编写一个简单的伪代码来演示这种情况:
Server:
global sslcontext initialized once
await new client
client.sslEngine = create new server ssl engine using the global sslcontext
client.handleHandshake and wait for it to be done
handle client.
Client:
global sslcontext initialized once
sslEngine = create new client ssl engine using the global sslcontext
performHandshake and wait for it to be done
disconnect (close gracefully the connection)
sslEngine = create new client ssl engine using the global sslcontext
configure engine to not allow session creation
performHandshake and …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
SSLContext sslContext = SSLContext.getInstance("TLS", BouncyCastleProvider.PROVIDER_NAME);
sslContext.init(keyManagerFactory.getKeyManagers(), null, null);
SSLEngine sslEngine = sslContext.createSSLEngine();
String[] suites = { "TLS_ECDHE_ECDSA_WITH_AES_128_CCM_8" };
sslEngine.setEnabledCipherSuites(suites);
Run Code Online (Sandbox Code Playgroud)
谢谢。
编辑:我发现我应该使用BouncyCastleJsseProviderwhich 需要一个SecureRandom对象,如下所示:
sslContext.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
Run Code Online (Sandbox Code Playgroud)
使用新的提供程序后,我在我的代码库中得到以下堆栈跟踪,据我所知,它应该像以前一样工作:
Aug 17, 2017 8:47:32 PM org.bouncycastle.jsse.provider.ProvTlsServer notifyAlertRaised
INFO: Server raised fatal(2) handshake_failure(40) alert: Failed to read record
org.bouncycastle.tls.TlsFatalAlert: handshake_failure(40)
at org.bouncycastle.tls.AbstractTlsServer.getSelectedCipherSuite(Unknown Source)
at org.bouncycastle.jsse.provider.ProvTlsServer.getSelectedCipherSuite(Unknown Source)
at org.bouncycastle.tls.TlsServerProtocol.sendServerHelloMessage(Unknown Source)
at org.bouncycastle.tls.TlsServerProtocol.handleHandshakeMessage(Unknown Source)
at org.bouncycastle.tls.TlsProtocol.processHandshakeQueue(Unknown Source)
at org.bouncycastle.tls.TlsProtocol.processRecord(Unknown Source)
at org.bouncycastle.tls.RecordStream.readRecord(Unknown Source)
at org.bouncycastle.tls.TlsProtocol.safeReadRecord(Unknown Source)
at org.bouncycastle.tls.TlsProtocol.offerInput(Unknown Source)
at …Run Code Online (Sandbox Code Playgroud)