certkit/lib.rs
1//! # CertKit - A Pure Rust Certificate Management Library
2//!
3//! CertKit is a comprehensive certificate management library built entirely with rustcrypto libraries,
4//! providing an alternative to rcgen without dependencies on ring or openssl (except for testing).
5//! It supports creating and managing X.509 certificate chains, including loading intermediate CAs
6//! and generating server and client certificates.
7//!
8//! ## Supported Key Types
9//!
10//! CertKit supports the following cryptographic key types:
11//! - **RSA**: 2048, 3072, and 4096-bit keys
12//! - **ECDSA**: P-256, P-384, and P-521 curves
13//! - **Ed25519**: Edwards curve digital signature algorithm
14//!
15//! ## Supported Certificate Formats
16//!
17//! - **DER**: Distinguished Encoding Rules (binary format)
18//! - **PEM**: Privacy-Enhanced Mail (base64-encoded text format)
19//!
20//! ## Key Features
21//!
22//! - **Pure Rust**: Built entirely with rustcrypto libraries
23//! - **Certificate Chain Building**: Create multi-level certificate hierarchies
24//! - **Self-Signed Certificates**: Generate root CA certificates
25//! - **Intermediate CAs**: Support for multi-level certificate authorities
26//! - **X.509 Extensions**: Comprehensive support for standard extensions
27//! - **Format Flexibility**: Import/export in both PEM and DER formats
28//!
29//! ## Scope
30//!
31//! CertKit *builds* and *parses* certificates and keys. It does **not** verify
32//! signatures or perform certificate-path/chain validation, pair it with a
33//! verifier such as [`rustls`]/[`webpki`] when you need to validate a chain.
34//!
35//! [`rustls`]: https://docs.rs/rustls
36//! [`webpki`]: https://docs.rs/webpki
37//!
38//! ## Quick Start
39//!
40//! ### Generating a Self-Signed Certificate
41//!
42//! ```rust,no_run
43//! use certkit::{
44//! key::KeyPair,
45//! cert::{Certificate, params::{CertificateParams, DistinguishedName}},
46//! };
47//!
48//! # fn main() -> Result<(), certkit::error::CertKitError> {
49//! // Generate an RSA key pair
50//! let key_pair = KeyPair::generate_rsa(2048)?;
51//!
52//! // Create certificate parameters
53//! let subject = DistinguishedName::builder()
54//! .common_name("example.com".to_string())
55//! .organization("Example Corp".to_string())
56//! .country("US".to_string())
57//! .build();
58//!
59//! let cert_info = CertificateParams::builder()
60//! .subject(subject)
61//! .subject_public_key(certkit::key::PublicKey::from_key_pair(&key_pair))
62//! .build();
63//!
64//! // Generate the self-signed certificate
65//! let certificate = Certificate::new_self_signed(&cert_info, &key_pair)?;
66//!
67//! // Export to PEM format
68//! let pem_cert = certificate.to_pem()?;
69//! println!("Certificate:\n{}", pem_cert);
70//! # Ok(())
71//! # }
72//! ```
73//!
74//! ### Creating a Certificate Chain
75//!
76//! ```rust,no_run
77//! use certkit::{
78//! key::KeyPair,
79//! cert::{Certificate, CertificateWithPrivateKey, params::{CertificateParams, DistinguishedName, Validity}},
80//! issuer::Issuer,
81//! };
82//!
83//! # fn main() -> Result<(), certkit::error::CertKitError> {
84//! // Generate keys for CA and end-entity
85//! let ca_key = KeyPair::generate_ecdsa_p256();
86//! let server_key = KeyPair::generate_ecdsa_p256();
87//!
88//! // Create CA certificate
89//! let ca_subject = DistinguishedName::builder()
90//! .common_name("Example CA".to_string())
91//! .organization("Example Corp".to_string())
92//! .build();
93//!
94//! let ca_cert_info = CertificateParams::builder()
95//! .subject(ca_subject)
96//! .subject_public_key(certkit::key::PublicKey::from_key_pair(&ca_key))
97//! .is_ca(true)
98//! .build();
99//!
100//! let ca_cert = Certificate::new_self_signed(&ca_cert_info, &ca_key)?;
101//! let ca_with_key = CertificateWithPrivateKey::new(ca_cert, ca_key);
102//!
103//! // Create server certificate signed by CA
104//! let server_subject = DistinguishedName::builder()
105//! .common_name("server.example.com".to_string())
106//! .build();
107//!
108//! let server_cert_info = CertificateParams::builder()
109//! .subject(server_subject)
110//! .subject_public_key(certkit::key::PublicKey::from_key_pair(&server_key))
111//! .build();
112//!
113//! let validity = Validity::for_days(365)?;
114//! let server_cert = ca_with_key.issue(&server_cert_info, validity)?;
115//!
116//! println!("Server certificate issued successfully!");
117//! # Ok(())
118//! # }
119//! ```
120//!
121//! ### Working with Certificate Extensions
122//!
123//! ```rust,no_run
124//! use certkit::{
125//! key::KeyPair,
126//! cert::{
127//! Certificate,
128//! params::{CertificateParams, DistinguishedName, ExtensionParam},
129//! extensions::{SubjectAltName, ExtendedKeyUsage, ExtendedKeyUsageOption, ToAndFromX509Extension},
130//! },
131//! };
132//!
133//! # fn main() -> Result<(), certkit::error::CertKitError> {
134//! let key_pair = KeyPair::generate_ed25519();
135//!
136//! // Create Subject Alternative Name extension
137//! let san = SubjectAltName {
138//! dns_names: vec!["example.com".to_string(), "www.example.com".to_string()],
139//! ..Default::default()
140//! };
141//!
142//! // Create Extended Key Usage extension
143//! let eku = ExtendedKeyUsage {
144//! usage: vec![ExtendedKeyUsageOption::ServerAuth, ExtendedKeyUsageOption::ClientAuth],
145//! };
146//!
147//! let subject = DistinguishedName::builder()
148//! .common_name("example.com".to_string())
149//! .build();
150//!
151//! let cert_info = CertificateParams::builder()
152//! .subject(subject)
153//! .subject_public_key(certkit::key::PublicKey::from_key_pair(&key_pair))
154//! .extensions(vec![
155//! ExtensionParam::from_extension(san, false)?,
156//! ExtensionParam::from_extension(eku, true)?,
157//! ])
158//! .build();
159//!
160//! let certificate = Certificate::new_self_signed(&cert_info, &key_pair)?;
161//! println!("Certificate with extensions created successfully!");
162//! # Ok(())
163//! # }
164//! ```
165//!
166//! ## Error Handling
167//!
168//! CertKit uses a comprehensive error system that provides detailed information about failures:
169//!
170//! ```rust
171//! use certkit::{key::KeyPair, error::CertKitError};
172//!
173//! match KeyPair::import_from_pkcs8_pem("invalid pem data") {
174//! Ok(key_pair) => println!("Key imported successfully"),
175//! Err(CertKitError::DecodingError(msg)) => println!("Failed to decode key: {}", msg),
176//! Err(CertKitError::InvalidInput(msg)) => println!("Invalid input: {}", msg),
177//! Err(e) => println!("Other error: {}", e),
178//! }
179//! ```
180//!
181//! ## Module Organization
182//!
183//! - [`key`]: Key generation, import/export, and cryptographic operations
184//! - [`cert`]: Certificate creation, encoding/decoding, and management
185//! - [`issuer`]: Certificate issuing functionality and CA operations
186//! - [`error`]: Comprehensive error types and handling
187//! - [`tbs_certificate`]: Low-level certificate structure manipulation
188
189#[cfg(not(any(
190 feature = "ed25519",
191 feature = "rsa",
192 feature = "p256",
193 feature = "p384",
194 feature = "p521"
195)))]
196compile_error!("Please enable at least 1 cryptographic algorithm to use certkit");
197
198pub mod cert;
199pub mod error;
200pub mod issuer;
201pub mod key;
202pub mod tbs_certificate;
203
204/// Initializes `env_logger` for unit tests. Defaults to the `error` level so
205/// the suite is quiet, but `RUST_LOG` still overrides it.
206#[cfg(test)]
207pub(crate) fn init_test_logger() {
208 let _ = env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("error"))
209 .is_test(true)
210 .try_init();
211}