1use std::fs;
2
3use chia_ssl::ChiaCertificate;
4
5#[cfg(any(feature = "native-tls", feature = "rustls"))]
6use tokio_tungstenite::Connector;
7
8use crate::ClientError;
9
10pub fn load_ssl_cert(cert_path: &str, key_path: &str) -> Result<ChiaCertificate, ClientError> {
12 fs::read_to_string(cert_path)
13 .and_then(|cert| {
14 fs::read_to_string(key_path).map(|key| ChiaCertificate {
15 cert_pem: cert,
16 key_pem: key,
17 })
18 })
19 .or_else(|_| {
20 let cert = ChiaCertificate::generate()?;
21 fs::write(cert_path, &cert.cert_pem)?;
22 fs::write(key_path, &cert.key_pem)?;
23 Ok(cert)
24 })
25}
26
27#[cfg(feature = "native-tls")]
29pub fn create_native_tls_connector(cert: &ChiaCertificate) -> Result<Connector, ClientError> {
30 use native_tls::{Identity, TlsConnector};
31
32 let identity = Identity::from_pkcs8(cert.cert_pem.as_bytes(), cert.key_pem.as_bytes())?;
33 let tls_connector = TlsConnector::builder()
34 .identity(identity)
35 .danger_accept_invalid_certs(true)
36 .build()?;
37
38 Ok(Connector::NativeTls(tls_connector))
39}
40
41#[cfg(feature = "rustls")]
43pub fn create_rustls_connector(cert: &ChiaCertificate) -> Result<Connector, ClientError> {
44 use std::sync::Arc;
45
46 use chia_ssl::CHIA_CA_CRT;
47 use rustls::{
48 ClientConfig, DigitallySignedStruct, RootCertStore,
49 client::danger::HandshakeSignatureValid,
50 crypto::{CryptoProvider, verify_tls12_signature, verify_tls13_signature},
51 pki_types::{CertificateDer, PrivateKeyDer, ServerName, UnixTime},
52 };
53
54 #[derive(Debug)]
55 struct NoCertificateVerification(CryptoProvider);
56
57 impl rustls::client::danger::ServerCertVerifier for NoCertificateVerification {
58 fn verify_server_cert(
59 &self,
60 _end_entity: &CertificateDer<'_>,
61 _intermediates: &[CertificateDer<'_>],
62 _server_name: &ServerName<'_>,
63 _ocsp: &[u8],
64 _now: UnixTime,
65 ) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
66 Ok(rustls::client::danger::ServerCertVerified::assertion())
67 }
68
69 fn verify_tls12_signature(
70 &self,
71 message: &[u8],
72 cert: &CertificateDer<'_>,
73 dss: &DigitallySignedStruct,
74 ) -> Result<HandshakeSignatureValid, rustls::Error> {
75 verify_tls12_signature(
76 message,
77 cert,
78 dss,
79 &self.0.signature_verification_algorithms,
80 )
81 }
82
83 fn verify_tls13_signature(
84 &self,
85 message: &[u8],
86 cert: &CertificateDer<'_>,
87 dss: &DigitallySignedStruct,
88 ) -> Result<HandshakeSignatureValid, rustls::Error> {
89 verify_tls13_signature(
90 message,
91 cert,
92 dss,
93 &self.0.signature_verification_algorithms,
94 )
95 }
96
97 fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
98 self.0.signature_verification_algorithms.supported_schemes()
99 }
100 }
101
102 let mut root_cert_store = RootCertStore::empty();
103
104 let ca: Vec<CertificateDer<'_>> =
105 rustls_pemfile::certs(&mut CHIA_CA_CRT.as_bytes()).collect::<Result<_, _>>()?;
106
107 root_cert_store.add(ca.into_iter().next().ok_or(ClientError::MissingCa)?)?;
108
109 let cert_chain: Vec<CertificateDer<'_>> =
110 rustls_pemfile::certs(&mut cert.cert_pem.as_bytes()).collect::<Result<_, _>>()?;
111
112 let key = rustls_pemfile::pkcs8_private_keys(&mut cert.key_pem.as_bytes())
113 .next()
114 .ok_or(ClientError::MissingPkcs8Key)??;
115
116 let mut config = ClientConfig::builder()
117 .with_root_certificates(root_cert_store)
118 .with_client_auth_cert(cert_chain, PrivateKeyDer::Pkcs8(key))?;
119
120 config
121 .dangerous()
122 .set_certificate_verifier(Arc::new(NoCertificateVerification(
123 rustls::crypto::aws_lc_rs::default_provider(),
124 )));
125
126 Ok(Connector::Rustls(Arc::new(config)))
127}