bc_components/
private_keys.rs1use anyhow::Result;
2use bc_ur::prelude::*;
3use crate::{
4 tags,
5 Decrypter,
6 Digest,
7 EncapsulationPrivateKey,
8 Reference,
9 ReferenceProvider,
10 Signature,
11 Signer,
12 SigningPrivateKey,
13};
14
15#[derive(Debug, Clone, PartialEq, Eq, Hash)]
59pub struct PrivateKeys {
60 signing_private_key: SigningPrivateKey,
61 encapsulation_private_key: EncapsulationPrivateKey,
62}
63
64impl PrivateKeys {
65 pub fn with_keys(
67 signing_private_key: SigningPrivateKey,
68 encapsulation_private_key: EncapsulationPrivateKey
69 ) -> Self {
70 Self {
71 signing_private_key,
72 encapsulation_private_key,
73 }
74 }
75
76 pub fn signing_private_key(&self) -> &SigningPrivateKey {
78 &self.signing_private_key
79 }
80
81 pub fn enapsulation_private_key(&self) -> &EncapsulationPrivateKey {
83 &self.encapsulation_private_key
84 }
85}
86
87pub trait PrivateKeysProvider {
106 fn private_keys(&self) -> PrivateKeys;
115}
116
117impl PrivateKeysProvider for PrivateKeys {
118 fn private_keys(&self) -> PrivateKeys {
119 self.clone()
120 }
121}
122
123impl ReferenceProvider for PrivateKeys {
124 fn reference(&self) -> Reference {
125 Reference::from_digest(Digest::from_image(self.tagged_cbor().to_cbor_data()))
126 }
127}
128
129impl AsRef<PrivateKeys> for PrivateKeys {
130 fn as_ref(&self) -> &PrivateKeys {
131 self
132 }
133}
134
135impl AsRef<SigningPrivateKey> for PrivateKeys {
136 fn as_ref(&self) -> &SigningPrivateKey {
137 &self.signing_private_key
138 }
139}
140
141impl AsRef<EncapsulationPrivateKey> for PrivateKeys {
142 fn as_ref(&self) -> &EncapsulationPrivateKey {
143 &self.encapsulation_private_key
144 }
145}
146
147impl CBORTagged for PrivateKeys {
148 fn cbor_tags() -> Vec<Tag> {
149 tags_for_values(&[tags::TAG_PRIVATE_KEYS])
150 }
151}
152
153impl From<PrivateKeys> for CBOR {
154 fn from(value: PrivateKeys) -> Self {
155 value.tagged_cbor()
156 }
157}
158
159impl CBORTaggedEncodable for PrivateKeys {
160 fn untagged_cbor(&self) -> CBOR {
161 let signing_key_cbor: CBOR = self.signing_private_key.clone().into();
162 let encapsulation_key_cbor: CBOR = self.encapsulation_private_key.clone().into();
163 vec![signing_key_cbor, encapsulation_key_cbor].into()
164 }
165}
166
167impl TryFrom<CBOR> for PrivateKeys {
168 type Error = dcbor::Error;
169
170 fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
171 Self::from_tagged_cbor(cbor)
172 }
173}
174
175impl CBORTaggedDecodable for PrivateKeys {
176 fn from_untagged_cbor(untagged_cbor: CBOR) -> dcbor::Result<Self> {
177 match untagged_cbor.as_case() {
178 CBORCase::Array(elements) => {
179 if elements.len() != 2 {
180 return Err("PrivateKeys must have two elements".into());
181 }
182
183 let signing_private_key = SigningPrivateKey::try_from(elements[0].clone())?;
184 let encapsulation_private_key = EncapsulationPrivateKey::try_from(
185 elements[1].clone()
186 )?;
187 Ok(Self::with_keys(signing_private_key, encapsulation_private_key))
188 }
189 _ => return Err("PrivateKeys must be an array".into()),
190 }
191 }
192}
193
194impl Signer for PrivateKeys {
195 fn sign_with_options(
196 &self,
197 message: &dyn AsRef<[u8]>,
198 options: Option<crate::SigningOptions>
199 ) -> Result<Signature> {
200 self.signing_private_key.sign_with_options(message, options)
201 }
202}
203
204impl Decrypter for PrivateKeys {
205 fn encapsulation_private_key(&self) -> EncapsulationPrivateKey {
206 self.encapsulation_private_key.clone()
207 }
208}
209
210impl std::fmt::Display for PrivateKeys {
211 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
212 write!(f, "PrivateKeys({})", self.reference().ref_hex_short())
213 }
214}
215
216#[cfg(test)]
217mod tests {
218 use bc_ur::{ UREncodable, URDecodable };
219 use hex_literal::hex;
220 use dcbor::prelude::*;
221
222 use crate::{ PrivateKeyBase, PrivateKeys, PrivateKeysProvider, ReferenceProvider };
223
224 const SEED: [u8; 16] = hex!("59f2293a5bce7d4de59e71b4207ac5d2");
225
226 #[test]
227 fn test_private_keys() {
228 crate::register_tags();
229
230 let private_key_base = PrivateKeyBase::from_data(SEED);
231 let private_keys = private_key_base.private_keys();
232
233 let cbor = CBOR::from(private_keys.clone());
234 println!("{}", cbor.diagnostic_annotated());
235
236 let private_keys_2 = PrivateKeys::try_from(cbor.clone()).unwrap();
237 assert_eq!(private_keys, private_keys_2);
238
239 let cbor_2 = CBOR::from(private_keys_2);
240 assert_eq!(cbor, cbor_2);
241
242 let ur = private_keys.ur_string();
243 assert_eq!(
244 ur,
245 "ur:crypto-prvkeys/lftansgohdcxmdahoxgepeethhvaeotkbadnssnnihsflokkfwbwryzoyasgwtfpgdrhssmhhehttansgehdcxktzmlslflpnbfzfsencspklkdygactnlykgmclrnbdmwgwgdrsqdjswkfrldjylpmtdpskfx"
246 );
247 assert_eq!(PrivateKeys::from_ur_string(&ur).unwrap(), private_keys);
248
249 assert_eq!(format!("{}", private_keys), "PrivateKeys(fa742ac8)");
250 assert_eq!(format!("{}", private_keys.reference()), "Reference(fa742ac8)");
251 }
252}