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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
|
use serialize::hex::FromHex;
use std::io;
use std::path::Path;
use std::fs::File;
use crypto::hash::Type::SHA256;
use crypto::pkey::PKey;
use x509::{X509, X509Generator};
use x509::extension::Extension::{KeyUsage, ExtKeyUsage, SubjectAltName, OtherNid, OtherStr};
use x509::extension::AltNameOption as SAN;
use x509::extension::KeyUsageOption::{DigitalSignature, KeyEncipherment};
use x509::extension::ExtKeyUsageOption::{self, ClientAuth, ServerAuth};
use nid::Nid;
fn get_generator() -> X509Generator {
X509Generator::new()
.set_bitlength(2048)
.set_valid_period(365 * 2)
.add_name("CN".to_string(), "test_me".to_string())
.set_sign_hash(SHA256)
.add_extension(KeyUsage(vec![DigitalSignature, KeyEncipherment]))
.add_extension(ExtKeyUsage(vec![ClientAuth,
ServerAuth,
ExtKeyUsageOption::Other("2.999.1".to_owned())]))
.add_extension(SubjectAltName(vec![(SAN::DNS, "example.com".to_owned())]))
.add_extension(OtherNid(Nid::BasicConstraints, "critical,CA:TRUE".to_owned()))
.add_extension(OtherStr("2.999.2".to_owned(), "ASN1:UTF8:example value".to_owned()))
}
#[test]
fn test_cert_gen() {
let (cert, pkey) = get_generator().generate().unwrap();
cert.write_pem(&mut io::sink()).unwrap();
pkey.write_pem(&mut io::sink()).unwrap();
// FIXME: check data in result to be correct, needs implementation
// of X509 getters
assert_eq!(pkey.save_pub(), cert.public_key().save_pub());
}
/// SubjectKeyIdentifier must be added before AuthorityKeyIdentifier or OpenSSL
/// is "unable to get issuer keyid." This test ensures the order of insertion
/// for extensions is preserved when the cert is signed.
#[test]
fn test_cert_gen_extension_ordering() {
get_generator()
.add_extension(OtherNid(Nid::SubjectKeyIdentifier, "hash".to_owned()))
.add_extension(OtherNid(Nid::AuthorityKeyIdentifier, "keyid:always".to_owned()))
.generate()
.expect("Failed to generate cert with order-dependent extensions");
}
/// Proves that a passing result from `test_cert_gen_extension_ordering` is
/// deterministic by reversing the order of extensions and asserting failure.
#[test]
fn test_cert_gen_extension_bad_ordering() {
let result = get_generator()
.add_extension(OtherNid(Nid::AuthorityKeyIdentifier, "keyid:always".to_owned()))
.add_extension(OtherNid(Nid::SubjectKeyIdentifier, "hash".to_owned()))
.generate();
assert!(result.is_err());
}
#[test]
fn test_req_gen() {
let mut pkey = PKey::new();
pkey.gen(512);
let req = get_generator().request(&pkey).unwrap();
req.write_pem(&mut io::sink()).unwrap();
// FIXME: check data in result to be correct, needs implementation
// of X509_REQ getters
}
#[test]
fn test_cert_loading() {
let cert_path = Path::new("test/cert.pem");
let mut file = File::open(&cert_path)
.ok()
.expect("Failed to open `test/cert.pem`");
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
let fingerprint = cert.fingerprint(SHA256).unwrap();
// Hash was generated as SHA256 hash of certificate "test/cert.pem"
// in DER format.
// Command: openssl x509 -in test/cert.pem -outform DER | openssl dgst -sha256
// Please update if "test/cert.pem" will ever change
let hash_str = "db400bb62f1b1f29c3b8f323b8f7d9dea724fdcd67104ef549c772ae3749655b";
let hash_vec = hash_str.from_hex().unwrap();
assert_eq!(fingerprint, hash_vec);
}
#[test]
fn test_subject_read_cn() {
let cert_path = Path::new("test/cert.pem");
let mut file = File::open(&cert_path)
.ok()
.expect("Failed to open `test/cert.pem`");
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
let subject = cert.subject_name();
let cn = match subject.text_by_nid(Nid::CN) {
Some(x) => x,
None => panic!("Failed to read CN from cert"),
};
assert_eq!(&cn as &str, "test_cert")
}
#[test]
fn test_nid_values() {
let cert_path = Path::new("test/nid_test_cert.pem");
let mut file = File::open(&cert_path)
.ok()
.expect("Failed to open `test/nid_test_cert.pem`");
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
let subject = cert.subject_name();
let cn = match subject.text_by_nid(Nid::CN) {
Some(x) => x,
None => panic!("Failed to read CN from cert"),
};
assert_eq!(&cn as &str, "example.com");
let email = match subject.text_by_nid(Nid::Email) {
Some(x) => x,
None => panic!("Failed to read subject email address from cert"),
};
assert_eq!(&email as &str, "[email protected]");
let friendly = match subject.text_by_nid(Nid::FriendlyName) {
Some(x) => x,
None => panic!("Failed to read subject friendly name from cert"),
};
assert_eq!(&friendly as &str, "Example");
}
#[test]
fn test_nid_uid_value() {
let cert_path = Path::new("test/nid_uid_test_cert.pem");
let mut file = File::open(&cert_path)
.ok()
.expect("Failed to open `test/nid_uid_test_cert.pem`");
let cert = X509::from_pem(&mut file).ok().expect("Failed to load PEM");
let subject = cert.subject_name();
let cn = match subject.text_by_nid(Nid::UserId) {
Some(x) => x,
None => panic!("Failed to read UID from cert"),
};
assert_eq!(&cn as &str, "this is the userId");
}
|