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