Skip to content

Commit

Permalink
peer_connection: replace x509_cert with pem field
Browse files Browse the repository at this point in the history
also, make `pem` and `expires` fields private
and add `RTCCertificate::new` method, which gives a way to construct a
`RTCCertificate` using an already generated certificate (as opposed to
generating a new one using `from_params` or `from_key_pair` methods).

Fixes webrtc-rs#168
  • Loading branch information
melekes committed May 26, 2022
1 parent 9fe6af4 commit 124ab0a
Showing 1 changed file with 53 additions and 18 deletions.
71 changes: 53 additions & 18 deletions src/peer_connection/certificate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ use waitgroup::Worker;
pub struct RTCCertificate {
pub(crate) certificate: dtls::crypto::Certificate,
pub(crate) stats_id: String,
pub(crate) x509_cert: rcgen::Certificate,
pub(crate) expires: SystemTime,

pem: String,
expires: SystemTime,
}

/// Equals determines if two certificates are identical by comparing only certificate
Expand Down Expand Up @@ -100,16 +101,40 @@ impl RTCCertificate {
.unwrap()
.as_nanos() as u64
),
x509_cert,
pem: x509_cert.serialize_pem()?,
expires,
})
}

/// new constructs a `RTCCertificate` from an existing certificate. Use this method when you
/// have a persistent certificate (i.e. you don't want to generate a new one for each DTLS
/// connection).
pub fn new(certificate: dtls::crypto::Certificate, pem: &str, expires: SystemTime) -> Self {
Self {
certificate,
stats_id: format!(
"certificate-{}",
SystemTime::now()
.duration_since(UNIX_EPOCH)
.unwrap()
.as_nanos() as u64
),
pem: pem.to_owned(),
expires,
}
}

/// expires returns the timestamp after which this certificate is no longer valid.
pub fn expires(&self) -> SystemTime {
self.expires
}

/// pem returns the certificate encoded as two PEM blocks: one for the X509 certificate and the
/// other for the private key.
pub fn pem(&self) -> &str {
&self.pem
}

/// get_fingerprints returns certificate fingerprints, one of which
/// is computed with the digest algorithm used in the certificate signature.
pub fn get_fingerprints(&self) -> Result<Vec<RTCDtlsFingerprint>> {
Expand Down Expand Up @@ -239,12 +264,6 @@ impl RTCCertificate {

RTCCertificate::from_params(params)
}

/// PEM returns the certificate encoded as two pem block: once for the X509
/// certificate and the other for the private key
pub fn pem(&self) -> Result<String> {
Ok(self.x509_cert.serialize_pem()?)
}
}

#[cfg(test)]
Expand All @@ -259,9 +278,8 @@ mod test {
let kp_pem = kp.serialize_pem();
let cert = Certificate::generate_certificate(kp)?;
let cert_pem = cert.x509_cert.serialize_pem()?;
//_, err = tls.X509KeyPair(certPEM, skPEM)
//_, err = tls.X509KeyPair(cert.pem(), skPEM)
*/
Ok(())
}
Expand All @@ -273,8 +291,7 @@ mod test {
assert!(kp_pem.contains("PRIVATE KEY"));

let cert = RTCCertificate::from_key_pair(kp)?;
let cert_pem = cert.x509_cert.serialize_pem()?;
assert!(cert_pem.contains("CERTIFICATE"));
assert!(cert.pem().contains("CERTIFICATE"));

//_, err = tls.X509KeyPair(certPEM, skPEM)

Expand Down Expand Up @@ -304,14 +321,14 @@ mod test {
let kp1 = KeyPair::generate(&rcgen::PKCS_ECDSA_P256_SHA256)?;
let kp1_pem = kp1.serialize_pem();
let cert1 = RTCCertificate::from_key_pair(kp1)?;
let cert1_pem = cert1.pem()?;
let cert1_pem = cert1.pem();

let kp2 = KeyPair::generate(&rcgen::PKCS_ECDSA_P256_SHA256)?;
let _cert2 = RTCCertificate::from_key_pair(kp2)?;

let kp3 = KeyPair::from_pem(kp1_pem.as_str())?;
let kp3_pem = kp3.serialize_pem();
let _cert3 = RTCCertificate::from_pem(cert1_pem.as_str(), kp3)?;
let _cert3 = RTCCertificate::from_pem(cert1_pem, kp3)?;

assert_eq!(kp1_pem, kp3_pem);
//assert!(cert1 != cert2);
Expand Down Expand Up @@ -355,18 +372,36 @@ mod test {
let kp = KeyPair::generate(&rcgen::PKCS_ECDSA_P256_SHA256)?;
let kp_pem = kp.serialize_pem();
let cert = RTCCertificate::from_key_pair(kp)?;
let pem = cert.pem()?;
let pem = cert.pem();
log::info!("{}", pem);

let kp2 = KeyPair::from_pem(kp_pem.as_str())?;
let kp2_pem = kp2.serialize_pem();
let cert2 = RTCCertificate::from_pem(pem.as_str(), kp2)?;
let pem2 = cert2.pem()?;
let cert2 = RTCCertificate::from_pem(pem, kp2)?;
let pem2 = cert2.pem();
log::info!("{}", pem2);

assert_eq!(kp_pem, kp2_pem);
//TODO: assert_eq!(pem, pem2);

Ok(())
}

#[test]
fn test_new() -> Result<()> {
// NOTE `dtls_cert` key pair and `key_pair` are different, but it's fine here.
let key_pair = KeyPair::generate(&rcgen::PKCS_ECDSA_P256_SHA256)?;
let dtls_cert = dtls::crypto::Certificate::generate_self_signed(["localhost".to_owned()])?;

let expires = SystemTime::now();
let pem = key_pair.serialize_pem();

let cert = RTCCertificate::new(dtls_cert, &pem, expires);

assert_ne!("", cert.stats_id);
assert_eq!(expires, cert.expires());
assert_eq!(pem, cert.pem());

Ok(())
}
}

0 comments on commit 124ab0a

Please sign in to comment.