阅读本文前,请先阅读 使用 RSA 密钥交换方式时,使用私钥解密 HTTPS 流量数据。
以下内容来自于 https://firefox-source-docs.mozilla.org/security/nss/legacy/key_log_format/index.html。
外部应用程序可以通过 Key Log 解密 TLS 连接。Wireshark 1.6.0 及以上版本可以使用该日志文件解密数据包。通过 Wireshark -> Preferences -> Protocols -> TLS -> (Pre)-Master-Secret log file,告诉 Wireshark 去哪里寻找 Key 文件。
通过将环境变量 SSLKEYLOGFILE 设置为文件的方式,启用 Key Log。Key Log 文件由一系列行组成。注释行以 # 开头,注释将被忽略。密钥遵循格式 <Label> <space> <ClientRandom> <space> <Secret>,其中:
<Label> 描述后面的密码<ClientRandom> 是来自于 Client Hello 消息的 32 字节随机值,被编码为 64 个十六进制字符<Secret> 依赖于上面的 LabelLabel 的定义如下:
RSA:48 字节的预主密钥,被编码为 96 个十六进制字符CLIENT_RANDOM:48 字节的主密钥,被编码为 96 个十六进制字符(用于 SSL 3.0,TLS 1.0、1.1 和 1.2)CLIENT_EARLY_TRAFFIC_SECRET:客户端的早期流量密钥(十六进制编码)(用于 TLS 1.3)CLIENT_HANDSHAKE_TRAFFIC_SECRET:客户端的握手流量密钥(十六进制编码)(用于 TLS 1.3)SERVER_HANDSHAKE_TRAFFIC_SECRET:服务端的握手流量密钥(十六进制编码)(用于 TLS 1.3)CLIENT_TRAFFIC_SECRET_0:客户端的第一个应用流量密钥(十六进制编码)(用于 TLS 1.3)SERVER_TRAFFIC_SECRET_0:服务端的第一个应用流量密钥(十六进制编码)(用于 TLS 1.3)EARLY_EXPORTER_SECRET:十六进制编码的早期导出器密钥(用于 TLS 1.3)EXPORTER_SECRET:十六进制编码的导出器密钥RSA 形式允许记录使用 RSA 密钥协商的密码套件,并且这是 Wireshark 1.6.0 支持的第一个形式。它已被 CLIENT_RANDOM 取代,后者可以与其它密钥协商算法(例如基于 Diffie-Hellman 的算法)一起使用,从 Wireshark 1.8.0 起,被支持。
在 TLS 1.3 中,十六进制编码的密钥大小取决于选择的密码套件。对于 SHA256、SHA384、SHA512 分别为 64、96、128 字符。
$ nginx -Vnginx version: nginx/1.18.0 (Ubuntu)built with OpenSSL 1.1.1f 31 Mar 2020TLS SNI support enabledconfigure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-HdenXw/nginx-1.18.0=. -fstack-protector-strong -Wformat -Werror=format-security -fPIC -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -fPIC' --prefix=/usr/share/nginx --conf-path=/etc/nginx/nginx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fastcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-compat --with-debug --with-pcre-jit --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_request_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_sub_module下载 sslkeylog.c 源代码
编译:
$ cc sslkeylog.c -shared -o libsslkeylog.so -fPIC -ldlmacOS 的使用:
$ cc sslkeylog.c -shared -o libsslkeylog.dylib -fPIC -ldl \ -I/usr/local/opt/openssl@1.1/include \ -L/usr/local/opt/openssl@1.1/lib -lssl$ DYLD_INSERT_LIBRARIES=./libsslkeylog.dylib DYLD_FORCE_FLAT_NAMESPACE=1 \ SSLKEYLOGFILE=premaster.txt /usr/local/opt/openssl@1.1/bin/openssl ...如果缺少相应的头文件,那么安装它们,比如在 Ubuntu 上:
$ sudo apt install -y libssl-dev
将编译后的动态连接库拷贝到 /usr/local/lib/
$ mv libsslkeylog.so /usr/local/lib//etc/nginx/nginx.conf:
worker_processes auto;pid /run/nginx.pid;
events { worker_connections 768;}
env SSLKEYLOGFILE;env LD_PRELOAD;
http { access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log;
sendfile on; tcp_nodelay on; keepalive_timeout 15;
include /etc/nginx/mime.types; default_type application/octet-stream;
ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_certificate /etc/nginx/cert.pem; ssl_certificate_key /etc/nginx/prvtkey.pem; ssl_session_cache off; ssl_session_tickets off;
server { listen 443 ssl; }}$ SSLKEYLOGFILE=/tmp/sslkey.log LD_PRELOAD=/usr/local/lib/libsslkeylog.so nginx$ sudo tcpdump -i lo -w test.pcap$ curl \ -o /dev/null \ -v \ --tlsv1.2 \ --resolve "test.com:443:127.0.0.1" \ --cacert cacert.pem \ https://test.com/