bc_components/
private_keys.rs1use bc_ur::prelude::*;
2
3use crate::{
4 Decrypter, Digest, EncapsulationPrivateKey, PublicKeys, Reference,
5 ReferenceProvider, 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 pub fn public_keys(&self) -> Result<PublicKeys> {
81 Ok(PublicKeys::new(
82 self.signing_private_key.public_key()?,
83 self.encapsulation_private_key.public_key()?,
84 ))
85 }
86}
87
88pub trait PrivateKeysProvider {
109 fn private_keys(&self) -> PrivateKeys;
118}
119
120impl PrivateKeysProvider for PrivateKeys {
121 fn private_keys(&self) -> PrivateKeys { self.clone() }
122}
123
124impl ReferenceProvider for PrivateKeys {
125 fn reference(&self) -> Reference {
126 Reference::from_digest(Digest::from_image(
127 self.tagged_cbor().to_cbor_data(),
128 ))
129 }
130}
131
132impl AsRef<PrivateKeys> for PrivateKeys {
133 fn as_ref(&self) -> &PrivateKeys { self }
134}
135
136impl AsRef<SigningPrivateKey> for PrivateKeys {
137 fn as_ref(&self) -> &SigningPrivateKey { &self.signing_private_key }
138}
139
140impl AsRef<EncapsulationPrivateKey> for PrivateKeys {
141 fn as_ref(&self) -> &EncapsulationPrivateKey {
142 &self.encapsulation_private_key
143 }
144}
145
146impl CBORTagged for PrivateKeys {
147 fn cbor_tags() -> Vec<Tag> { tags_for_values(&[tags::TAG_PRIVATE_KEYS]) }
148}
149
150impl From<PrivateKeys> for CBOR {
151 fn from(value: PrivateKeys) -> Self { value.tagged_cbor() }
152}
153
154impl CBORTaggedEncodable for PrivateKeys {
155 fn untagged_cbor(&self) -> CBOR {
156 #[cfg(any(
157 feature = "secp256k1",
158 feature = "ed25519",
159 feature = "ssh",
160 feature = "pqcrypto"
161 ))]
162 {
163 let _signing_key_cbor: CBOR =
164 self.signing_private_key.clone().into();
165 let _encapsulation_key_cbor: CBOR =
166 self.encapsulation_private_key.clone().into();
167 vec![_signing_key_cbor, _encapsulation_key_cbor].into()
168 }
169 #[cfg(not(any(
170 feature = "secp256k1",
171 feature = "ed25519",
172 feature = "ssh",
173 feature = "pqcrypto"
174 )))]
175 {
176 match self.signing_private_key {}
177 }
178 }
179}
180
181impl TryFrom<CBOR> for PrivateKeys {
182 type Error = dcbor::Error;
183
184 fn try_from(cbor: CBOR) -> dcbor::Result<Self> {
185 Self::from_tagged_cbor(cbor)
186 }
187}
188
189impl CBORTaggedDecodable for PrivateKeys {
190 fn from_untagged_cbor(untagged_cbor: CBOR) -> dcbor::Result<Self> {
191 match untagged_cbor.as_case() {
192 CBORCase::Array(elements) => {
193 if elements.len() != 2 {
194 return Err("PrivateKeys must have two elements".into());
195 }
196
197 let signing_private_key =
198 SigningPrivateKey::try_from(elements[0].clone())?;
199 let encapsulation_private_key =
200 EncapsulationPrivateKey::try_from(elements[1].clone())?;
201 Ok(Self::with_keys(
202 signing_private_key,
203 encapsulation_private_key,
204 ))
205 }
206 _ => Err("PrivateKeys must be an array".into()),
207 }
208 }
209}
210
211impl Signer for PrivateKeys {
212 fn sign_with_options(
213 &self,
214 message: &dyn AsRef<[u8]>,
215 options: Option<crate::SigningOptions>,
216 ) -> Result<Signature> {
217 self.signing_private_key.sign_with_options(message, options)
218 }
219}
220
221impl Decrypter for PrivateKeys {
222 fn encapsulation_private_key(&self) -> EncapsulationPrivateKey {
223 self.encapsulation_private_key.clone()
224 }
225}
226
227impl std::fmt::Display for PrivateKeys {
228 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
229 write!(
230 f,
231 "PrivateKeys({}, {}, {})",
232 self.reference().ref_hex_short(),
233 self.signing_private_key,
234 self.encapsulation_private_key
235 )
236 }
237}
238
239#[cfg(test)]
240#[cfg(feature = "secp256k1")]
241mod tests {
242 use bc_ur::{URDecodable, UREncodable};
243 use dcbor::prelude::*;
244 use hex_literal::hex;
245
246 use crate::{
247 PrivateKeyBase, PrivateKeys, PrivateKeysProvider, ReferenceProvider,
248 };
249
250 const SEED: [u8; 16] = hex!("59f2293a5bce7d4de59e71b4207ac5d2");
251
252 #[test]
253 #[cfg(feature = "secp256k1")]
254 fn test_private_keys() {
255 crate::register_tags();
256
257 let private_key_base = PrivateKeyBase::from_data(SEED);
258 let private_keys = private_key_base.private_keys();
259
260 let cbor = CBOR::from(private_keys.clone());
261 println!("{}", cbor.diagnostic_annotated());
262
263 let private_keys_2 = PrivateKeys::try_from(cbor.clone()).unwrap();
264 assert_eq!(private_keys, private_keys_2);
265
266 let cbor_2 = CBOR::from(private_keys_2);
267 assert_eq!(cbor, cbor_2);
268
269 let ur = private_keys.ur_string();
270 assert_eq!(
271 ur,
272 "ur:crypto-prvkeys/lftansgohdcxmdahoxgepeethhvaeotkbadnssnnihsflokkfwbwryzoyasgwtfpgdrhssmhhehttansgehdcxktzmlslflpnbfzfsencspklkdygactnlykgmclrnbdmwgwgdrsqdjswkfrldjylpmtdpskfx"
273 );
274 assert_eq!(PrivateKeys::from_ur_string(&ur).unwrap(), private_keys);
275
276 assert_eq!(
277 format!("{}", private_keys),
278 "PrivateKeys(fa742ac8, SigningPrivateKey(2a645922, SchnorrPrivateKey(0b02c820)), EncapsulationPrivateKey(ded5f016, X25519PrivateKey(ded5f016)))"
279 );
280 assert_eq!(
281 format!("{}", private_keys.reference()),
282 "Reference(fa742ac8)"
283 );
284 }
285}