1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use {
pkcs8::{der::Document, AlgorithmIdentifier, ObjectIdentifier},
rcgen::{CertificateParams, DistinguishedName, DnType, SanType},
solana_sdk::{pubkey::Pubkey, signature::Keypair},
std::{error::Error, net::IpAddr},
x509_parser::{prelude::*, public_key::PublicKey},
};
pub fn new_self_signed_tls_certificate_chain(
keypair: &Keypair,
san: IpAddr,
) -> Result<(Vec<rustls::Certificate>, rustls::PrivateKey), Box<dyn Error>> {
const ED25519_IDENTIFIER: [u32; 4] = [1, 3, 101, 112];
let mut private_key = Vec::<u8>::with_capacity(34);
private_key.extend_from_slice(&[0x04, 0x20]); private_key.extend_from_slice(keypair.secret().as_bytes());
let key_pkcs8 = pkcs8::PrivateKeyInfo {
algorithm: AlgorithmIdentifier {
oid: ObjectIdentifier::from_arcs(&ED25519_IDENTIFIER).expect("Failed to convert OID"),
parameters: None,
},
private_key: &private_key,
public_key: None,
};
let key_pkcs8_der = key_pkcs8
.to_der()
.expect("Failed to convert keypair to DER")
.to_der();
let rcgen_keypair = rcgen::KeyPair::from_der(&key_pkcs8_der)?;
let mut cert_params = CertificateParams::default();
cert_params.subject_alt_names = vec![SanType::IpAddress(san)];
cert_params.alg = &rcgen::PKCS_ED25519;
cert_params.key_pair = Some(rcgen_keypair);
cert_params.distinguished_name = DistinguishedName::new();
cert_params
.distinguished_name
.push(DnType::CommonName, "Safecoin node");
let cert = rcgen::Certificate::from_params(cert_params)?;
let cert_der = cert.serialize_der().unwrap();
let priv_key = cert.serialize_private_key_der();
let priv_key = rustls::PrivateKey(priv_key);
let cert_chain = vec![rustls::Certificate(cert_der)];
Ok((cert_chain, priv_key))
}
pub fn get_pubkey_from_tls_certificate(certificates: &[rustls::Certificate]) -> Option<Pubkey> {
if certificates.len() == 1 {
let der_cert = &certificates[0];
let (_, cert) = X509Certificate::from_der(der_cert.as_ref()).ok()?;
match cert.public_key().parsed().ok()? {
PublicKey::Unknown(key) => Pubkey::try_from(key).ok(),
_ => None,
}
} else {
None
}
}
#[cfg(test)]
mod tests {
use {super::*, solana_sdk::signer::Signer, std::net::Ipv4Addr};
#[test]
fn test_generate_tls_certificate() {
let keypair = Keypair::new();
if let Ok((certs, _)) =
new_self_signed_tls_certificate_chain(&keypair, IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)))
{
if let Some(pubkey) = get_pubkey_from_tls_certificate(&certs) {
assert_eq!(pubkey, keypair.pubkey());
} else {
panic!("Failed to get certificate pubkey");
}
} else {
panic!("Failed to generate certificates");
}
}
}