在Go中提取TLS秘密

发布于 2025-02-10 02:45:49 字数 1904 浏览 2 评论 0 原文

我不确定这是否真的是一个Wireshark,Go或Syncthing问题;我尝试了 wireshark dev list https://groups.google.com/g/golang-nuts/c/dp70565acra“ rel =” nofollow noreferrer'> go dev list ,但没有回复,所以我想在这里尝试:

我'm在

我阅读 wireshark tls tls documentation ;同步写在旅途中,因此,这样(这只是在上游代码与添加两行同步的代码):

// The TLS configuration is used for both the listening socket and outgoing
// connections.

var tlsCfg *tls.Config
if a.cfg.Options().InsecureAllowOldTLSVersions {
    l.Infoln("TLS 1.2 is allowed on sync connections. This is less than optimally secure.")
    tlsCfg = tlsutil.SecureDefaultWithTLS12()
} else {
    tlsCfg = tlsutil.SecureDefaultTLS13()
}
tlsCfg.Certificates = []tls.Certificate{a.cert}
tlsCfg.NextProtos = []string{bepProtocolName}
tlsCfg.ClientAuth = tls.RequestClientCert
tlsCfg.SessionTicketsDisabled = true
tlsCfg.InsecureSkipVerify = true

// The following two lines open a file in the current directory and configure the application to dump its TLS secrets there
// See: https://pkg.go.dev/crypto/tls#example-Config-KeyLogWriter

w, err := os.OpenFile("tls-secrets.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
tlsCfg.KeyLogWriter = w

这项工作原理,并且将各种内容写入指定的文件,但是将该文件提供给Wireshark并不启用TLS解密。 I examined the file, and I see that it contains CLIENT_HANDSHAKE_TRAFFIC_SECRET, SERVER_HANDSHAKE_TRAFFIC_SECRET, CLIENT_TRAFFIC_SECRET_0, and SERVER_TRAFFIC_SECRET_0 lines, but不是关键 client_random 行。我是做错事还是错过了什么?

I'm not totally sure whether this is really a Wireshark, Go, or Syncthing question; I tried the Wireshark dev list and the Go dev list but got no response, so I figured I'll try here:

I'm working on a Wireshark Syncthing dissector. Since most of the Syncthing protocols are encapsulated in TLS, I need to provide the TLS secrets to Wireshark.

I read the Wireshark TLS documentation; Syncthing is written in Go, so I patched it to export TLS secrets, like this (this is just Syncthing upstream code with the addition of the two final lines):

// The TLS configuration is used for both the listening socket and outgoing
// connections.

var tlsCfg *tls.Config
if a.cfg.Options().InsecureAllowOldTLSVersions {
    l.Infoln("TLS 1.2 is allowed on sync connections. This is less than optimally secure.")
    tlsCfg = tlsutil.SecureDefaultWithTLS12()
} else {
    tlsCfg = tlsutil.SecureDefaultTLS13()
}
tlsCfg.Certificates = []tls.Certificate{a.cert}
tlsCfg.NextProtos = []string{bepProtocolName}
tlsCfg.ClientAuth = tls.RequestClientCert
tlsCfg.SessionTicketsDisabled = true
tlsCfg.InsecureSkipVerify = true

// The following two lines open a file in the current directory and configure the application to dump its TLS secrets there
// See: https://pkg.go.dev/crypto/tls#example-Config-KeyLogWriter

w, err := os.OpenFile("tls-secrets.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
tlsCfg.KeyLogWriter = w

This works, and various stuff is written to the specified file, but providing that file to Wireshark doesn't enable TLS decryption. I examined the file, and I see that it contains CLIENT_HANDSHAKE_TRAFFIC_SECRET, SERVER_HANDSHAKE_TRAFFIC_SECRET, CLIENT_TRAFFIC_SECRET_0, and SERVER_TRAFFIC_SECRET_0 lines, but not the crucial CLIENT_RANDOM lines. Am I doing something wrong or missing something?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

沦落红尘 2025-02-17 02:45:49

根本原因是 tls1.2 tls1.3 之间的区别,可以找到差异在这里

per per per per

    keyLogLabelTLS12           = "CLIENT_RANDOM"
    keyLogLabelClientHandshake = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
    keyLogLabelServerHandshake = "SERVER_HANDSHAKE_TRAFFIC_SECRET"
    keyLogLabelClientTraffic   = "CLIENT_TRAFFIC_SECRET_0"
    keyLogLabelServerTraffic   = "SERVER_TRAFFIC_SECRET_0"
  • For tls1.3, those parameters CLIENT_HANDSHAKE_TRAFFIC_SECRET, SERVER_HANDSHAKE_TRAFFIC_SECRET, CLIENT_TRAFFIC_SECRET_0, and server_traffic_secret_0 可以作为
  • tls1.2 client> client_random 的客户秘密导出,可以作为客户端秘密导出,

所有这些>都可以在Wireshark中使用,以解密TLS1。 2和TLS 1.3。


这是一个测试示例

,然后启动一台HTTPS服务器

    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        if req.URL.Path != "/" {
            http.NotFound(w, req)
            return
        }
    })

    w, err := os.OpenFile("/keypath/https-key.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    if err != nil {
        fmt.Printf("failed to open file err %+v", err)
        return
    }

    cs := make([]uint16, len(cipherSuites))
    copy(cs, cipherSuites)
    var tlsCfg tls.Config
    tlsCfg.Certificates = make([]tls.Certificate, 1)
    tlsCfg.Certificates[0], err = tls.LoadX509KeyPair(*certFile, *keyFile)
    tlsCfg.NextProtos = []string{"h2"}
    tlsCfg.ClientAuth = tls.RequestClientCert
    tlsCfg.SessionTicketsDisabled = true
    tlsCfg.InsecureSkipVerify = true
    tlsCfg.KeyLogWriter = w
    tlsCfg.MinVersion = tls.VersionTLS13
    tlsCfg.CipherSuites = cs
    tlsCfg.PreferServerCipherSuites = true

    srv := &http.Server{
        Addr:      *addr,
        Handler:   mux,
        TLSConfig: &tlsCfg,
    }

    log.Printf("Starting server on %s", *addr)
    err = srv.ListenAndServeTLS("", "")
    log.Fatal(err)

