/etc/nginx/cert.pem:
-----BEGIN CERTIFICATE-----
MIIDmzCCAoOgAwIBAgIBATANBgkqhkiG9w0BAQsFADB/MRMwEQYDVQQDDApNeSBU
ZXN0IENBMQswCQYDVQQIDAJCSjELMAkGA1UEBhMCQ04xIjAgBgkqhkiG9w0BCQEW
E3Jvb3QtY2FAZXhhbXBsZS5jb20xKjAoBgNVBAoMIVJvb3QgQ2VydGlmaWNhdGlv
biBBdXRob3JpdHkgVGVzdDAeFw0yMzA0MDMwOTI1MzNaFw0yNDA0MDIwOTI1MzNa
MIGTMREwDwYDVQQDDAh0ZXN0LmNvbTEQMA4GA1UECAwHQmVpamluZzELMAkGA1UE
BhMCQ04xIDAeBgkqhkiG9w0BCQEWEWVtYWlsQGV4YW1wbGUuY29tMRowGAYDVQQK
DBFPcmdhbml6YXRpb24gTmFtZTEhMB8GA1UECwwYT3JnYW5pemF0aW9uYWwgVW5p
dCBOYW1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt7D4Xt5g9Nf5
RBxZ5sw7OEcZh9nLnhjp6NgDl0EgYScvcds1SmnEaYwZnDF/uDIFA0PsDVCZVsvr
J22fpcNF3fyha1HDfoBJCUAQd14DHzncl6E2rRkH4vb85lM5V3GXDag+7/p+qhBQ
VPDJtJlLbDNbyJEbIoXYy2xyeOt1oCr7FRK/f/cn64ZTWs7P8Irh2obHq9uk1wBf
Rp9FWf71XMNx5URDhB9lODQL6akr/XCsMmGPCWpj2YAOV43aooIIkogE9n/Ial5Z
VwImWvsAoIxLBGBNF57H3suWVv+nlErExTFzq2LmYurweik4DWKViqYrQm/DBsoL
e+Z1sAKr/QIDAQABow0wCzAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQA8
9N65Q7G+QHHsM3eJrJndwJvhxLu+xZ1HcDimo+eVBBsE/OeL9RsyzRgbVPrpBvDn
oc/iTggB6Id9w1C690fkaaQ6BdwjBhZNTiYdvrIvVtsLJ7lVNOOBbQqi3nbjDFhM
zFZlXcj+kTfPO+30PGc5PuaqiOCG4WCj+f+6GNIT0Yh8Lk2FbAKVNmadEFBcUIX/
lmGBmnbXP7oXXCD+R+3PWXzOBnjDLmX23f4/Vs7Y44YDoZvdnb1JPQnN0oMYLCm4
5+pgZlKLzr0wW53mhbxWNaVnk+iFGk9UoTzDLOMr4JtWWt+Q1GzIMOspomSMu8AU
JofnRg5dB4RE3IkDu2LD
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIDnDCCAoSgAwIBAgIUMDS1qf89ZVS5FV1R1I7fzcFwrtowDQYJKoZIhvcNAQEL
BQAwfzETMBEGA1UEAwwKTXkgVGVzdCBDQTELMAkGA1UECAwCQkoxCzAJBgNVBAYT
AkNOMSIwIAYJKoZIhvcNAQkBFhNyb290LWNhQGV4YW1wbGUuY29tMSowKAYDVQQK
DCFSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFRlc3QwHhcNMjMwNDAzMDky
MzQ5WhcNMjQwNDAyMDkyMzQ5WjB/MRMwEQYDVQQDDApNeSBUZXN0IENBMQswCQYD
VQQIDAJCSjELMAkGA1UEBhMCQ04xIjAgBgkqhkiG9w0BCQEWE3Jvb3QtY2FAZXhh
bXBsZS5jb20xKjAoBgNVBAoMIVJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
VGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMx4TP/kzcDmeGH7
Oodp/aLxuA2UyEgQweJDkzaOG/swRZp5okx/zy+B+ToPY9GdEgnORxK8cPf3U8wS
KR6Q9kVY574kN6l6Ci+aVGKAVTJt8Ta0IXkCZDLdmHmLxh3Rr0bCzVl5Bxns2xmL
wG9ZN3yzbZjnpOBsYhoShlvV39JzKGPHJ3kui/FvU6vFi22CYm3IPDXAl4qy0YgU
1CAk+Vjp5/tZTsqx60qOUIz+N60gGwjH7wzGjJ7Wl2Lu6lZKfCn1McD+rCxh6B7b
uuNjGfHHoCGDBnfm1rd6KNeERvgoVaaKGw5sq6yXZtk8faTfNx4synf1ugZYacv0
ZhBE3DkCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA
bfAEXO831XyiLH9sVx577cGWNXCtvNTBUrip4DgQumIRJ8cJwbWKmttOGs3JrCuU
kNtqY4oS3hMUHbQ56V2SHqUbzTIjAMmZzmUF6gPSC0fySNfembgpeE/Cu5T1zIcX
HlXWF0f6H3QF+Myv3+J1+9IVoZVCncSeZ65ubrmyDNojU/s2AoMNIbJGPhnEdqA/
nskW54NR4ENXfob8gVuulnouMAQcKZ+LjRFUgvFQzisr8njinA4Uu6/fFiDNJTOg
Xy8Eh6XKBYdxCWzxKVt2T9w4H1q7lWVirJtdWzfDV731ETtREtwVPF9420Tl+7IB
0xwEYe8wLbe8SjgBow4Nbw==
-----END CERTIFICATE-----
/etc/nginx/prvtkey.pem:
-----BEGIN RSA PRIVATE KEY-----
MIIEpQIBAAKCAQEAt7D4Xt5g9Nf5RBxZ5sw7OEcZh9nLnhjp6NgDl0EgYScvcds1
SmnEaYwZnDF/uDIFA0PsDVCZVsvrJ22fpcNF3fyha1HDfoBJCUAQd14DHzncl6E2
rRkH4vb85lM5V3GXDag+7/p+qhBQVPDJtJlLbDNbyJEbIoXYy2xyeOt1oCr7FRK/
f/cn64ZTWs7P8Irh2obHq9uk1wBfRp9FWf71XMNx5URDhB9lODQL6akr/XCsMmGP
CWpj2YAOV43aooIIkogE9n/Ial5ZVwImWvsAoIxLBGBNF57H3suWVv+nlErExTFz
q2LmYurweik4DWKViqYrQm/DBsoLe+Z1sAKr/QIDAQABAoIBAQCSc9Mh+BS/QS4o
Yp4+x9fzP6SYTknsK5ranNcIEdGaA97s3MO5J2iEakHE6SYWGjMq7k1WNEt9Cyna
Dqm5RF4A5blg0hiWU/tnF5/JO7grfjtk3RC1o35JM3hgvju6fwLazagYNtQkDMuv
XSbECXA7vRrRZveGZ8Z4MWd3BuuKHUCCQpd4WvEzsNw1dWzEn1T4DpTsrg2gn6oE
ncnqBMnmDZTSpmH6YnNj2+50Y6HvNdPKvfnqqx8DWDE1i9LSjdR815372nTDhlWs
gOZouv9LEgaySt/ZE9p2XciMjGZe2CtPhJ/7BWQjxGbs2J5fl3hauVrc3RtbVJMz
KJSqvVihAoGBAOBuWVTNeMSL5D/dgigmS5Mjg1af0FUBvNX6waCHznh09u5Z4gG8
HycJ2H468mDeQHxGYx9zvgUJ4TN+oWC4hR1V2k2kzYpNHlKGlMf69BD77t52Fziq
DPWfJHmfEtYZgmTHxYkMpRjZQnS3L1X2ek+Urmj8wCr+GRo3+lwnRKO5AoGBANGH
mkW++vaUI9VD4UOF49ZQgAE2IB+EOJA3xjFMYzKIbd4H5tocSeHk2ZW0x3MtiPC4
qemhkueZy15M35lF/boi9gIMPCOPOFkmXEFgkGTzHy5/gsoamqrA1vXdR0+kwiRi
kM6GCqUMTvtxw/L90W/z7lqfrcKqqCP2BH1tULRlAoGBAKLh85uEdH3ROZrQXMJe
6MKlJ5Ea88x+MlrqXtTvO35ZBU3/lfPEYKeokaMrjPWY2BxZyV7uVZ66iOMiqGTW
BmZABOwNC8+wIK2sVxa8n54j+j0iX8AUSsuI8KQEO1t/sA8MneTVdI0QQRcMTCKL
fEF9mwc/SQjq2bUZo252YW6hAoGAIn5lalf/brqCj6hmHDydfnmwKQLlFOsqeKuF
6DXAGuCU3bmFSqDflN2c6GVjdFWptp9f8YNU8OXDshmLserw00TQJRQojl4Uk7CZ
/XVNMCFKH9iECouIrNWkTcOI6taf02eamTU96V/2XLSk4orggMKymZ6x91sq5Qiq
Qo/NenUCgYEAjq64bx7Sr4/SYbZDqaISvaz96r7nXMrAoZ+XrJn2B3JJhoMIGYg3
gRkBsR1PY5TArBbR8r9ekciEAVkg4zPQeEqy1MErnlPg4V/k3hoXeHoTNxc65hTt
SyEIhR7oo/H7tQKMhGtMD85VqeDkBEz2Vr4O0OtGfS5fdbCVcJkaQVM=
-----END RSA PRIVATE KEY-----
cacert.pem:
-----BEGIN CERTIFICATE-----
MIIDnDCCAoSgAwIBAgIUMDS1qf89ZVS5FV1R1I7fzcFwrtowDQYJKoZIhvcNAQEL
BQAwfzETMBEGA1UEAwwKTXkgVGVzdCBDQTELMAkGA1UECAwCQkoxCzAJBgNVBAYT
AkNOMSIwIAYJKoZIhvcNAQkBFhNyb290LWNhQGV4YW1wbGUuY29tMSowKAYDVQQK
DCFSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFRlc3QwHhcNMjMwNDAzMDky
MzQ5WhcNMjQwNDAyMDkyMzQ5WjB/MRMwEQYDVQQDDApNeSBUZXN0IENBMQswCQYD
VQQIDAJCSjELMAkGA1UEBhMCQ04xIjAgBgkqhkiG9w0BCQEWE3Jvb3QtY2FAZXhh
bXBsZS5jb20xKjAoBgNVBAoMIVJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
VGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMx4TP/kzcDmeGH7
Oodp/aLxuA2UyEgQweJDkzaOG/swRZp5okx/zy+B+ToPY9GdEgnORxK8cPf3U8wS
KR6Q9kVY574kN6l6Ci+aVGKAVTJt8Ta0IXkCZDLdmHmLxh3Rr0bCzVl5Bxns2xmL
wG9ZN3yzbZjnpOBsYhoShlvV39JzKGPHJ3kui/FvU6vFi22CYm3IPDXAl4qy0YgU
1CAk+Vjp5/tZTsqx60qOUIz+N60gGwjH7wzGjJ7Wl2Lu6lZKfCn1McD+rCxh6B7b
uuNjGfHHoCGDBnfm1rd6KNeERvgoVaaKGw5sq6yXZtk8faTfNx4synf1ugZYacv0
ZhBE3DkCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEA
bfAEXO831XyiLH9sVx577cGWNXCtvNTBUrip4DgQumIRJ8cJwbWKmttOGs3JrCuU
kNtqY4oS3hMUHbQ56V2SHqUbzTIjAMmZzmUF6gPSC0fySNfembgpeE/Cu5T1zIcX
HlXWF0f6H3QF+Myv3+J1+9IVoZVCncSeZ65ubrmyDNojU/s2AoMNIbJGPhnEdqA/
nskW54NR4ENXfob8gVuulnouMAQcKZ+LjRFUgvFQzisr8njinA4Uu6/fFiDNJTOg
Xy8Eh6XKBYdxCWzxKVt2T9w4H1q7lWVirJtdWzfDV731ETtREtwVPF9420Tl+7IB
0xwEYe8wLbe8SjgBow4Nbw==
-----END CERTIFICATE-----
test.com
$ openssl version
OpenSSL 1.1.1f 31 Mar 2020
$ nginx -V
nginx version: nginx/1.18.0 (Ubuntu)
built with OpenSSL 1.1.1f 31 Mar 2020
TLS SNI support enabled
configure 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
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 768;
}
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 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_certificate /etc/nginx/cert.pem;
ssl_certificate_key /etc/nginx/prvtkey.pem;
ssl_ciphers AES256-GCM-SHA384;
ssl_session_cache off;
ssl_session_tickets off;
server {
listen 443 ssl;
}
}
注意,在 nginx 配置文件中,通过 ssl_ciphers
指令限制启用的加密算法,这里强制使用 RSA 密钥交换方式。查看 Nginx 配置 HTTPS ,获取更多关于 SSL 的配置信息。
$ tcpdump --version
tcpdump version 4.9.3
libpcap version 1.9.1 (with TPACKET_V3)
OpenSSL 1.1.1f 31 Mar 2020
$ curl --version
curl 7.68.0 (x86_64-pc-linux-gnu) libcurl/7.68.0 OpenSSL/1.1.1f zlib/1.2.11 brotli/1.0.9 libidn2/2.3.0 libpsl/0.21.0 (+libidn2/2.3.0) libssh/0.9.3/openssl/zlib nghttp2/1.41.0 librtmp/2.3
Release-Date: 2020-01-08
Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp
Features: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSockets
Python 3.10.6
在本机安装 Wireshark,本文使用的版本如下:
% /Applications/Wireshark.app/Contents/MacOS/Wireshark --version
Wireshark 4.0.4 (v4.0.4-0-gea14d468d9ca).
主要用于查看 pcap 数据包。如果不想安装 Wireshark,也可以使用 Python scapy 包解析 pcap 数据包,或者使用其它方式。
如果 Nginx 未启动,那么使用下面的命令启动它:
$ sudo nginx
$ sudo tcpdump -i lo -w test.pcap
其中:
-i
用于指定要抓取的网络接口-w
将抓取到的数据包保存到指定的文件中。比如 -w capature.pcap
将抓取到数据包保存到 capture.pcap 文件中,可以用 Wireshark 等网络分析工具查看和分析curl \
-o /dev/null \
-v \
--tlsv1.2 \
--resolve "test.com:443:127.0.0.1" \
--cacert cacert.pem \
https://test.com/
其中,cacert.pem 是自建 CA 的证书。
可以在输出中看到类似下面的内容:
* SSL connection using TLSv1.2 / AES256-GCM-SHA384
说明与 nginx.conf 中配置的一样,即使用的密钥交换方式是 RSA,对称加密算法是 AES256-GCM,哈希算法是 SHA384。
打开 Wireshark。点击 File -> Open,选择 test.pcap。依次获取下述解密 HTTPS 流量用到的数据。
x
import hmac
import hashlib
import struct
from cryptography.hazmat.primitives.serialization import load_pem_private_key
from cryptography.hazmat.primitives.asymmetric import padding
from Crypto.Cipher import AES
MASTER_SECRET_LENGTH: int = 48
KEY_BLOCK_LENGTH: int = 168
KEY_LENGTH: int = 32
IV_LENGTH: int = 4
def prf(secret: bytes, seed: bytes, output_len: int) -> bytes:
"""
Pseudo Random Function 实现
"""
_A: bytes = seed
_R: bytes = b""
while len(_R) < output_len:
_A = hmac.new(secret, _A, hashlib.sha384).digest()
_R += hmac.new(secret, _A + seed, hashlib.sha384).digest()
return _R[:output_len]
class TLSRSADecrypter:
def __init__(
self,
private_key_pem: bytes,
encrypted_pre_master_secret: bytes,
client_hello_handshake_message: bytes,
server_hello_handshake_message: bytes,
certificate_handshake_message: bytes,
server_hello_done_handshake_message: bytes,
client_key_exchange_handshake_message: bytes,
server_random: bytes,
client_random: bytes
):
self._private_key: bytes = private_key_pem
self._encrypted_pre_master_secret: bytes = encrypted_pre_master_secret
self._pre_master_secret: bytes = self._get_pre_master_secret()
self._client_hello_handshake_message: bytes = client_hello_handshake_message
self._server_hello_handshake_message: bytes = server_hello_handshake_message
self._certificate_handshake_message: bytes = certificate_handshake_message
self._server_hello_done_handshake_message: bytes = server_hello_done_handshake_message
self._client_key_exchange_handshake_message: bytes = client_key_exchange_handshake_message
self._session_hash: bytes = self._get_session_hash()
self._master_secret: bytes = prf(self._pre_master_secret, self._session_hash, MASTER_SECRET_LENGTH)
self._server_random: bytes = server_random
self._client_random: bytes = client_random
self._key_block: bytes = self._get_key_block()
self._client_write_key: bytes = self._key_block[0:KEY_LENGTH]
self._server_write_key: bytes = self._key_block[KEY_LENGTH:2 * KEY_LENGTH]
self._client_write_iv: bytes = self._key_block[2 * KEY_LENGTH: 2 * KEY_LENGTH + 4]
self._server_write_iv: bytes = self._key_block[2 * KEY_LENGTH + 4: 2 * KEY_LENGTH + 4 + 4]
def _get_pre_master_secret(self) -> bytes:
private_key = load_pem_private_key(self._private_key, password=None)
return private_key.decrypt(self._encrypted_pre_master_secret, padding.PKCS1v15())
def _get_session_hash(self) -> bytes:
return b"extended master secret" + \
hashlib.sha384(
self._client_hello_handshake_message +
self._server_hello_handshake_message +
self._certificate_handshake_message +
self._server_hello_done_handshake_message +
self._client_key_exchange_handshake_message
).digest()
def _get_key_block(self) -> bytes:
return prf(
self._master_secret,
b"key expansion" + self._server_random + self._client_random,
KEY_BLOCK_LENGTH
)
def decrypt(iv: bytes, key: bytes, cipher_text: bytes) -> bytes:
# Cipher Text 结构:nonce(0 到 7) + encrypted data(8 到 -17) + authentication tag(-16 到最后)
nonce: bytes = iv + cipher_text[:8]
# Application Data 对应的值为 0x17
aad: bytes = b"\x00" * 7 + b"\x01" + b"\x17" + b"\x03\x03" + struct.pack("!I", len(cipher_text) - 24)[-2:]
aes_cipher = AES.new(key, AES.MODE_GCM, nonce=nonce)
aes_cipher.update(aad)
return aes_cipher.decrypt_and_verify(cipher_text[8:-16], cipher_text[-16:])
def decrypt_client_hex(self, cipher_text_hex: str) -> bytes:
return self.decrypt(self._client_write_iv, self._client_write_key, bytes.fromhex(cipher_text_hex))
def decrypt_server_hex(self, cipher_text_hex: str) -> bytes:
return self.decrypt(self._server_write_iv, self._server_write_key, bytes.fromhex(cipher_text_hex))
def pre_master_secret_hex(self) -> str:
return self._pre_master_secret.hex()
def session_hash_hex(self) -> str:
return self._session_hash.hex()
def master_secret_hex(self) -> str:
return self._master_secret.hex()
def key_block_hex(self) -> str:
return self._key_block.hex()
def client_write_key_hex(self) -> str:
return self._client_write_key.hex()
def server_write_key_hex(self) -> str:
return self._server_write_key.hex()
def client_write_iv_hex(self) -> str:
return self._client_write_iv.hex()
def server_write_iv_hex(self) -> str:
return self._server_write_iv.hex()
class TLSRSADecrypterBuilder:
def __init__(self):
self._private_key_pem: bytes = b""
self._encrypted_pre_master_secret: bytes = b""
self._client_hello_handshake_message: bytes = b""
self._server_hello_handshake_message: bytes = b""
self._certificate_handshake_message: bytes = b""
self._server_hello_done_handshake_message: bytes = b""
self._client_key_exchange_handshake_message: bytes = b""
self._server_random: bytes = b""
self._client_random: bytes = b""
def with_private_key_pem(self, private_key_pem: bytes) -> "TLSRSADecrypterBuilder":
self._private_key_pem = private_key_pem
return self
def with_encrypted_pre_master_secret_hex(self, encrypted_pre_master_secret_hex: str) -> "TLSRSADecrypterBuilder":
self._encrypted_pre_master_secret = bytes.fromhex(encrypted_pre_master_secret_hex)
return self
def with_client_hello_handshake_message_hex(
self,
client_hello_handshake_message_hex: str
) -> "TLSRSADecrypterBuilder":
self._client_hello_handshake_message = bytes.fromhex(client_hello_handshake_message_hex)
return self
def with_server_hello_handshake_message_hex(self,
server_hello_handshake_message_hex: str) -> "TLSRSADecrypterBuilder":
self._server_hello_handshake_message = bytes.fromhex(server_hello_handshake_message_hex)
return self
def with_certificate_handshake_message_hex(self,
certificate_handshake_message_hex: str) -> "TLSRSADecrypterBuilder":
self._certificate_handshake_message = bytes.fromhex(certificate_handshake_message_hex)
return self
def with_server_hello_done_handshake_message_hex(
self,
server_hello_done_handshake_message_hex: str
) -> "TLSRSADecrypterBuilder":
self._server_hello_done_handshake_message = bytes.fromhex(server_hello_done_handshake_message_hex)
return self
def with_client_key_exchange_handshake_message_hex(
self,
client_key_exchange_handshake_message_hex: str
) -> "TLSRSADecrypterBuilder":
self._client_key_exchange_handshake_message = bytes.fromhex(client_key_exchange_handshake_message_hex)
return self
def with_server_random_hex(self, server_random_hex: str) -> "TLSRSADecrypterBuilder":
self._server_random = bytes.fromhex(server_random_hex)
return self
def with_client_random_hex(self, client_random_hex: str) -> "TLSRSADecrypterBuilder":
self._client_random = bytes.fromhex(client_random_hex)
return self
def build(self) -> TLSRSADecrypter:
if not self._private_key_pem:
raise ValueError("no private key provided")
if not self._encrypted_pre_master_secret:
raise ValueError("no encrypted pre-master secret provided")
if not self._client_hello_handshake_message:
raise ValueError("no client hello handshake message provided")
if not self._server_hello_handshake_message:
raise ValueError("no server hello handshake message provided")
if not self._certificate_handshake_message:
raise ValueError("no certificate handshake message provided")
if not self._server_hello_done_handshake_message:
raise ValueError("no server hello done handshake message provided")
if not self._client_key_exchange_handshake_message:
raise ValueError("no client key exchange handshake message provided")
if not self._server_random:
raise ValueError("no server random provided")
if not self._client_random:
raise ValueError("no client random provided")
return TLSRSADecrypter(
self._private_key_pem,
self._encrypted_pre_master_secret,
self._client_hello_handshake_message,
self._server_hello_handshake_message,
self._certificate_handshake_message,
self._server_hello_done_handshake_message,
self._client_key_exchange_handshake_message,
self._server_random,
self._client_random
)
def main():
# 二进制形式的私钥(PEM 格式)
private_key = b""
# Hex 格式的 RSA 加密的预主密钥
encrypted_pre_master = ""
# Hex 格式的 Client Hello 握手消息
client_hello = ""
# Hex 格式的 Server Hello 握手消息
server_hello = ""
# Hex 格式的 Certificate 握手消息
certificate = ""
# Hex 格式的 Server Hello Done 握手消息
server_hello_done = ""
# Hex 格式的 Client Key Exchange 握手消息
client_key_exchange = ""
# Hex 格式的 Server Random
server_random = ""
# Hex 格式的 Client Random
client_random = ""
# Hex 格式的请求报文
request = ""
# Hex 格式的响应报文
response = ""
decrypter = TLSRSADecrypterBuilder() \
.with_private_key_pem(private_key) \
.with_encrypted_pre_master_secret_hex(encrypted_pre_master) \
.with_client_hello_handshake_message_hex(client_hello) \
.with_server_hello_handshake_message_hex(server_hello) \
.with_certificate_handshake_message_hex(certificate) \
.with_server_hello_done_handshake_message_hex(server_hello_done) \
.with_client_key_exchange_handshake_message_hex(client_key_exchange) \
.with_server_random_hex(server_random) \
.with_client_random_hex(client_random) \
.build()
print("请求:")
print(decrypter.decrypt_client_hex(request).decode())
print("响应:")
print(decrypter.decrypt_server_hex(response).decode())
if __name__ == "__main__":
main()
注意
- 设置代码中的 private_key、encrypted_pre_master、client_hello 等变量的值
- 本示例指针的加密算法是 AES-GCM-SHA384,并且针对的是 Full Handshake 流程
macOS 版本