1use std::sync::Arc;
4
5use anyhow::{Context, Result};
6
7use crate::{cert_x509, util::cryptoutil};
8
9pub trait CertManager: Send + Sync {
10 fn get_ca_cert(&self) -> Result<Vec<u8>>;
11 fn get_ca_key(&self) -> Result<p256::SecretKey>;
12 fn get_ca_public_key(&self) -> Result<Vec<u8>>;
13 fn get_user_cert(&self, id: u64) -> Result<Vec<u8>>;
14 fn get_user_key(&self, id: u64) -> Result<p256::SecretKey>;
15 fn get_fabric_id(&self) -> u64;
16}
17
18pub struct FileCertManager {
21 fabric_id: u64,
22 path: String,
23}
24
25impl FileCertManager {
26 pub fn new(fabric_id: u64, path: &str) -> Arc<Self> {
27 Arc::new(Self {
28 fabric_id,
29 path: path.to_owned(),
30 })
31 }
32 pub fn load(path: &str) -> Result<Arc<Self>> {
33 let fname = format!("{}/metadata.pem", path);
34 let fabric_str =
35 std::fs::read_to_string(&fname).context(format!("can't read from {}", fname))?;
36 let fabric_id = fabric_str.parse::<u64>()?;
37 Ok(Arc::new(Self {
38 fabric_id,
39 path: path.to_owned(),
40 }))
41 }
42 fn user_key_fname(&self, id: u64) -> String {
43 format!("{}/{}-private.pem", self.path, id)
44 }
45 fn ca_key_fname(&self) -> String {
46 format!("{}/ca-private.pem", self.path)
47 }
48 fn user_cert_fname(&self, id: u64) -> String {
49 format!("{}/{}-cert.pem", self.path, id)
50 }
51 fn ca_cert_fname(&self) -> String {
52 format!("{}/ca-cert.pem", self.path)
53 }
54 fn metadata_fname(&self) -> String {
55 format!("{}/metadata.pem", self.path)
56 }
57}
58
59const CA_NODE_ID: u64 = 1;
60
61impl FileCertManager {
77 pub fn bootstrap(&self) -> Result<()> {
80 std::fs::create_dir(&self.path)?;
81
82 let secret_key = p256::SecretKey::random(&mut rand::thread_rng());
83 let data = cryptoutil::secret_key_to_rfc5915(&secret_key)?;
84 let pem = pem::Pem::new("EC PRIVATE KEY", data);
85 std::fs::write(self.ca_key_fname(), pem::encode(&pem).as_bytes())?;
86 let node_public_key = secret_key.public_key().to_sec1_bytes();
87
88 let x509 = cert_x509::encode_x509(
89 &node_public_key,
90 CA_NODE_ID,
91 self.fabric_id,
92 CA_NODE_ID,
93 &secret_key,
94 true,
95 )?;
96 cryptoutil::write_pem("CERTIFICATE", &x509, &self.ca_cert_fname())?;
97 std::fs::write(self.metadata_fname(), format!("{}", self.fabric_id))?;
98 Ok(())
99 }
100
101 pub fn create_user(&self, id: u64) -> Result<()> {
104 let ca_private = self.get_ca_key()?;
105 let secret_key = p256::SecretKey::random(&mut rand::thread_rng());
106 let data = cryptoutil::secret_key_to_rfc5915(&secret_key)?;
107 let pem = pem::Pem::new("EC PRIVATE KEY", data);
108 std::fs::write(self.user_key_fname(id), pem::encode(&pem).as_bytes())?;
109 let node_public_key = secret_key.public_key().to_sec1_bytes();
110
111 let x509 = cert_x509::encode_x509(
112 &node_public_key,
113 id,
114 self.fabric_id,
115 CA_NODE_ID,
116 &ca_private,
117 false,
118 )?;
119 cryptoutil::write_pem("CERTIFICATE", &x509, &self.user_cert_fname(id))?;
120 Ok(())
121 }
122}
123
124impl CertManager for FileCertManager {
125 fn get_ca_cert(&self) -> Result<Vec<u8>> {
126 cryptoutil::read_data_from_pem(&self.ca_cert_fname())
127 }
128
129 fn get_ca_key(&self) -> Result<p256::SecretKey> {
130 cryptoutil::read_private_key_from_pem(&self.ca_key_fname())
131 }
132
133 fn get_user_cert(&self, id: u64) -> Result<Vec<u8>> {
134 cryptoutil::read_data_from_pem(&self.user_cert_fname(id))
135 }
136
137 fn get_user_key(&self, id: u64) -> Result<p256::SecretKey> {
138 cryptoutil::read_private_key_from_pem(&self.user_key_fname(id))
139 }
140
141 fn get_ca_public_key(&self) -> Result<Vec<u8>> {
142 Ok(self.get_ca_key()?.public_key().to_sec1_bytes().to_vec())
143 }
144
145 fn get_fabric_id(&self) -> u64 {
146 self.fabric_id
147 }
148}