,然后通过 curl 使用 tls1.3 curl -lv https:// localhost:4000- cacert/crtpath/ca.crt -tlsv1.3

我们可以在下面找到 https-key.txt 的内容,

> cat https-key.txt
CLIENT_HANDSHAKE_TRAFFIC_SECRET xxxx yyyyy
SERVER_HANDSHAKE_TRAFFIC_SECRET xxxx yyyyyyyyy
CLIENT_TRAFFIC_SECRET_0 xxxxxxx yyyy
SERVER_TRAFFIC_SECRET_0 xx yyyyyyyyyyyy

然后设置keyfile /keypath/grpc-key。 txt to 首选项 - >协议 - > TLS - > (pre) - 船长销售日志文件名在Wireshark中,现在Wireshark可以

对TLS1.2测试进行TLS解密,您可以将服务器代码更改为 tlscfg.minversion = tls.versiontls12 然后通过 curl tls1.2 curl -lv https:// localhost:4000 -cacert/crtpath/ca.crt -tlsv1对其进行测试。 2 。并再次检查 https-key.txt ,您可以发现内容可以是 client_random xxxxxx yyyyyyyyyyyyyyyy

The root cause is the difference between tls1.2 and tls1.3, the difference could be found here
enter image description here

Per golang tls code

    keyLogLabelTLS12           = "CLIENT_RANDOM"
    keyLogLabelClientHandshake = "CLIENT_HANDSHAKE_TRAFFIC_SECRET"
    keyLogLabelServerHandshake = "SERVER_HANDSHAKE_TRAFFIC_SECRET"
    keyLogLabelClientTraffic   = "CLIENT_TRAFFIC_SECRET_0"
    keyLogLabelServerTraffic   = "SERVER_TRAFFIC_SECRET_0"
  • For tls1.3, those parameters CLIENT_HANDSHAKE_TRAFFIC_SECRET, SERVER_HANDSHAKE_TRAFFIC_SECRET, CLIENT_TRAFFIC_SECRET_0, and SERVER_TRAFFIC_SECRET_0 could be exported as client secrets
  • For tls1.2, CLIENT_RANDOM could be exported as client secrets

