Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ssl/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Netty SSL中的字段长度溢出_Java_Ssl_Openssl_Netty_Tls1.2 - Fatal编程技术网

Java Netty SSL中的字段长度溢出

Java Netty SSL中的字段长度溢出,java,ssl,openssl,netty,tls1.2,Java,Ssl,Openssl,Netty,Tls1.2,我使用Netty实现了一个带有安全套接字的服务器。我的sslHandler代码是: SslHandler sslHandler = SslContextBuilder .forServer(certFile, keyFile) .trustManager(trustFile) .clientAuth(ClientAuth.REQU

我使用Netty实现了一个带有安全套接字的服务器。我的sslHandler代码是:

SslHandler sslHandler = SslContextBuilder
                            .forServer(certFile, keyFile)
                            .trustManager(trustFile)
                            .clientAuth(ClientAuth.REQUIRE)
                            .build()
                            .newHandler(channel.alloc());
trustFile
是一个文件对象,包含大约700条证书文本,如:

-----开始证书----- Miiehdccawsgawbagijaor6+3G8C6f7MA0GCSqGSIb3DQEBCwUAMIGNMQswCQYD VQGEWJVUZESMBAGA1UECAWJQ2FSAWZVBWLHMRWGGYDVQKDBNDAXNJBYBTEXN0 ................................................................ IGHDYC519KBYSMFHUM9GXW35LPMFWSTBGYKBCMZJ1WMWXB/eZOK1SMjVQ/L/JVg -----结束证书-----

当我将服务器连接到

curl-k-v-eclient.pem--key client.key.pem--cacert rootCA.pemhttps://10.140.28.33:31069

将弹出一个异常:

11:00:18.636 [nioEventLoopGroup-3-2] WARN io.netty.channel.DefaultChannelPipeline - An exceptionCaught() event was fired, and it reached at the tail of the pipeline. It usually means the last handler in the pipeline did not handle the exception.
io.netty.handler.codec.DecoderException: java.lang.RuntimeException: Field length overflow, the field length (106142) should be less than 65536
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:459)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:265)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:340)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1334)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:362)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:348)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:926)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:134)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:644)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:579)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:496)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:458)
    at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858)
    at io.netty.util.concurrent.DefaultThreadFactory$DefaultRunnableDecorator.run(DefaultThreadFactory.java:138)
    at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.RuntimeException: Field length overflow, the field length (106142) should be less than 65536
    at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1476)
    at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:535)
    at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:813)
    at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
    at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
    at io.netty.handler.ssl.SslHandler$SslEngineType$3.unwrap(SslHandler.java:255)
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1162)
    at io.netty.handler.ssl.SslHandler.decode(SslHandler.java:1084)
    at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:489)
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:428)
    ... 16 common frames omitted
Caused by: java.lang.RuntimeException: Field length overflow, the field length (106142) should be less than 65536
    at sun.security.ssl.HandshakeOutStream.checkOverflow(HandshakeOutStream.java:231)
    at sun.security.ssl.HandshakeOutStream.putInt16(HandshakeOutStream.java:163)
    at sun.security.ssl.HandshakeMessage$CertificateRequest.send(HandshakeMessage.java:1442)
    at sun.security.ssl.HandshakeMessage.write(HandshakeMessage.java:143)
    at sun.security.ssl.ServerHandshaker.clientHello(ServerHandshaker.java:971)
    at sun.security.ssl.ServerHandshaker.processMessage(ServerHandshaker.java:224)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:1026)
    at sun.security.ssl.Handshaker$1.run(Handshaker.java:966)
    at sun.security.ssl.Handshaker$1.run(Handshaker.java:963)
    at java.security.AccessController.doPrivileged(Native Method)
    at sun.security.ssl.Handshaker$DelegatedTask.run(Handshaker.java:1416)
    at io.netty.handler.ssl.SslHandler.runDelegatedTasks(SslHandler.java:1301)
    at io.netty.handler.ssl.SslHandler.unwrap(SslHandler.java:1214)
    ... 19 common frames omitted
但是如果我在只剩下几个证书的情况下修剪信任文件,则不会发生错误。


这是一个JDK bug吗?我怎样才能避免它呢?

JSSE可能没有给出更清晰的警告,但有一个根本性的问题

