chia_sdk_client/
tls.rs

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
10/// Loads an SSL certificate, or creates it if it doesn't exist already.
11pub 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/// Creates a native-tls connector from a certificate.
28#[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/// Creates a rustls connector from a certificate.
42#[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        client::danger::HandshakeSignatureValid,
49        crypto::{verify_tls12_signature, verify_tls13_signature, CryptoProvider},
50        pki_types::{CertificateDer, PrivateKeyDer, ServerName, UnixTime},
51        ClientConfig, DigitallySignedStruct, RootCertStore,
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}