1 use std
::cmp
::Ordering
;
3 use crate::asn1
::Asn1Time
;
4 use crate::bn
::{BigNum, MsbOption}
;
5 use crate::hash
::MessageDigest
;
7 use crate::pkey
::{PKey, Private}
;
9 use crate::stack
::Stack
;
10 use crate::x509
::extension
::{
11 AuthorityKeyIdentifier
, BasicConstraints
, ExtendedKeyUsage
, KeyUsage
, SubjectAlternativeName
,
14 use crate::x509
::store
::X509StoreBuilder
;
15 #[cfg(any(ossl102, libressl261))]
16 use crate::x509
::verify
::X509VerifyFlags
;
18 use crate::x509
::X509Builder
;
19 use crate::x509
::{X509Name, X509Req, X509StoreContext, X509VerifyResult, X509}
;
20 use hex
::{self, FromHex}
;
22 fn pkey() -> PKey
<Private
> {
23 let rsa
= Rsa
::generate(2048).unwrap();
24 PKey
::from_rsa(rsa
).unwrap()
28 fn test_cert_loading() {
29 let cert
= include_bytes
!("../../test/cert.pem");
30 let cert
= X509
::from_pem(cert
).unwrap();
31 let fingerprint
= cert
.digest(MessageDigest
::sha1()).unwrap();
33 let hash_str
= "59172d9313e84459bcff27f967e79e6e9217e584";
34 let hash_vec
= Vec
::from_hex(hash_str
).unwrap();
36 assert_eq
!(hash_vec
, &*fingerprint
);
41 let cert
= include_bytes
!("../../test/cert.pem");
42 let cert
= X509
::from_pem(cert
).unwrap();
43 let debugged
= format
!("{:#?}", cert
);
45 assert
!(debugged
.contains(r
#"serial_number: "8771f7bdee982fa5""#));
46 #[cfg(not(boringssl))]
47 assert
!(debugged
.contains(r
#"serial_number: "8771F7BDEE982FA5""#));
48 assert
!(debugged
.contains(r
#"signature_algorithm: sha256WithRSAEncryption"#));
49 assert
!(debugged
.contains(r
#"countryName = "AU""#));
50 assert
!(debugged
.contains(r
#"stateOrProvinceName = "Some-State""#));
51 assert
!(debugged
.contains(r
#"not_before: Aug 14 17:00:03 2016 GMT"#));
52 assert
!(debugged
.contains(r
#"not_after: Aug 12 17:00:03 2026 GMT"#));
56 fn test_cert_issue_validity() {
57 let cert
= include_bytes
!("../../test/cert.pem");
58 let cert
= X509
::from_pem(cert
).unwrap();
59 let not_before
= cert
.not_before().to_string();
60 let not_after
= cert
.not_after().to_string();
62 assert_eq
!(not_before
, "Aug 14 17:00:03 2016 GMT");
63 assert_eq
!(not_after
, "Aug 12 17:00:03 2026 GMT");
68 let cert
= include_bytes
!("../../test/cert.pem");
69 let cert
= X509
::from_pem(cert
).unwrap();
71 let der
= cert
.to_der().unwrap();
72 assert
!(!der
.is_empty());
76 fn test_subject_read_cn() {
77 let cert
= include_bytes
!("../../test/cert.pem");
78 let cert
= X509
::from_pem(cert
).unwrap();
79 let subject
= cert
.subject_name();
80 let cn
= subject
.entries_by_nid(Nid
::COMMONNAME
).next().unwrap();
81 assert_eq
!(cn
.data().as_slice(), b
"foobar.com")
85 fn test_nid_values() {
86 let cert
= include_bytes
!("../../test/nid_test_cert.pem");
87 let cert
= X509
::from_pem(cert
).unwrap();
88 let subject
= cert
.subject_name();
90 let cn
= subject
.entries_by_nid(Nid
::COMMONNAME
).next().unwrap();
91 assert_eq
!(cn
.data().as_slice(), b
"example.com");
94 .entries_by_nid(Nid
::PKCS9_EMAILADDRESS
)
97 assert_eq
!(email
.data().as_slice(), b
"test@example.com");
99 let friendly
= subject
.entries_by_nid(Nid
::FRIENDLYNAME
).next().unwrap();
100 assert_eq
!(&**friendly
.data().as_utf8().unwrap(), "Example");
104 fn test_nameref_iterator() {
105 let cert
= include_bytes
!("../../test/nid_test_cert.pem");
106 let cert
= X509
::from_pem(cert
).unwrap();
107 let subject
= cert
.subject_name();
108 let mut all_entries
= subject
.entries();
110 let email
= all_entries
.next().unwrap();
112 email
.object().nid().as_raw(),
113 Nid
::PKCS9_EMAILADDRESS
.as_raw()
115 assert_eq
!(email
.data().as_slice(), b
"test@example.com");
117 let cn
= all_entries
.next().unwrap();
118 assert_eq
!(cn
.object().nid().as_raw(), Nid
::COMMONNAME
.as_raw());
119 assert_eq
!(cn
.data().as_slice(), b
"example.com");
121 let friendly
= all_entries
.next().unwrap();
122 assert_eq
!(friendly
.object().nid().as_raw(), Nid
::FRIENDLYNAME
.as_raw());
123 assert_eq
!(&**friendly
.data().as_utf8().unwrap(), "Example");
125 if all_entries
.next().is_some() {
131 fn test_nid_uid_value() {
132 let cert
= include_bytes
!("../../test/nid_uid_test_cert.pem");
133 let cert
= X509
::from_pem(cert
).unwrap();
134 let subject
= cert
.subject_name();
136 let cn
= subject
.entries_by_nid(Nid
::USERID
).next().unwrap();
137 assert_eq
!(cn
.data().as_slice(), b
"this is the userId");
141 fn test_subject_alt_name() {
142 let cert
= include_bytes
!("../../test/alt_name_cert.pem");
143 let cert
= X509
::from_pem(cert
).unwrap();
145 let subject_alt_names
= cert
.subject_alt_names().unwrap();
146 assert_eq
!(5, subject_alt_names
.len());
147 assert_eq
!(Some("example.com"), subject_alt_names
[0].dnsname());
148 assert_eq
!(subject_alt_names
[1].ipaddress(), Some(&[127, 0, 0, 1][..]));
150 subject_alt_names
[2].ipaddress(),
151 Some(&b
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])
153 assert_eq
!(Some("test@example.com"), subject_alt_names
[3].email());
154 assert_eq
!(Some("http://www.example.com"), subject_alt_names
[4].uri());
158 fn test_subject_alt_name_iter() {
159 let cert
= include_bytes
!("../../test/alt_name_cert.pem");
160 let cert
= X509
::from_pem(cert
).unwrap();
162 let subject_alt_names
= cert
.subject_alt_names().unwrap();
163 let mut subject_alt_names_iter
= subject_alt_names
.iter();
165 subject_alt_names_iter
.next().unwrap().dnsname(),
169 subject_alt_names_iter
.next().unwrap().ipaddress(),
170 Some(&[127, 0, 0, 1][..])
173 subject_alt_names_iter
.next().unwrap().ipaddress(),
174 Some(&b
"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\x01"[..])
177 subject_alt_names_iter
.next().unwrap().email(),
178 Some("test@example.com")
181 subject_alt_names_iter
.next().unwrap().uri(),
182 Some("http://www.example.com")
184 assert
!(subject_alt_names_iter
.next().is_none());
188 fn test_aia_ca_issuer() {
190 let cert
= include_bytes
!("../../test/aia_test_cert.pem");
191 let cert
= X509
::from_pem(cert
).unwrap();
192 let authority_info
= cert
.authority_info().unwrap();
193 assert_eq
!(authority_info
.len(), 1);
194 assert_eq
!(authority_info
[0].method().to_string(), "CA Issuers");
196 authority_info
[0].location().uri(),
197 Some("http://www.example.com/cert.pem")
200 let cert
= include_bytes
!("../../test/cert.pem");
201 let cert
= X509
::from_pem(cert
).unwrap();
202 assert
!(cert
.authority_info().is_none());
209 let mut name
= X509Name
::builder().unwrap();
210 name
.append_entry_by_nid(Nid
::COMMONNAME
, "foobar.com")
212 let name
= name
.build();
214 let mut builder
= X509
::builder().unwrap();
215 builder
.set_version(2).unwrap();
216 builder
.set_subject_name(&name
).unwrap();
217 builder
.set_issuer_name(&name
).unwrap();
219 .set_not_before(&Asn1Time
::days_from_now(0).unwrap())
222 .set_not_after(&Asn1Time
::days_from_now(365).unwrap())
224 builder
.set_pubkey(&pkey
).unwrap();
226 let mut serial
= BigNum
::new().unwrap();
227 serial
.rand(128, MsbOption
::MAYBE_ZERO
, false).unwrap();
229 .set_serial_number(&serial
.to_asn1_integer().unwrap())
232 let basic_constraints
= BasicConstraints
::new().critical().ca().build().unwrap();
233 builder
.append_extension(basic_constraints
).unwrap();
234 let key_usage
= KeyUsage
::new()
239 builder
.append_extension(key_usage
).unwrap();
240 let ext_key_usage
= ExtendedKeyUsage
::new()
246 builder
.append_extension(ext_key_usage
).unwrap();
247 let subject_key_identifier
= SubjectKeyIdentifier
::new()
248 .build(&builder
.x509v3_context(None
, None
))
250 builder
.append_extension(subject_key_identifier
).unwrap();
251 let authority_key_identifier
= AuthorityKeyIdentifier
::new()
253 .build(&builder
.x509v3_context(None
, None
))
255 builder
.append_extension(authority_key_identifier
).unwrap();
256 let subject_alternative_name
= SubjectAlternativeName
::new()
258 .build(&builder
.x509v3_context(None
, None
))
260 builder
.append_extension(subject_alternative_name
).unwrap();
262 builder
.sign(&pkey
, MessageDigest
::sha256()).unwrap();
264 let x509
= builder
.build();
266 assert
!(pkey
.public_eq(&x509
.public_key().unwrap()));
267 assert
!(x509
.verify(&pkey
).unwrap());
271 .entries_by_nid(Nid
::COMMONNAME
)
274 assert_eq
!(cn
.data().as_slice(), b
"foobar.com");
275 assert_eq
!(serial
, x509
.serial_number().to_bn().unwrap());
279 fn x509_req_builder() {
282 let mut name
= X509Name
::builder().unwrap();
283 name
.append_entry_by_nid(Nid
::COMMONNAME
, "foobar.com")
285 let name
= name
.build();
287 let mut builder
= X509Req
::builder().unwrap();
288 builder
.set_version(0).unwrap();
289 builder
.set_subject_name(&name
).unwrap();
290 builder
.set_pubkey(&pkey
).unwrap();
292 let mut extensions
= Stack
::new().unwrap();
293 let key_usage
= KeyUsage
::new()
298 extensions
.push(key_usage
).unwrap();
299 let subject_alternative_name
= SubjectAlternativeName
::new()
301 .build(&builder
.x509v3_context(None
))
303 extensions
.push(subject_alternative_name
).unwrap();
304 builder
.add_extensions(&extensions
).unwrap();
306 builder
.sign(&pkey
, MessageDigest
::sha256()).unwrap();
308 let req
= builder
.build();
309 assert
!(req
.public_key().unwrap().public_eq(&pkey
));
310 assert_eq
!(req
.extensions().unwrap().len(), extensions
.len());
311 assert
!(req
.verify(&pkey
).unwrap());
315 fn test_stack_from_pem() {
316 let certs
= include_bytes
!("../../test/certs.pem");
317 let certs
= X509
::stack_from_pem(certs
).unwrap();
319 assert_eq
!(certs
.len(), 2);
321 hex
::encode(certs
[0].digest(MessageDigest
::sha1()).unwrap()),
322 "59172d9313e84459bcff27f967e79e6e9217e584"
325 hex
::encode(certs
[1].digest(MessageDigest
::sha1()).unwrap()),
326 "c0cbdf7cdd03c9773e5468e1f6d2da7d5cbb1875"
332 let cert
= include_bytes
!("../../test/cert.pem");
333 let cert
= X509
::from_pem(cert
).unwrap();
334 let ca
= include_bytes
!("../../test/root-ca.pem");
335 let ca
= X509
::from_pem(ca
).unwrap();
337 assert_eq
!(ca
.issued(&cert
), X509VerifyResult
::OK
);
338 assert_ne
!(cert
.issued(&cert
), X509VerifyResult
::OK
);
343 let cert
= include_bytes
!("../../test/cert.pem");
344 let cert
= X509
::from_pem(cert
).unwrap();
345 let signature
= cert
.signature();
347 hex
::encode(signature
.as_slice()),
348 "4af607b889790b43470442cfa551cdb8b6d0b0340d2958f76b9e3ef6ad4992230cead6842587f0ecad5\
349 78e6e11a221521e940187e3d6652de14e84e82f6671f097cc47932e022add3c0cb54a26bf27fa84c107\
350 4971caa6bee2e42d34a5b066c427f2d452038082b8073993399548088429de034fdd589dcfb0dd33be7\
351 ebdfdf698a28d628a89568881d658151276bde333600969502c4e62e1d3470a683364dfb241f78d310a\
352 89c119297df093eb36b7fd7540224f488806780305d1e79ffc938fe2275441726522ab36d88348e6c51\
353 f13dcc46b5e1cdac23c974fd5ef86aa41e91c9311655090a52333bc79687c748d833595d4c5f987508f\
356 let algorithm
= cert
.signature_algorithm();
357 assert_eq
!(algorithm
.object().nid(), Nid
::SHA256WITHRSAENCRYPTION
);
358 assert_eq
!(algorithm
.object().to_string(), "sha256WithRSAEncryption");
362 #[allow(clippy::redundant_clone)]
364 let cert
= include_bytes
!("../../test/cert.pem");
365 let cert
= X509
::from_pem(cert
).unwrap();
370 fn test_verify_cert() {
371 let cert
= include_bytes
!("../../test/cert.pem");
372 let cert
= X509
::from_pem(cert
).unwrap();
373 let ca
= include_bytes
!("../../test/root-ca.pem");
374 let ca
= X509
::from_pem(ca
).unwrap();
375 let chain
= Stack
::new().unwrap();
377 let mut store_bldr
= X509StoreBuilder
::new().unwrap();
378 store_bldr
.add_cert(ca
).unwrap();
379 let store
= store_bldr
.build();
381 let mut context
= X509StoreContext
::new().unwrap();
383 .init(&store
, &cert
, &chain
, |c
| c
.verify_cert())
386 .init(&store
, &cert
, &chain
, |c
| c
.verify_cert())
391 fn test_verify_fails() {
392 let cert
= include_bytes
!("../../test/cert.pem");
393 let cert
= X509
::from_pem(cert
).unwrap();
394 let ca
= include_bytes
!("../../test/alt_name_cert.pem");
395 let ca
= X509
::from_pem(ca
).unwrap();
396 let chain
= Stack
::new().unwrap();
398 let mut store_bldr
= X509StoreBuilder
::new().unwrap();
399 store_bldr
.add_cert(ca
).unwrap();
400 let store
= store_bldr
.build();
402 let mut context
= X509StoreContext
::new().unwrap();
404 .init(&store
, &cert
, &chain
, |c
| c
.verify_cert())
409 #[cfg(any(ossl102, libressl261))]
410 fn test_verify_fails_with_crl_flag_set_and_no_crl() {
411 let cert
= include_bytes
!("../../test/cert.pem");
412 let cert
= X509
::from_pem(cert
).unwrap();
413 let ca
= include_bytes
!("../../test/root-ca.pem");
414 let ca
= X509
::from_pem(ca
).unwrap();
415 let chain
= Stack
::new().unwrap();
417 let mut store_bldr
= X509StoreBuilder
::new().unwrap();
418 store_bldr
.add_cert(ca
).unwrap();
419 store_bldr
.set_flags(X509VerifyFlags
::CRL_CHECK
).unwrap();
420 let store
= store_bldr
.build();
422 let mut context
= X509StoreContext
::new().unwrap();
425 .init(&store
, &cert
, &chain
, |c
| {
431 "unable to get certificate CRL"
437 fn x509_ref_version() {
438 let mut builder
= X509Builder
::new().unwrap();
439 let expected_version
= 2;
441 .set_version(expected_version
)
442 .expect("Failed to set certificate version");
443 let cert
= builder
.build();
444 let actual_version
= cert
.version();
446 expected_version
, actual_version
,
447 "Obtained certificate version is incorrect",
453 fn x509_ref_version_no_version_set() {
454 let cert
= X509Builder
::new().unwrap().build();
455 let actual_version
= cert
.version();
458 "Default certificate version is incorrect",
463 fn test_save_subject_der() {
464 let cert
= include_bytes
!("../../test/cert.pem");
465 let cert
= X509
::from_pem(cert
).unwrap();
467 let der
= cert
.subject_name().to_der().unwrap();
468 println
!("der: {:?}", der
);
469 assert
!(!der
.is_empty());
473 fn test_load_subject_der() {
474 // The subject from ../../test/cert.pem
475 const SUBJECT_DER
: &[u8] = &[
476 48, 90, 49, 11, 48, 9, 6, 3, 85, 4, 6, 19, 2, 65, 85, 49, 19, 48, 17, 6, 3, 85, 4, 8, 12,
477 10, 83, 111, 109, 101, 45, 83, 116, 97, 116, 101, 49, 33, 48, 31, 6, 3, 85, 4, 10, 12, 24,
478 73, 110, 116, 101, 114, 110, 101, 116, 32, 87, 105, 100, 103, 105, 116, 115, 32, 80, 116,
479 121, 32, 76, 116, 100, 49, 19, 48, 17, 6, 3, 85, 4, 3, 12, 10, 102, 111, 111, 98, 97, 114,
482 X509Name
::from_der(SUBJECT_DER
).unwrap();
486 fn test_convert_to_text() {
487 let cert
= include_bytes
!("../../test/cert.pem");
488 let cert
= X509
::from_pem(cert
).unwrap();
490 const SUBSTRINGS
: &[&str] = &[
493 "Signature Algorithm:",
494 "Issuer: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd\n",
495 "Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=foobar.com\n",
496 "Subject Public Key Info:",
499 let text
= String
::from_utf8(cert
.to_text().unwrap()).unwrap();
501 for substring
in SUBSTRINGS
{
503 text
.contains(substring
),
504 "{:?} not found inside {}",
512 fn test_convert_req_to_text() {
513 let csr
= include_bytes
!("../../test/csr.pem");
514 let csr
= X509Req
::from_pem(csr
).unwrap();
516 const SUBSTRINGS
: &[&str] = &[
517 "Certificate Request:\n",
519 "Subject: C=AU, ST=Some-State, O=Internet Widgits Pty Ltd, CN=foobar.com\n",
520 "Subject Public Key Info:",
521 "Signature Algorithm:",
524 let text
= String
::from_utf8(csr
.to_text().unwrap()).unwrap();
526 for substring
in SUBSTRINGS
{
528 text
.contains(substring
),
529 "{:?} not found inside {}",
538 let cert
= include_bytes
!("../../test/cert.pem");
539 let cert
= X509
::from_pem(cert
).unwrap();
541 let subject
= cert
.subject_name();
542 let issuer
= cert
.issuer_name();
543 assert_eq
!(Ordering
::Equal
, subject
.try_cmp(subject
).unwrap());
544 assert_eq
!(Ordering
::Greater
, subject
.try_cmp(issuer
).unwrap());