/etc/nginx/cert.pem:
-----BEGIN CERTIFICATE-----MIIDmzCCAoOgAwIBAgIBATANBgkqhkiG9w0BAQsFADB/MRMwEQYDVQQDDApNeSBUZXN0IENBMQswCQYDVQQIDAJCSjELMAkGA1UEBhMCQ04xIjAgBgkqhkiG9w0BCQEWE3Jvb3QtY2FAZXhhbXBsZS5jb20xKjAoBgNVBAoMIVJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgVGVzdDAeFw0yMzA0MDMwOTI1MzNaFw0yNDA0MDIwOTI1MzNaMIGTMREwDwYDVQQDDAh0ZXN0LmNvbTEQMA4GA1UECAwHQmVpamluZzELMAkGA1UEBhMCQ04xIDAeBgkqhkiG9w0BCQEWEWVtYWlsQGV4YW1wbGUuY29tMRowGAYDVQQKDBFPcmdhbml6YXRpb24gTmFtZTEhMB8GA1UECwwYT3JnYW5pemF0aW9uYWwgVW5pdCBOYW1lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt7D4Xt5g9Nf5RBxZ5sw7OEcZh9nLnhjp6NgDl0EgYScvcds1SmnEaYwZnDF/uDIFA0PsDVCZVsvrJ22fpcNF3fyha1HDfoBJCUAQd14DHzncl6E2rRkH4vb85lM5V3GXDag+7/p+qhBQVPDJtJlLbDNbyJEbIoXYy2xyeOt1oCr7FRK/f/cn64ZTWs7P8Irh2obHq9uk1wBfRp9FWf71XMNx5URDhB9lODQL6akr/XCsMmGPCWpj2YAOV43aooIIkogE9n/Ial5ZVwImWvsAoIxLBGBNF57H3suWVv+nlErExTFzq2LmYurweik4DWKViqYrQm/DBsoLe+Z1sAKr/QIDAQABow0wCzAJBgNVHRMEAjAAMA0GCSqGSIb3DQEBCwUAA4IBAQA89N65Q7G+QHHsM3eJrJndwJvhxLu+xZ1HcDimo+eVBBsE/OeL9RsyzRgbVPrpBvDnoc/iTggB6Id9w1C690fkaaQ6BdwjBhZNTiYdvrIvVtsLJ7lVNOOBbQqi3nbjDFhMzFZlXcj+kTfPO+30PGc5PuaqiOCG4WCj+f+6GNIT0Yh8Lk2FbAKVNmadEFBcUIX/lmGBmnbXP7oXXCD+R+3PWXzOBnjDLmX23f4/Vs7Y44YDoZvdnb1JPQnN0oMYLCm45+pgZlKLzr0wW53mhbxWNaVnk+iFGk9UoTzDLOMr4JtWWt+Q1GzIMOspomSMu8AUJofnRg5dB4RE3IkDu2LD-----END CERTIFICATE----------BEGIN CERTIFICATE-----MIIDnDCCAoSgAwIBAgIUMDS1qf89ZVS5FV1R1I7fzcFwrtowDQYJKoZIhvcNAQELBQAwfzETMBEGA1UEAwwKTXkgVGVzdCBDQTELMAkGA1UECAwCQkoxCzAJBgNVBAYTAkNOMSIwIAYJKoZIhvcNAQkBFhNyb290LWNhQGV4YW1wbGUuY29tMSowKAYDVQQKDCFSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFRlc3QwHhcNMjMwNDAzMDkyMzQ5WhcNMjQwNDAyMDkyMzQ5WjB/MRMwEQYDVQQDDApNeSBUZXN0IENBMQswCQYDVQQIDAJCSjELMAkGA1UEBhMCQ04xIjAgBgkqhkiG9w0BCQEWE3Jvb3QtY2FAZXhhbXBsZS5jb20xKjAoBgNVBAoMIVJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgVGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMx4TP/kzcDmeGH7Oodp/aLxuA2UyEgQweJDkzaOG/swRZp5okx/zy+B+ToPY9GdEgnORxK8cPf3U8wSKR6Q9kVY574kN6l6Ci+aVGKAVTJt8Ta0IXkCZDLdmHmLxh3Rr0bCzVl5Bxns2xmLwG9ZN3yzbZjnpOBsYhoShlvV39JzKGPHJ3kui/FvU6vFi22CYm3IPDXAl4qy0YgU1CAk+Vjp5/tZTsqx60qOUIz+N60gGwjH7wzGjJ7Wl2Lu6lZKfCn1McD+rCxh6B7buuNjGfHHoCGDBnfm1rd6KNeERvgoVaaKGw5sq6yXZtk8faTfNx4synf1ugZYacv0ZhBE3DkCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAbfAEXO831XyiLH9sVx577cGWNXCtvNTBUrip4DgQumIRJ8cJwbWKmttOGs3JrCuUkNtqY4oS3hMUHbQ56V2SHqUbzTIjAMmZzmUF6gPSC0fySNfembgpeE/Cu5T1zIcXHlXWF0f6H3QF+Myv3+J1+9IVoZVCncSeZ65ubrmyDNojU/s2AoMNIbJGPhnEdqA/nskW54NR4ENXfob8gVuulnouMAQcKZ+LjRFUgvFQzisr8njinA4Uu6/fFiDNJTOgXy8Eh6XKBYdxCWzxKVt2T9w4H1q7lWVirJtdWzfDV731ETtREtwVPF9420Tl+7IB0xwEYe8wLbe8SjgBow4Nbw==-----END CERTIFICATE-----
/etc/nginx/prvtkey.pem:
-----BEGIN RSA PRIVATE KEY-----MIIEpQIBAAKCAQEAt7D4Xt5g9Nf5RBxZ5sw7OEcZh9nLnhjp6NgDl0EgYScvcds1SmnEaYwZnDF/uDIFA0PsDVCZVsvrJ22fpcNF3fyha1HDfoBJCUAQd14DHzncl6E2rRkH4vb85lM5V3GXDag+7/p+qhBQVPDJtJlLbDNbyJEbIoXYy2xyeOt1oCr7FRK/f/cn64ZTWs7P8Irh2obHq9uk1wBfRp9FWf71XMNx5URDhB9lODQL6akr/XCsMmGPCWpj2YAOV43aooIIkogE9n/Ial5ZVwImWvsAoIxLBGBNF57H3suWVv+nlErExTFzq2LmYurweik4DWKViqYrQm/DBsoLe+Z1sAKr/QIDAQABAoIBAQCSc9Mh+BS/QS4oYp4+x9fzP6SYTknsK5ranNcIEdGaA97s3MO5J2iEakHE6SYWGjMq7k1WNEt9CynaDqm5RF4A5blg0hiWU/tnF5/JO7grfjtk3RC1o35JM3hgvju6fwLazagYNtQkDMuvXSbECXA7vRrRZveGZ8Z4MWd3BuuKHUCCQpd4WvEzsNw1dWzEn1T4DpTsrg2gn6oEncnqBMnmDZTSpmH6YnNj2+50Y6HvNdPKvfnqqx8DWDE1i9LSjdR815372nTDhlWsgOZouv9LEgaySt/ZE9p2XciMjGZe2CtPhJ/7BWQjxGbs2J5fl3hauVrc3RtbVJMzKJSqvVihAoGBAOBuWVTNeMSL5D/dgigmS5Mjg1af0FUBvNX6waCHznh09u5Z4gG8HycJ2H468mDeQHxGYx9zvgUJ4TN+oWC4hR1V2k2kzYpNHlKGlMf69BD77t52FziqDPWfJHmfEtYZgmTHxYkMpRjZQnS3L1X2ek+Urmj8wCr+GRo3+lwnRKO5AoGBANGHmkW++vaUI9VD4UOF49ZQgAE2IB+EOJA3xjFMYzKIbd4H5tocSeHk2ZW0x3MtiPC4qemhkueZy15M35lF/boi9gIMPCOPOFkmXEFgkGTzHy5/gsoamqrA1vXdR0+kwiRikM6GCqUMTvtxw/L90W/z7lqfrcKqqCP2BH1tULRlAoGBAKLh85uEdH3ROZrQXMJe6MKlJ5Ea88x+MlrqXtTvO35ZBU3/lfPEYKeokaMrjPWY2BxZyV7uVZ66iOMiqGTWBmZABOwNC8+wIK2sVxa8n54j+j0iX8AUSsuI8KQEO1t/sA8MneTVdI0QQRcMTCKLfEF9mwc/SQjq2bUZo252YW6hAoGAIn5lalf/brqCj6hmHDydfnmwKQLlFOsqeKuF6DXAGuCU3bmFSqDflN2c6GVjdFWptp9f8YNU8OXDshmLserw00TQJRQojl4Uk7CZ/XVNMCFKH9iECouIrNWkTcOI6taf02eamTU96V/2XLSk4orggMKymZ6x91sq5QiqQo/NenUCgYEAjq64bx7Sr4/SYbZDqaISvaz96r7nXMrAoZ+XrJn2B3JJhoMIGYg3gRkBsR1PY5TArBbR8r9ekciEAVkg4zPQeEqy1MErnlPg4V/k3hoXeHoTNxc65hTtSyEIhR7oo/H7tQKMhGtMD85VqeDkBEz2Vr4O0OtGfS5fdbCVcJkaQVM=-----END RSA PRIVATE KEY-----
cacert.pem:
-----BEGIN CERTIFICATE-----MIIDnDCCAoSgAwIBAgIUMDS1qf89ZVS5FV1R1I7fzcFwrtowDQYJKoZIhvcNAQELBQAwfzETMBEGA1UEAwwKTXkgVGVzdCBDQTELMAkGA1UECAwCQkoxCzAJBgNVBAYTAkNOMSIwIAYJKoZIhvcNAQkBFhNyb290LWNhQGV4YW1wbGUuY29tMSowKAYDVQQKDCFSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFRlc3QwHhcNMjMwNDAzMDkyMzQ5WhcNMjQwNDAyMDkyMzQ5WjB/MRMwEQYDVQQDDApNeSBUZXN0IENBMQswCQYDVQQIDAJCSjELMAkGA1UEBhMCQ04xIjAgBgkqhkiG9w0BCQEWE3Jvb3QtY2FAZXhhbXBsZS5jb20xKjAoBgNVBAoMIVJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgVGVzdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMx4TP/kzcDmeGH7Oodp/aLxuA2UyEgQweJDkzaOG/swRZp5okx/zy+B+ToPY9GdEgnORxK8cPf3U8wSKR6Q9kVY574kN6l6Ci+aVGKAVTJt8Ta0IXkCZDLdmHmLxh3Rr0bCzVl5Bxns2xmLwG9ZN3yzbZjnpOBsYhoShlvV39JzKGPHJ3kui/FvU6vFi22CYm3IPDXAl4qy0YgU1CAk+Vjp5/tZTsqx60qOUIz+N60gGwjH7wzGjJ7Wl2Lu6lZKfCn1McD+rCxh6B7buuNjGfHHoCGDBnfm1rd6KNeERvgoVaaKGw5sq6yXZtk8faTfNx4synf1ugZYacv0ZhBE3DkCAwEAAaMQMA4wDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAbfAEXO831XyiLH9sVx577cGWNXCtvNTBUrip4DgQumIRJ8cJwbWKmttOGs3JrCuUkNtqY4oS3hMUHbQ56V2SHqUbzTIjAMmZzmUF6gPSC0fySNfembgpeE/Cu5T1zIcXHlXWF0f6H3QF+Myv3+J1+9IVoZVCncSeZ65ubrmyDNojU/s2AoMNIbJGPhnEdqA/nskW54NR4ENXfob8gVuulnouMAQcKZ+LjRFUgvFQzisr8njinA4Uu6/fFiDNJTOgXy8Eh6XKBYdxCWzxKVt2T9w4H1q7lWVirJtdWzfDV731ETtREtwVPF9420Tl+7IB0xwEYe8wLbe8SjgBow4Nbw==-----END CERTIFICATE-----
test.com$ openssl versionOpenSSL 1.1.1f 31 Mar 2020$ 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_moduleworker_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 --versiontcpdump version 4.9.3libpcap version 1.9.1 (with TPACKET_V3)OpenSSL 1.1.1f 31 Mar 2020$ curl --versioncurl 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.3Release-Date: 2020-01-08Protocols: dict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftpFeatures: AsynchDNS brotli GSS-API HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz NTLM NTLM_WB PSL SPNEGO SSL TLS-SRP UnixSocketsPython 3.10.6
在本机安装 Wireshark,本文使用的版本如下:
% /Applications/Wireshark.app/Contents/MacOS/Wireshark --versionWireshark 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 hmacimport hashlibimport struct
from cryptography.hazmat.primitives.serialization import load_pem_private_keyfrom cryptography.hazmat.primitives.asymmetric import paddingfrom Crypto.Cipher import AES
MASTER_SECRET_LENGTH: int = 48KEY_BLOCK_LENGTH: int = 168KEY_LENGTH: int = 32IV_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 版本