All of them could be used in Wireshark to decrypt TLS1.2 and TLS 1.3.


Here is one test sample

First, start one HTTPS server

    mux := http.NewServeMux()
    mux.HandleFunc("/", func(w http.ResponseWriter, req *http.Request) {
        if req.URL.Path != "/" {
            http.NotFound(w, req)
            return
        }
    })

    w, err := os.OpenFile("/keypath/https-key.txt", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
    if err != nil {
        fmt.Printf("failed to open file err %+v", err)
        return
    }

    cs := make([]uint16, len(cipherSuites))
    copy(cs, cipherSuites)
    var tlsCfg tls.Config
    tlsCfg.Certificates = make([]tls.Certificate, 1)
    tlsCfg.Certificates[0], err = tls.LoadX509KeyPair(*certFile, *keyFile)
    tlsCfg.NextProtos = []string{"h2"}
    tlsCfg.ClientAuth = tls.RequestClientCert
    tlsCfg.SessionTicketsDisabled = true
    tlsCfg.InsecureSkipVerify = true
    tlsCfg.KeyLogWriter = w
    tlsCfg.MinVersion = tls.VersionTLS13
    tlsCfg.CipherSuites = cs
    tlsCfg.PreferServerCipherSuites = true

    srv := &http.Server{
        Addr:      *addr,
        Handler:   mux,
        TLSConfig: &tlsCfg,
    }

    log.Printf("Starting server on %s", *addr)
    err = srv.ListenAndServeTLS("", "")
    log.Fatal(err)

Then, test it through curl with tls1.3 curl -Lv https://localhost:4000 --cacert /crtpath/ca.crt --tlsv1.3

We could find the content of https-key.txt as below

> cat https-key.txt
CLIENT_HANDSHAKE_TRAFFIC_SECRET xxxx yyyyy
SERVER_HANDSHAKE_TRAFFIC_SECRET xxxx yyyyyyyyy
CLIENT_TRAFFIC_SECRET_0 xxxxxxx yyyy
SERVER_TRAFFIC_SECRET_0 xx yyyyyyyyyyyy

Then set the keyFile /keypath/grpc-key.txt to Preferences -> Protocols -> TLS -> (Pre)-Master-Secret log filename in WireShark, now the Wireshark could do TLS decryption

For TLS1.2 test, you could change the server code to tlsCfg.MinVersion = tls.VersionTLS12 and then test it through curl with tls1.2 curl -Lv https://localhost:4000 --cacert /crtpath/ca.crt --tlsv1.2. And check the https-key.txt again, you could find the content could be CLIENT_RANDOM xxxxxx yyyyyyyy.

梦纸 2025-02-17 02:45:49

我在@zangw的大力帮助下弄清楚了。有两个问题:

Wireshark现在成功地解密了TLS数据;可以通过选择“加密应用程序数据”,然后单击窗口底部的“解密TLS”选项卡来查看。

I figured it out, with a lot of help from @zangw. There were two problems:

  • Although some discussions of TLS decryption in Wireshark mention CLIENT_RANDOM, this is only for TLS 1.2; current Syncthing generally uses TLS 1.3, which involves the other secrets I was seeing (CLIENT_HANDSHAKE_TRAFFIC_SECRET, SERVER_HANDSHAKE_TRAFFIC_SECRET, CLIENT_TRAFFIC_SECRET_0, and SERVER_TRAFFIC_SECRET_0) - see the official documentation of the NSS Key Log Format.
  • I was starting the capture too late (since I was waiting for the secrets to be written out to the file in order to be able to provide them to Wireshark), and so Wireshark was missing the initial TLS handshake, which resulted in the misidentification of the protocol as TLS 1.2 instead of 1.3 as well as the inability to decrypt the traffic. The correct way to proceed is to start the capture before the TLS negotiation begins, and then subsequently provide Wireshark with the secrets file after it is created. (This may require saving and reloading the capture.)

Wireshark now successfuly decrypts the TLS data; it can be viewed by selecting "Encrypted Application Data" and then clicking on the "Decrypted TLS" tab at the bottom of the window.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文