rust_ev_crypto_primitives/
direct_trust.rs1use super::basic_crypto_functions::{
20 BasisCryptoError, CertificateExtension, Keystore as SslKeystore, SigningCertificate,
21};
22use std::{
23 fs, io,
24 path::{Path, PathBuf},
25};
26use thiserror::Error;
27
28#[derive(Error, Debug)]
29#[error(transparent)]
30pub struct DirectTrustError(#[from] DirectTrustErrorRepr);
32
33#[derive(Error, Debug)]
34enum DirectTrustErrorRepr {
35 #[error("Error reading password file {path}")]
36 ReadPassword { path: PathBuf, source: io::Error },
37 #[error("Error creating the keystore from the file {path}")]
38 KeystoreFromFile {
39 path: PathBuf,
40 source: BasisCryptoError,
41 },
42 #[error("Error creating the keystore from the directory {path}")]
43 KeystoreFromDir {
44 path: PathBuf,
45 source: BasisCryptoError,
46 },
47 #[error("Error getting the public certificate {authority} from the keystore")]
48 PublicCertificate {
49 authority: String,
50 source: BasisCryptoError,
51 },
52 #[error("Error getting the private certificate from the keystore")]
53 PrivateCertificate { source: BasisCryptoError },
54}
55
56pub struct Keystore {
58 keystore: SslKeystore,
59}
60
61impl Keystore {
62 pub fn from_pkcs12(
64 keystore_path: &Path,
65 password_file_path: &Path,
66 ) -> Result<Self, DirectTrustError> {
67 let pwd = fs::read_to_string(password_file_path).map_err(|e| {
68 DirectTrustErrorRepr::ReadPassword {
69 path: password_file_path.to_path_buf(),
70 source: e,
71 }
72 })?;
73 Ok(Keystore {
74 keystore: SslKeystore::from_pkcs12(keystore_path, &pwd).map_err(|e| {
75 DirectTrustErrorRepr::KeystoreFromFile {
76 path: keystore_path.to_path_buf(),
77 source: e,
78 }
79 })?,
80 })
81 }
82
83 pub fn from_directory(
85 keystore_path: &Path,
86 extension: &CertificateExtension,
87 ) -> Result<Self, DirectTrustError> {
88 let mut ks = SslKeystore::from_directory(keystore_path).map_err(|e| {
89 DirectTrustErrorRepr::KeystoreFromDir {
90 path: keystore_path.to_path_buf(),
91 source: e,
92 }
93 })?;
94 ks.set_certificate_extension(extension);
95 Ok(Self { keystore: ks })
96 }
97
98 pub fn public_certificate(
100 &self,
101 authority: &str,
102 ) -> Result<DirectTrustCertificate, DirectTrustError> {
103 let cert = self
104 .keystore
105 .get_public_certificate(&String::from(authority))
106 .map_err(|e| DirectTrustErrorRepr::PublicCertificate {
107 authority: authority.to_string(),
108 source: e,
109 })?;
110 Ok(DirectTrustCertificate { cert })
111 }
112
113 pub fn secret_key_certificate(&self) -> Result<DirectTrustCertificate, DirectTrustError> {
117 let cert = self
118 .keystore
119 .get_secret_certificate()
120 .map_err(|e| DirectTrustErrorRepr::PrivateCertificate { source: e })?;
121 Ok(DirectTrustCertificate { cert })
122 }
123}
124
125#[derive(Clone)]
127pub struct DirectTrustCertificate {
128 cert: SigningCertificate,
129}
130
131impl DirectTrustCertificate {
132 pub fn authority(&self) -> &str {
134 self.cert.authority()
135 }
136
137 pub fn signing_certificate(&self) -> &SigningCertificate {
139 &self.cert
140 }
141}
142
143#[cfg(test)]
144mod test {
145 use super::*;
146 use std::path::PathBuf;
147
148 const VERIFIER_KEYSTORE_FILE_NAME: &str = "public_keys_keystore_verifier.p12";
149 const VERIFIER_PASSWORD_FILE_NAME: &str = "public_keys_keystore_verifier_pw.txt";
150 const CANTON_KEYSTORE_FILE_NAME: &str = "signing_keystore_canton.p12";
151 const CANTON_PASSWORD_FILE_NAME: &str = "signing_pw_canton.txt";
152
153 fn get_location() -> PathBuf {
154 Path::new("./").join("test_data").join("direct-trust")
155 }
156
157 #[test]
158 fn test_create_pkcs12() {
159 let dt = Keystore::from_pkcs12(
160 &get_location().join(Path::new(VERIFIER_KEYSTORE_FILE_NAME)),
161 &get_location().join(Path::new(VERIFIER_PASSWORD_FILE_NAME)),
162 )
163 .unwrap();
164 assert!(dt.public_certificate("canton").is_ok());
165 assert!(dt.public_certificate("toto").is_err());
166 assert!(dt.secret_key_certificate().is_err());
167 let dt = Keystore::from_pkcs12(
168 &get_location().join(Path::new(CANTON_KEYSTORE_FILE_NAME)),
169 &get_location().join(Path::new(CANTON_PASSWORD_FILE_NAME)),
170 )
171 .unwrap();
172 assert!(dt.secret_key_certificate().is_ok());
173 let dt_err = Keystore::from_pkcs12(
174 Path::new("./toto"),
175 &get_location().join(Path::new(VERIFIER_PASSWORD_FILE_NAME)),
176 );
177 assert!(dt_err.is_err());
178 }
179
180 #[test]
181 fn test_create_dir() {
182 let dt =
183 Keystore::from_directory(&get_location(), &CertificateExtension::default()).unwrap();
184 assert!(dt.public_certificate("canton").is_ok());
186 assert!(dt.public_certificate("toto").is_err());
187 let dt_err =
188 Keystore::from_directory(Path::new("./toto"), &CertificateExtension::default());
189 assert!(dt_err.is_err());
190 }
191}