solana_streamer/tls_certificates.rs
1use {
2 solana_sdk::{pubkey::Pubkey, signature::Keypair, signer::Signer},
3 x509_parser::{prelude::*, public_key::PublicKey},
4};
5
6pub fn new_dummy_x509_certificate(
7 keypair: &Keypair,
8) -> (
9 rustls::pki_types::CertificateDer<'static>,
10 rustls::pki_types::PrivateKeyDer<'static>,
11) {
12 // Unfortunately, rustls does not accept a "raw" Ed25519 key.
13 // We have to convert it to DER and pass it to the library.
14
15 // Convert private key into PKCS#8 v1 object.
16 // RFC 8410, Section 7: Private Key Format
17 // https://www.rfc-editor.org/rfc/rfc8410#section-7
18 //
19 // The hardcoded prefix decodes to the following ASN.1 structure:
20 //
21 // PrivateKeyInfo SEQUENCE (3 elem)
22 // version Version INTEGER 0
23 // privateKeyAlgorithm AlgorithmIdentifier SEQUENCE (1 elem)
24 // algorithm OBJECT IDENTIFIER 1.3.101.112 curveEd25519 (EdDSA 25519 signature algorithm)
25 // privateKey PrivateKey OCTET STRING (34 byte)
26 const PKCS8_PREFIX: [u8; 16] = [
27 0x30, 0x2e, 0x02, 0x01, 0x00, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x04, 0x22, 0x04,
28 0x20,
29 ];
30 let mut key_pkcs8_der = Vec::<u8>::with_capacity(PKCS8_PREFIX.len() + 32);
31 key_pkcs8_der.extend_from_slice(&PKCS8_PREFIX);
32 key_pkcs8_der.extend_from_slice(keypair.secret().as_bytes());
33
34 // Create a dummy certificate. Only the SubjectPublicKeyInfo field
35 // is relevant to the peer-to-peer protocols. The signature of the
36 // X.509 certificate is deliberately invalid. (Peer authenticity is
37 // checked in the TLS 1.3 CertificateVerify)
38 // See https://www.itu.int/rec/T-REC-X.509-201910-I/en for detailed definitions.
39
40 let mut cert_der = Vec::<u8>::with_capacity(0xf4);
41 // Certificate SEQUENCE (3 elem)
42 // tbsCertificate TBSCertificate SEQUENCE (8 elem)
43 // version [0] (1 elem)
44 // INTEGER 2
45 // serialNumber CertificateSerialNumber INTEGER (62 bit)
46 // signature AlgorithmIdentifier SEQUENCE (1 elem)
47 // algorithm OBJECT IDENTIFIER 1.3.101.112 curveEd25519 (EdDSA 25519 signature algorithm)
48 // issuer Name SEQUENCE (1 elem)
49 // RelativeDistinguishedName SET (1 elem)
50 // AttributeTypeAndValue SEQUENCE (2 elem)
51 // type AttributeType OBJECT IDENTIFIER 2.5.4.3 commonName (X.520 DN component)
52 // value AttributeValue [?] UTF8String Solana
53 // validity Validity SEQUENCE (2 elem)
54 // notBefore Time UTCTime 1970-01-01 00:00:00 UTC
55 // notAfter Time GeneralizedTime 4096-01-01 00:00:00 UTC
56 // subject Name SEQUENCE (0 elem)
57 // subjectPublicKeyInfo SubjectPublicKeyInfo SEQUENCE (2 elem)
58 // algorithm AlgorithmIdentifier SEQUENCE (1 elem)
59 // algorithm OBJECT IDENTIFIER 1.3.101.112 curveEd25519 (EdDSA 25519 signature algorithm)
60 // subjectPublicKey BIT STRING (256 bit)
61 cert_der.extend_from_slice(&[
62 0x30, 0x81, 0xf6, 0x30, 0x81, 0xa9, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x08, 0x01, 0x01,
63 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x30, 0x16,
64 0x31, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x04, 0x03, 0x0c, 0x0b, 0x53, 0x6f, 0x6c, 0x61,
65 0x6e, 0x61, 0x20, 0x6e, 0x6f, 0x64, 0x65, 0x30, 0x20, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31,
66 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x34, 0x30, 0x39, 0x36,
67 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x00, 0x30, 0x2a,
68 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x21, 0x00,
69 ]);
70 cert_der.extend_from_slice(&keypair.pubkey().to_bytes());
71 // extensions [3] (1 elem)
72 // Extensions SEQUENCE (2 elem)
73 // Extension SEQUENCE (3 elem)
74 // extnID OBJECT IDENTIFIER 2.5.29.17 subjectAltName (X.509 extension)
75 // critical BOOLEAN true
76 // extnValue OCTET STRING (13 byte) encapsulating
77 // SEQUENCE (1 elem)
78 // [2] (9 byte) localhost
79 // Extension SEQUENCE (3 elem)
80 // extnID OBJECT IDENTIFIER 2.5.29.19 basicConstraints (X.509 extension)
81 // critical BOOLEAN true
82 // extnValue OCTET STRING (2 byte) encapsulating
83 // SEQUENCE (0 elem)
84 // signatureAlgorithm AlgorithmIdentifier SEQUENCE (1 elem)
85 // algorithm OBJECT IDENTIFIER 1.3.101.112 curveEd25519 (EdDSA 25519 signature algorithm)
86 // signature BIT STRING (512 bit)
87 cert_der.extend_from_slice(&[
88 0xa3, 0x29, 0x30, 0x27, 0x30, 0x17, 0x06, 0x03, 0x55, 0x1d, 0x11, 0x01, 0x01, 0xff, 0x04,
89 0x0d, 0x30, 0x0b, 0x82, 0x09, 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 0x73, 0x74, 0x30,
90 0x0c, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x02, 0x30, 0x00, 0x30, 0x05,
91 0x06, 0x03, 0x2b, 0x65, 0x70, 0x03, 0x41, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
92 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
93 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
94 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
95 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
96 ]);
97
98 (
99 rustls::pki_types::CertificateDer::from(cert_der),
100 rustls::pki_types::PrivateKeyDer::try_from(key_pkcs8_der).unwrap(),
101 )
102}
103
104pub fn get_pubkey_from_tls_certificate(
105 der_cert: &rustls::pki_types::CertificateDer,
106) -> Option<Pubkey> {
107 let (_, cert) = X509Certificate::from_der(der_cert.as_ref()).ok()?;
108 match cert.public_key().parsed().ok()? {
109 PublicKey::Unknown(key) => Pubkey::try_from(key).ok(),
110 _ => None,
111 }
112}
113
114#[cfg(test)]
115mod tests {
116 use {super::*, solana_sdk::signer::Signer};
117
118 #[test]
119 fn test_generate_tls_certificate() {
120 let keypair = Keypair::new();
121 let (cert, _) = new_dummy_x509_certificate(&keypair);
122 if let Some(pubkey) = get_pubkey_from_tls_certificate(&cert) {
123 assert_eq!(pubkey, keypair.pubkey());
124 } else {
125 panic!("Failed to get certificate pubkey");
126 }
127 }
128}