当SSL/TLS服务器请求客户端身份验证时,它通常会在证书请求消息中发送客户端应使用的证书颁发机构列表,请参阅或更早版本。由于您信任大量的自签名证书,其中每个自签名者有效地充当自己的CA,这意味着您的服务器需要发送一个庞大的CA列表——但该列表的总字节数限制为65535字节。您的异常显示您正在尝试发送106142字节,该字节不符合65535字节的要求;这意味着您的证书名称(主题)平均约为150字节,在我看来,如果这些名称完全在您的企业中使用,那么这似乎有点偏高,因此可能不需要像公共web这样的全球唯一名称(特别是具有增强身份要求的EV)

如果您的所有客户端都知道要使用哪个证书而不被提示,一个可能的解决方法是让服务器将CA列表发送为空,这是允许的,但不鼓励这样做。JSSE只需从trustmanager的
getAcceptedAssuers()
方法中填充CertReq.CAlist,trustmanager API是为定制而设计的,因此您只需将真正的X509TrustManager包装成一个正常验证接收到的证书链,但将
getAcceptedAssuers()
作为空数组返回。对于实际的Java类(
SSLContext
etamici),这是相当容易的,但我不确定在哪里可以看到Netty的“改进”


但是一个更好的解决方案,正如EJP在评论中指出的那样,不是单独信任大量的自签名证书,而是让CA发布客户端证书,然后服务器只需要信任该CA(以及它发布的证书)CertReq只自动指定该CA。如果您还没有合适的已建立CA可供使用,则有许多选项可用于您自己的CA,在此处的其他Qs和其他堆栈(IME主要是security.SX unix.SX和serverfault)中讨论,但是考虑到您使用的是Java,请记住,因为j7
keytool-gencert
执行的是一个最小但可用的CA函数。(除了键对和CSR生成(这是
keytool
在黑暗时代所做的工作)。

JSSE没有给出更清晰的警告可能是一个缺陷,但存在一个根本问题

当SSL/TLS服务器请求客户端身份验证时,它通常会在证书请求消息中发送客户端应使用的证书颁发机构列表,请参阅或更早版本。由于您信任大量的自签名证书,其中每个自签名者有效地充当自己的CA,这意味着您的服务器需要发送一个庞大的CA列表——但该列表的总字节数限制为65535字节。您的异常显示您正在尝试发送106142字节,该字节不符合65535字节的要求;这意味着您的证书名称(主题)平均约为150字节,在我看来,如果这些名称完全在您的企业中使用,那么这似乎有点偏高,因此可能不需要像公共web这样的全球唯一名称(特别是具有增强身份要求的EV)

如果您的所有客户端都知道要使用哪个证书而不被提示,一个可能的解决方法是让服务器将CA列表发送为空,这是允许的,但不鼓励这样做。JSSE只需从trustmanager的
getAcceptedAssuers()
方法中填充CertReq.CAlist,trustmanager API是为定制而设计的,因此您只需将真正的X509TrustManager包装成一个正常验证接收到的证书链,但将
getAcceptedAssuers()
作为空数组返回。对于实际的Java类(
SSLContext
etamici),这是相当容易的,但我不确定在哪里可以看到Netty的“改进”


但是一个更好的解决方案,正如EJP在评论中指出的那样,不是单独信任大量的自签名证书,而是让CA发布客户端证书,然后服务器只需要信任该CA(以及它发布的证书)CertReq只自动指定该CA。如果您还没有合适的已建立CA可供使用,则有许多选项可用于您自己的CA,在此处的其他Qs和其他堆栈(IME主要是security.SX unix.SX和serverfault)中讨论,但是考虑到您使用的是Java,请记住,因为j7
keytool-gencert
执行的是一个最小但可用的CA函数。(除了密钥对和CSR生成之外,
keytool
早在黑暗时代就已经完成了。)

请问,你能展示一下你用来修剪信任文件的代码吗?@Jamin,我只是删除了很多证书文本,以使信任文件变小。为什么你需要700个信任证书?@EJP,因为我需要客户端身份验证,有1000多个客户端是slef签名的。然后你使用了错误的技术,因为你破坏了这个。您应该使用一个受信任的签名者。一个要信任的证书,而不是>1000。请显示用于修剪信任文件的代码?@Jam