bc_components/
public_keys.rs1use bc_ur::prelude::*;
2
3use crate::{
4 Digest, EncapsulationPublicKey, Encrypter, Reference, ReferenceProvider,
5 Signature, SigningPublicKey, Verifier, tags,
6};
7
8#[derive(Clone, PartialEq, Eq, Debug, Hash)]
51pub struct PublicKeys {
52 signing_public_key: SigningPublicKey,
53 encapsulation_public_key: EncapsulationPublicKey,
54}
55
56impl PublicKeys {
57 pub fn new(
60 signing_public_key: SigningPublicKey,
61 encapsulation_public_key: EncapsulationPublicKey,
62 ) -> Self {
63 Self { signing_public_key, encapsulation_public_key }
64 }
65
66 pub fn signing_public_key(&self) -> &SigningPublicKey {
68 &self.signing_public_key
69 }
70
71 pub fn enapsulation_public_key(&self) -> &EncapsulationPublicKey {
73 &self.encapsulation_public_key
74 }
75}
76
77pub trait PublicKeysProvider {
101 fn public_keys(&self) -> PublicKeys;
111}
112
113impl PublicKeysProvider for PublicKeys {
114 fn public_keys(&self) -> PublicKeys { self.clone() }
115}
116
117impl ReferenceProvider for PublicKeys {
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<PublicKeys> for PublicKeys {
126 fn as_ref(&self) -> &PublicKeys { self }
127}
128
129impl AsRef<SigningPublicKey> for PublicKeys {
130 fn as_ref(&self) -> &SigningPublicKey { &self.signing_public_key }
131}
132
133impl AsRef<EncapsulationPublicKey> for PublicKeys {
134 fn as_ref(&self) -> &EncapsulationPublicKey {
135 &self.encapsulation_public_key
136 }
137}
138
139impl CBORTagged for PublicKeys {
140 fn cbor_tags() -> Vec<Tag> { tags_for_values(&[tags::TAG_PUBLIC_KEYS]) }
141}
142
143impl From<PublicKeys> for CBOR {
144 fn from(value: PublicKeys) -> Self { value.tagged_cbor() }
145}
146
147impl CBORTaggedEncodable for PublicKeys {
148 fn untagged_cbor(&self) -> CBOR {
149 let signing_key_cbor: CBOR = self.signing_public_key.clone().into();
150 let encapsulation_key_cbor: CBOR =
151 self.encapsulation_public_key.clone().into();
152 vec![signing_key_cbor, encapsulation_key_cbor].into()
153 }
154}
155
156impl TryFrom<CBOR> for PublicKeys {
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 PublicKeys {
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("PublicKeys must have two elements".into());
170 }
171
172 let signing_public_key =
173 SigningPublicKey::try_from(elements[0].clone())?;
174 let encapsulation_public_key =
175 EncapsulationPublicKey::try_from(elements[1].clone())?;
176 Ok(Self::new(signing_public_key, encapsulation_public_key))
177 }
178 _ => Err("PublicKeys must be an array".into()),
179 }
180 }
181}
182
183impl Verifier for PublicKeys {
184 fn verify(&self, signature: &Signature, message: &dyn AsRef<[u8]>) -> bool {
185 self.signing_public_key.verify(signature, message)
186 }
187}
188
189impl Encrypter for PublicKeys {
190 fn encapsulation_public_key(&self) -> EncapsulationPublicKey {
191 self.encapsulation_public_key.clone()
192 }
193}
194
195impl std::fmt::Display for PublicKeys {
196 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
197 write!(f, "PublicKeys({})", self.reference().ref_hex_short())
198 }
199}
200
201#[cfg(test)]
202mod tests {
203 use bc_ur::{URDecodable, UREncodable};
204 use dcbor::prelude::*;
205 use hex_literal::hex;
206
207 use crate::{
208 PrivateKeyBase, PublicKeys, PublicKeysProvider, ReferenceProvider,
209 };
210
211 const SEED: [u8; 16] = hex!("59f2293a5bce7d4de59e71b4207ac5d2");
212
213 #[test]
214 fn test_private_key_base() {
215 crate::register_tags();
216 let private_key_base = PrivateKeyBase::from_data(SEED);
217 let public_keys = private_key_base.public_keys();
218
219 let cbor = CBOR::from(public_keys.clone());
220
221 let public_keys_2 = PublicKeys::try_from(cbor.clone()).unwrap();
222 assert_eq!(public_keys, public_keys_2);
223
224 let cbor_2 = CBOR::from(public_keys_2);
225 assert_eq!(cbor, cbor_2);
226
227 let ur = public_keys.ur_string();
228 assert_eq!(
229 ur,
230 "ur:crypto-pubkeys/lftanshfhdcxzcgtcpytvsgafsondpjkbkoxaopsnniycawpnbnlwsgtregdfhgynyjksrgafmcstansgrhdcxlnfnwfzstovlrdfeuoghvwwyuesbcltsmetbgeurpfoyswfrzojlwdenjzckvadnrndtgsya"
231 );
232 assert_eq!(PublicKeys::from_ur_string(&ur).unwrap(), public_keys);
233
234 assert_eq!(format!("{}", public_keys), "PublicKeys(c9ede672)");
235 assert_eq!(
236 format!("{}", public_keys.reference()),
237 "Reference(c9ede672)"
238 );
239 }
240}