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