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