TLS-Package 后的神秘字节 [英] Mysterious byte after TLS-Package

查看:30
本文介绍了TLS-Package 后的神秘字节的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建从 Java 到 Vala 服务器的 SSL TCP 连接.一切正常,直到我向服务器发送第二个包.(也是第一个包裹发送罚款).服务器只接收第二个包的第一个字节(在这种情况下为1"),没有别的,但是如果我在没有 SSL 的情况下连接到服务器,一切正常.我认为服务器不是问题,因为来自另一个 Vala 客户端的所有其他连接都运行良好.

I am trying to create a SSL TCP Connection from Java to a Vala Server. Everything works fine until I send a second package to the server. (also the first package sends fine). The server only receives the first byte (in this case the "1") of the second package, nothing else, but if I connect to the server without SSL everything works fine. I think that the server isn't the problem, because every other connection from another Vala client works pretty well.

我使用的是不受信任的证书,因此我创建了一个自定义 TrustManager,并且我使用的是 OpenJDK 7(基本操作系统 - Linux).这是我的代码:

I'm using an unstrusted Certificate, so I created a custom TrustManager and I'm using OpenJDK 7 (Elementary OS - Linux). Here's my code:

//Main:
SSLHandler handler = new SSLHandler();
handler.createSecureSocket("localhost", 7431);

byte[] data = {1,4,1,1,1,1};
handler.getOutputStream().write(data);
handler.getOutputStream().write(data);

// SSLHandler
public class SSLHandler {

    // SSL Socket erstellen
    SSLSocket sslSocket;

    public void createSecureSocket(String ip, int port) throws UnknownHostException, IOException, KeyManagementException, NoSuchAlgorithmException {

        SSLSocketFactory factory = (SSLSocketFactory) new DefaultTrustManager().createSSLFactory("TLS");

        sslSocket = (SSLSocket) factory.createSocket(ip, port);
    }

    public OutputStream getOutputStream() throws IOException {
        return sslSocket.getOutputStream();
    }

    public InputStream getInputStream() throws IOException {
        return sslSocket.getInputStream();
    }

}

//Custom Trust Manager
public class DefaultTrustManager implements X509TrustManager {

    @Override
    public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

    @Override
    public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {}

    @Override
    public X509Certificate[] getAcceptedIssuers() {
        return null;
    }

    public SSLSocketFactory createSSLFactory(String protocol) throws NoSuchAlgorithmException, KeyManagementException {
        SSLContext sslContext = SSLContext.getInstance(protocol);

        TrustManager[] byPassTrustManager = new TrustManager[] {this};

        sslContext.init(null, byPassTrustManager, new SecureRandom());

        return sslContext.getSocketFactory();
    }
}

有人知道这个问题的解决方案吗?

Does anybody know a solution for this problem?

推荐答案

TLDR:进行多次接收.

TLS/SSL 与 TCP 一样被定义为流服务,并且不保证保留记录边界,仅按顺序传送字节 - 或者如果不可能,请指出错误.例如,在 TCP 或 TLS/SSL 中,如果一方执行 3 个每次 1000 字节的发送操作,而接收方执行一系列接收操作,则这些操作可能会收到 500、700、1200 和 600 字节.通常,接收器必须在必要时进行多次接收以接收多于一个字节的数据结构.这可以使用分隔符来完成,例如 SMTP:将标题作为行读取,直到获得空行,将正文(数据)作为行读取,直到获得仅由点"(.) 组成的行.或者简单地计数:继续阅读,直到总共获得 N 个字节.例如,HTTP 和 HTTPS 使用这两者(在某些情况下使用更多).

TLS/SSL like TCP is defined as a stream service and does NOT guarantee to preserve record boundaries, only to deliver the bytes in order -- or if that's impossible, indicate the error. For example, in either TCP or TLS/SSL if one party does 3 send operations of 1000 bytes each, and the receiver does a series of receive operations, those might receive 500, 700, 1200, and 600 bytes. In general a receiver must do multiple receives if necessary to receive a data structure of more than one byte. This can be done with delimiters, like SMTP: read header as lines until you get an empty line, and body (data) until you get a line consisting solely of a 'dot' (.). Or simply with a count: keep reading until you get N bytes total. HTTP and HTTPS for example uses both of these (and more in some cases).

在实践中,TCP 实现经常拆分大于约 1000 字节的数据,这是由于它们对数据进行分段以进行传输和重新组合的方式.因此,大约在 1982 年之后还没有教过这个问题的 TCP 程序员从经验中学到了继续阅读直到完成".

In practice TCP implementations have very often split data larger than about 1000 bytes, due to the way they segment data for transmission and reassemble it. Thus TCP programmers after about 1982 not already taught about this issue have learned from experience to "keep reading until done".

但从历史上看,SSL/TLS 实现大多确实保留了大约 16k 字节的记录边界,这也是由于协议内部的工作方式.结果,许多没有阅读规范的程序员错误地认为 SSL/TLS 是一种记录服务.由于 2011 年的BEAST 攻击,这种情况发生了变化,在某些(相当有限的) 情况可能会破坏使用 SSLv3 或 TLSv1.0 和 CBC 模式密码发送的加密数据,因为这些协议通过将 IV 从一个数据记录链接到下一个数据记录来实现 CBC 模式.一种针对 BEAST 的防御措施,由包括 Java JSSE 在内的许多堆栈实现,是将每个数据记录分成两个(或更多)部分传输,这样敏感部分的 IV 就不会提前可见;非正式的共识是使用 1 个字节,然后(最多)使用剩余的 n-1 个字节.请参阅 https://security.stackexchange.com/questions/63215/why-does-firefox-split-https-request .

But historically SSL/TLS implementations mostly did preserve record boundaries up to roughly 16k bytes, again due to the way the protocol works internally. As a result many programmers who didn't read the specifications came to the false belief that SSL/TLS is a record service. This changed as a result of the BEAST attack in 2011, which in some (fairly limited) circumstances can break encrypted data that is sent using SSLv3 or TLSv1.0 with a CBC-mode cipher, because those protocols implement CBC mode by chaining the IV from one data record to the next. One defense against BEAST, implemented by many stacks including Java JSSE, is to transmit each data record in two (or more) parts such that the IV for the sensitive part is not visible in advance; the informal consensus is to use 1 byte and then (at most) the remaining n-1 bytes. See https://security.stackexchange.com/questions/63215/why-does-firefox-split-https-request .

请注意,此防御仅在 SSL 连接中的第二次和后续写入时进行,因为第一个使用基于 KDF 的 IV,未链接,并且仅用于 CBC 模式密码套件,因为只有它们在此链接 IV时尚.TLSv1.1 及更高版本不需要它,但目前我无法验证 JSSE 在这种情况下是否真的省略了它.

Note this defense is only done on the second and subsequent writes in an SSL connection, because the first one uses an IV based on the KDF, not chained, and only for CBC-mode ciphersuites, because only they chain IVs in this fashion. And it isn't needed for TLSv1.1 and higher, but at the moment I can't verify if JSSE actually omits it in that case.

这篇关于TLS-Package 后的神秘字节的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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