quantcrypt/asn1/
certificate.rs1use crate::{
2 dsa::{common::dsa_trait::Dsa, dsa_manager::DsaManager},
3 kem::{common::kem_trait::Kem, kem_manager::KemManager},
4 keys::PublicKey,
5};
6use chrono::{DateTime, Utc};
7use cms::enveloped_data::RecipientIdentifier;
8use der::{Decode, DecodePem, Encode, EncodePem};
9use spki::ObjectIdentifier;
10use x509_cert::{
11 ext::pkix::{AuthorityKeyIdentifier, KeyUsage, SubjectKeyIdentifier},
12 name::RdnSequence,
13 serial_number::SerialNumber,
14};
15
16use crate::errors::QuantCryptError;
17
18type Result<T> = std::result::Result<T, QuantCryptError>;
19
20#[derive(Clone)]
35pub struct Certificate {
36 cert: x509_cert::Certificate,
37}
38
39impl Certificate {
40 pub(crate) fn new(cert: x509_cert::Certificate) -> Certificate {
50 Certificate { cert }
51 }
52
53 pub fn to_der(&self) -> Result<Vec<u8>> {
59 let result = self
60 .cert
61 .to_der()
62 .map_err(|_| QuantCryptError::InvalidCertificate)?;
63 Ok(result)
64 }
65
66 pub fn to_pem(&self) -> Result<String> {
72 let result = self
73 .cert
74 .to_pem(pkcs8::LineEnding::LF)
75 .map_err(|_| QuantCryptError::InvalidCertificate)?;
76 Ok(result)
77 }
78
79 pub fn from_der(der: &[u8]) -> Result<Certificate> {
93 let mut cert = x509_cert::Certificate::from_der(der)
94 .map_err(|_| QuantCryptError::InvalidCertificate)?;
95 let original_oid = cert
97 .tbs_certificate
98 .subject_public_key_info
99 .algorithm
100 .oid
101 .to_string();
102 let new_oid: ObjectIdentifier = original_oid
103 .parse()
104 .map_err(|_| QuantCryptError::InvalidCertificate)?;
105 cert.tbs_certificate.subject_public_key_info.algorithm.oid = new_oid;
106 Ok(Certificate::new(cert))
107 }
108
109 pub fn from_pem(pem: &str) -> Result<Certificate> {
123 let cert = x509_cert::Certificate::from_pem(pem)
124 .map_err(|_| QuantCryptError::InvalidCertificate)?;
125 Ok(Certificate::new(cert))
126 }
127
128 pub fn get_subject(&self) -> RdnSequence {
134 self.cert.tbs_certificate.subject.clone()
135 }
136
137 pub fn get_issuer(&self) -> RdnSequence {
143 self.cert.tbs_certificate.issuer.clone()
144 }
145
146 pub fn get_serial_number(&self) -> SerialNumber {
152 self.cert.tbs_certificate.serial_number.clone()
153 }
154
155 pub fn get_subject_key_identifier(&self) -> Result<SubjectKeyIdentifier> {
161 if let Some(exts) = self.cert.tbs_certificate.extensions.clone() {
162 for ext in exts {
163 if ext.extn_id == const_oid::db::rfc5280::ID_CE_SUBJECT_KEY_IDENTIFIER {
164 let ski_raw_bytes = ext.extn_value.as_bytes();
165 let ski = SubjectKeyIdentifier::from_der(ski_raw_bytes)
166 .map_err(|_| QuantCryptError::InvalidCertificate)?;
167 return Ok(ski);
168 }
169 }
170 }
171 Err(QuantCryptError::SkidNotFound)
172 }
173
174 pub fn verify_self_signed(&self) -> Result<bool> {
180 if let Some(exts) = self.cert.tbs_certificate.extensions.clone() {
182 for ext in exts {
183 if ext.extn_id == const_oid::db::rfc5280::ID_CE_BASIC_CONSTRAINTS {
184 if let Ok(bc) = ext.to_der() {
185 if let Ok(bc) = x509_cert::ext::pkix::BasicConstraints::from_der(&bc) {
186 if bc.ca {
187 break;
188 }
189 }
190 }
191 }
192 }
193 } else {
194 return Ok(false);
195 }
196
197 if self.get_subject() != self.get_issuer() {
199 return Ok(false);
200 }
201
202 let msg = self
203 .cert
204 .tbs_certificate
205 .to_der()
206 .map_err(|_| QuantCryptError::InvalidCertificate)?;
207
208 let sig = self.cert.signature.raw_bytes();
209
210 let pk = self.get_public_key()?;
211
212 let result = pk.verify(&msg, sig).unwrap_or(false);
213
214 Ok(result)
215 }
216
217 pub fn get_public_key(&self) -> Result<PublicKey> {
223 let pk_der = self
224 .cert
225 .tbs_certificate
226 .subject_public_key_info
227 .to_der()
228 .map_err(|_| QuantCryptError::InvalidCertificate)?;
229
230 let pk = PublicKey::from_der(&pk_der).map_err(|_| QuantCryptError::InvalidCertificate)?;
231
232 Ok(pk)
233 }
234
235 pub fn verify_child(&self, child: &Certificate) -> Result<bool> {
249 if self.get_subject() != child.get_issuer() {
251 return Ok(false);
252 }
253
254 if let Ok(parent_skid) = self.get_subject_key_identifier() {
256 if let Some(exts) = child.cert.tbs_certificate.extensions.clone() {
257 for ext in exts {
258 if ext.extn_id == const_oid::db::rfc5280::ID_CE_AUTHORITY_KEY_IDENTIFIER {
259 let akid = AuthorityKeyIdentifier::from_der(ext.extn_value.as_bytes())
260 .map_err(|_| QuantCryptError::InvalidCertificate)?;
261
262 let akid = if let Some(akid) = akid.key_identifier {
263 akid
264 } else {
265 return Ok(false);
266 };
267
268 if akid != parent_skid.0 {
269 return Ok(false);
270 }
271 }
272 }
273 }
274 }
275
276 let msg = child
278 .cert
279 .tbs_certificate
280 .to_der()
281 .map_err(|_| QuantCryptError::InvalidCertificate)?;
282 let sig = child.cert.signature.raw_bytes();
283 let pk = self.get_public_key()?;
284
285 let result = pk
286 .verify(&msg, sig)
287 .map_err(|_| QuantCryptError::InvalidCertificate)?;
288
289 Ok(result)
290 }
291
292 pub fn from_file(path: &str) -> Result<Certificate> {
302 let contents = std::fs::read(path).map_err(|_| QuantCryptError::FileReadError)?;
304
305 let result = Certificate::from_der(&contents);
307
308 if let Ok(cert) = result {
309 Ok(cert)
310 } else {
311 let pem =
313 std::str::from_utf8(&contents).map_err(|_| QuantCryptError::InvalidCertificate)?;
314 if let Ok(cert) = Certificate::from_pem(pem) {
315 Ok(cert)
316 } else {
317 Err(QuantCryptError::InvalidCertificate)
318 }
319 }
320 }
321
322 pub fn to_der_file(&self, path: &str) -> Result<()> {
328 let der = self.to_der()?;
329 std::fs::write(path, der).map_err(|_| QuantCryptError::InvalidCertificate)?;
330 Ok(())
331 }
332
333 pub fn to_pem_file(&self, path: &str) -> Result<()> {
339 let pem = self.to_pem()?;
340 std::fs::write(path, pem).map_err(|_| QuantCryptError::InvalidCertificate)?;
341 Ok(())
342 }
343
344 pub fn is_identified_by(&self, rid: &RecipientIdentifier) -> bool {
356 match rid {
357 cms::enveloped_data::RecipientIdentifier::IssuerAndSerialNumber(issuer) => {
358 if self.get_issuer() == issuer.issuer
359 && self.get_serial_number() == issuer.serial_number
360 {
361 return true;
362 }
363 }
364 cms::enveloped_data::RecipientIdentifier::SubjectKeyIdentifier(ski) => {
365 if let Ok(cert_ski) = self.get_subject_key_identifier() {
366 if cert_ski == *ski {
367 return true;
368 }
369 }
370 }
371 }
372 false
373 }
374
375 pub fn is_valid(&self) -> bool {
381 let not_before = self.cert.tbs_certificate.validity.not_before.to_date_time();
383 let not_after = self.cert.tbs_certificate.validity.not_after.to_date_time();
384
385 let not_before: DateTime<Utc> = not_before.to_system_time().into();
387 let not_after: DateTime<Utc> = not_after.to_system_time().into();
388
389 let now = chrono::Utc::now();
391
392 let result = now >= not_before && now <= not_after;
394
395 let oid = self.cert.signature_algorithm.oid;
397 let expected_oid = self.cert.tbs_certificate.signature.oid;
398 if oid != expected_oid {
399 return false;
400 }
401
402 result
403 }
404
405 pub fn is_key_encipherment_enabled(&self) -> bool {
411 if let Some(exts) = self.cert.tbs_certificate.extensions.clone() {
412 for ext in exts {
413 if ext.extn_id == const_oid::db::rfc5280::ID_CE_KEY_USAGE {
414 if let Ok(ku) = KeyUsage::from_der(ext.extn_value.as_bytes()) {
415 return ku.key_encipherment();
416 }
417 }
418 }
419 }
420 false
421 }
422
423 pub fn get_public_key_oid(&self) -> String {
429 self.cert
430 .tbs_certificate
431 .subject_public_key_info
432 .algorithm
433 .oid
434 .to_string()
435 }
436
437 pub fn get_signature_oid(&self) -> String {
443 self.cert.tbs_certificate.signature.oid.to_string()
444 }
445
446 pub fn get_public_key_oid_friendly_name(&self) -> String {
452 let oid = self.get_public_key_oid();
453 if let Ok(man) = DsaManager::new_from_oid(&oid) {
454 let info = man.get_dsa_info();
455 format!("{:?}", info.dsa_type)
456 } else if let Ok(man) = KemManager::new_from_oid(&oid) {
457 let info = man.get_kem_info();
458 format!("{:?}", info.kem_type)
459 } else {
460 "Unknown".to_string()
461 }
462 }
463}
464
465#[cfg(test)]
466mod tests {
467 use crate::{certificates::CertValidity, certificates::Certificate};
468
469 #[test]
472 fn test_ml_dsa44_ecdsa_p256_sha256_self_signed_cert() {
473 #[cfg(feature = "ipd")]
475 let pem_bytes = include_bytes!(
476 "../../test/data_ipd/MlDsa44EcdsaP256SHA256-2.16.840.1.114027.80.8.1.4_ta.pem"
477 );
478
479 #[cfg(not(feature = "ipd"))]
480 let pem_bytes = include_bytes!(
481 "../../test/data/MlDsa44EcdsaP256SHA256-2.16.840.1.114027.80.8.1.4_ta.pem"
482 );
483
484 let pem = std::str::from_utf8(pem_bytes).unwrap().trim();
485 let cert = Certificate::from_pem(pem).unwrap();
486 assert!(cert.verify_self_signed().unwrap());
487 }
488
489 #[test]
490 fn test_ml_dsa_44_rsa2048_pss_sha256_self_signed_cert() {
491 #[cfg(feature = "ipd")]
493 let pem_bytes = include_bytes!(
494 "../../test/data_ipd/MlDsa44Rsa2048PssSha256-2.16.840.1.114027.80.8.1.1_ta.pem"
495 );
496
497 #[cfg(not(feature = "ipd"))]
498 let pem_bytes = include_bytes!(
499 "../../test/data/MlDsa44Rsa2048PssSha256-2.16.840.1.114027.80.8.1.1_ta.pem"
500 );
501 let pem = std::str::from_utf8(pem_bytes).unwrap().trim();
502 let cert = Certificate::from_pem(&pem).unwrap();
503 assert!(cert.verify_self_signed().unwrap());
504 }
505
506 #[test]
507 fn test_ml_dsa_44_rsa2048_pkcs15_sha256_self_signed_cert() {
508 #[cfg(not(feature = "ipd"))]
509 let pem_bytes = include_bytes!(
510 "../../test/data/MlDsa44Rsa2048Pkcs15Sha256-2.16.840.1.114027.80.8.1.2_ta.pem"
511 );
512 #[cfg(feature = "ipd")]
513 let pem_bytes = include_bytes!(
514 "../../test/data_ipd/MlDsa44Rsa2048Pkcs15Sha256-2.16.840.1.114027.80.8.1.2_ta.pem"
515 );
516 let pem = std::str::from_utf8(pem_bytes).unwrap().trim();
517 let cert = Certificate::from_pem(&pem).unwrap();
518 assert!(cert.verify_self_signed().unwrap());
519 }
520
521 #[test]
522 fn test_akid_skid() {
523 let (pk, sk) = crate::dsas::DsaKeyGenerator::new(crate::dsas::DsaAlgorithm::MlDsa44)
525 .generate()
526 .unwrap();
527
528 let validity = CertValidity::new(None, "2035-01-01T00:00:00Z").unwrap();
529
530 let cert = crate::certificates::CertificateBuilder::new(
531 crate::certificates::Profile::Root,
532 None,
533 validity,
534 "CN=example.com".to_string(),
535 pk,
536 &sk,
537 )
538 .unwrap()
539 .build()
540 .unwrap();
541
542 let (pk_kem, _) = crate::kems::KemKeyGenerator::new(crate::kems::KemAlgorithm::MlKem512)
544 .generate()
545 .unwrap();
546
547 let validity = CertValidity::new(None, "2035-01-01T00:00:00Z").unwrap();
548
549 let cert_kem = crate::certificates::CertificateBuilder::new(
550 crate::certificates::Profile::Leaf {
551 issuer: cert.get_subject(),
552 enable_key_agreement: false,
553 enable_key_encipherment: true,
554 },
555 None,
556 validity,
557 "CN=example.com".to_string(),
558 pk_kem,
559 &sk,
560 )
561 .unwrap()
562 .build()
563 .unwrap();
564
565 assert!(!cert_kem.verify_self_signed().unwrap());
566 assert!(cert.verify_child(&cert_kem).unwrap());
567 }
568
569 #[test]
570 fn test_certificate_expiry() {
571 let now = chrono::Utc::now();
573 let not_before = now + chrono::Duration::seconds(2);
574 let not_after = now + chrono::Duration::seconds(5);
575
576 let validity =
577 CertValidity::new(Some(¬_before.to_rfc3339()), ¬_after.to_rfc3339()).unwrap();
578
579 let (pk, sk) = crate::dsas::DsaKeyGenerator::new(crate::dsas::DsaAlgorithm::MlDsa44)
580 .generate()
581 .unwrap();
582 let cert = crate::certificates::CertificateBuilder::new(
583 crate::certificates::Profile::Root,
584 None,
585 validity,
586 "CN=example.com".to_string(),
587 pk,
588 &sk,
589 )
590 .unwrap()
591 .build()
592 .unwrap();
593 assert!(!cert.is_valid());
594 std::thread::sleep(std::time::Duration::from_secs(3));
596 assert!(cert.is_valid());
597 std::thread::sleep(std::time::Duration::from_secs(5));
599 assert!(!cert.is_valid());
600 }
601}