@@ -15,11 +15,13 @@ use tokio::sync::Mutex;
15
15
use waitgroup:: Worker ;
16
16
17
17
/// Certificate represents a x509Cert used to authenticate WebRTC communications.
18
+ #[ derive( Clone ) ]
18
19
pub struct RTCCertificate {
19
20
pub ( crate ) certificate : dtls:: crypto:: Certificate ,
20
21
pub ( crate ) stats_id : String ,
21
- pub ( crate ) x509_cert : rcgen:: Certificate ,
22
- pub ( crate ) expires : SystemTime ,
22
+
23
+ pem : String ,
24
+ expires : SystemTime ,
23
25
}
24
26
25
27
/// Equals determines if two certificates are identical by comparing only certificate
@@ -100,16 +102,45 @@ impl RTCCertificate {
100
102
. unwrap( )
101
103
. as_nanos( ) as u64
102
104
) ,
103
- x509_cert,
105
+ pem : x509_cert. serialize_pem ( ) ? ,
104
106
expires,
105
107
} )
106
108
}
107
109
110
+ /// Constructs a `RTCCertificate` from an existing certificate.
111
+ ///
112
+ /// Use this method when you have a persistent certificate (i.e. you don't want to generate a
113
+ /// new one for each DTLS connection).
114
+ pub fn from_existing (
115
+ certificate : dtls:: crypto:: Certificate ,
116
+ pem : & str ,
117
+ expires : SystemTime ,
118
+ ) -> Self {
119
+ Self {
120
+ certificate,
121
+ stats_id : format ! (
122
+ "certificate-{}" ,
123
+ SystemTime :: now( )
124
+ . duration_since( UNIX_EPOCH )
125
+ . unwrap( )
126
+ . as_nanos( ) as u64
127
+ ) ,
128
+ pem : pem. to_owned ( ) ,
129
+ expires,
130
+ }
131
+ }
132
+
108
133
/// expires returns the timestamp after which this certificate is no longer valid.
109
134
pub fn expires ( & self ) -> SystemTime {
110
135
self . expires
111
136
}
112
137
138
+ /// pem returns the certificate encoded as two PEM blocks: one for the X509 certificate and the
139
+ /// other for the private key.
140
+ pub fn pem ( & self ) -> & str {
141
+ & self . pem
142
+ }
143
+
113
144
/// get_fingerprints returns certificate fingerprints, one of which
114
145
/// is computed with the digest algorithm used in the certificate signature.
115
146
pub fn get_fingerprints ( & self ) -> Result < Vec < RTCDtlsFingerprint > > {
@@ -239,12 +270,6 @@ impl RTCCertificate {
239
270
240
271
RTCCertificate :: from_params ( params)
241
272
}
242
-
243
- /// PEM returns the certificate encoded as two pem block: once for the X509
244
- /// certificate and the other for the private key
245
- pub fn pem ( & self ) -> Result < String > {
246
- Ok ( self . x509_cert . serialize_pem ( ) ?)
247
- }
248
273
}
249
274
250
275
#[ cfg( test) ]
@@ -259,9 +284,8 @@ mod test {
259
284
let kp_pem = kp.serialize_pem();
260
285
261
286
let cert = Certificate::generate_certificate(kp)?;
262
- let cert_pem = cert.x509_cert.serialize_pem()?;
263
287
264
- //_, err = tls.X509KeyPair(certPEM , skPEM)
288
+ //_, err = tls.X509KeyPair(cert.pem() , skPEM)
265
289
*/
266
290
Ok ( ( ) )
267
291
}
@@ -273,8 +297,7 @@ mod test {
273
297
assert ! ( kp_pem. contains( "PRIVATE KEY" ) ) ;
274
298
275
299
let cert = RTCCertificate :: from_key_pair ( kp) ?;
276
- let cert_pem = cert. x509_cert . serialize_pem ( ) ?;
277
- assert ! ( cert_pem. contains( "CERTIFICATE" ) ) ;
300
+ assert ! ( cert. pem( ) . contains( "CERTIFICATE" ) ) ;
278
301
279
302
//_, err = tls.X509KeyPair(certPEM, skPEM)
280
303
@@ -304,14 +327,14 @@ mod test {
304
327
let kp1 = KeyPair :: generate ( & rcgen:: PKCS_ECDSA_P256_SHA256 ) ?;
305
328
let kp1_pem = kp1. serialize_pem ( ) ;
306
329
let cert1 = RTCCertificate :: from_key_pair ( kp1) ?;
307
- let cert1_pem = cert1. pem ( ) ? ;
330
+ let cert1_pem = cert1. pem ( ) ;
308
331
309
332
let kp2 = KeyPair :: generate ( & rcgen:: PKCS_ECDSA_P256_SHA256 ) ?;
310
333
let _cert2 = RTCCertificate :: from_key_pair ( kp2) ?;
311
334
312
335
let kp3 = KeyPair :: from_pem ( kp1_pem. as_str ( ) ) ?;
313
336
let kp3_pem = kp3. serialize_pem ( ) ;
314
- let _cert3 = RTCCertificate :: from_pem ( cert1_pem. as_str ( ) , kp3) ?;
337
+ let _cert3 = RTCCertificate :: from_pem ( cert1_pem, kp3) ?;
315
338
316
339
assert_eq ! ( kp1_pem, kp3_pem) ;
317
340
//assert!(cert1 != cert2);
@@ -355,18 +378,36 @@ mod test {
355
378
let kp = KeyPair :: generate ( & rcgen:: PKCS_ECDSA_P256_SHA256 ) ?;
356
379
let kp_pem = kp. serialize_pem ( ) ;
357
380
let cert = RTCCertificate :: from_key_pair ( kp) ?;
358
- let pem = cert. pem ( ) ? ;
381
+ let pem = cert. pem ( ) ;
359
382
log:: info!( "{}" , pem) ;
360
383
361
384
let kp2 = KeyPair :: from_pem ( kp_pem. as_str ( ) ) ?;
362
385
let kp2_pem = kp2. serialize_pem ( ) ;
363
- let cert2 = RTCCertificate :: from_pem ( pem. as_str ( ) , kp2) ?;
364
- let pem2 = cert2. pem ( ) ? ;
386
+ let cert2 = RTCCertificate :: from_pem ( pem, kp2) ?;
387
+ let pem2 = cert2. pem ( ) ;
365
388
log:: info!( "{}" , pem2) ;
366
389
367
390
assert_eq ! ( kp_pem, kp2_pem) ;
368
391
//TODO: assert_eq!(pem, pem2);
369
392
370
393
Ok ( ( ) )
371
394
}
395
+
396
+ #[ test]
397
+ fn test_from_existing ( ) -> Result < ( ) > {
398
+ // NOTE `dtls_cert` key pair and `key_pair` are different, but it's fine here.
399
+ let key_pair = KeyPair :: generate ( & rcgen:: PKCS_ECDSA_P256_SHA256 ) ?;
400
+ let dtls_cert = dtls:: crypto:: Certificate :: generate_self_signed ( [ "localhost" . to_owned ( ) ] ) ?;
401
+
402
+ let expires = SystemTime :: now ( ) ;
403
+ let pem = key_pair. serialize_pem ( ) ;
404
+
405
+ let cert = RTCCertificate :: from_existing ( dtls_cert, & pem, expires) ;
406
+
407
+ assert_ne ! ( "" , cert. stats_id) ;
408
+ assert_eq ! ( expires, cert. expires( ) ) ;
409
+ assert_eq ! ( pem, cert. pem( ) ) ;
410
+
411
+ Ok ( ( ) )
412
+ }
372
413
}
0 commit comments