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