fedimint_core/encoding/
threshold_crypto.rs1use std::io::{Error, Read, Write};
2
3use threshold_crypto::group::Curve;
4use threshold_crypto::{G1Affine, G1Projective};
5
6use crate::encoding::{Decodable, DecodeError, Encodable};
7use crate::module::registry::ModuleDecoderRegistry;
8
9impl Encodable for threshold_crypto::PublicKeySet {
10 fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<usize, Error> {
11 let mut len = 0;
12 let num_coeff = self.coefficients().len() as u64;
13 len += num_coeff.consensus_encode(writer)?;
14 for coefficient in self.coefficients() {
15 len += coefficient
16 .to_affine()
17 .to_compressed()
18 .consensus_encode(writer)?;
19 }
20 Ok(len)
21 }
22}
23
24impl Decodable for threshold_crypto::PublicKeySet {
25 fn consensus_decode<R: Read>(
26 r: &mut R,
27 modules: &ModuleDecoderRegistry,
28 ) -> Result<Self, DecodeError> {
29 let num_coeff = u64::consensus_decode(r, modules)?;
30 (0..num_coeff)
31 .map(|_| {
32 let bytes: [u8; 48] = Decodable::consensus_decode(r, modules)?;
33 let point = G1Affine::from_compressed(&bytes);
34 if point.is_some().unwrap_u8() == 1 {
35 let affine = point.unwrap();
36 Ok(G1Projective::from(affine))
37 } else {
38 Err(crate::encoding::DecodeError::from_str(
39 "Error decoding public key",
40 ))
41 }
42 })
43 .collect::<Result<Vec<_>, _>>()
44 .map(|coefficients| Self::from(threshold_crypto::poly::Commitment::from(coefficients)))
45 }
46}
47
48impl Encodable for threshold_crypto::PublicKey {
49 fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<usize, Error> {
50 self.to_bytes().consensus_encode(writer)
51 }
52}
53
54impl Decodable for threshold_crypto::PublicKey {
55 fn consensus_decode<R: Read>(
56 r: &mut R,
57 modules: &ModuleDecoderRegistry,
58 ) -> Result<Self, DecodeError> {
59 let bytes: [u8; 48] = Decodable::consensus_decode(r, modules)?;
60 Self::from_bytes(bytes).map_err(DecodeError::from_err)
61 }
62}
63
64impl Encodable for threshold_crypto::Ciphertext {
65 fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<usize, Error> {
66 self.to_bytes().consensus_encode(writer)
67 }
68}
69
70impl Decodable for threshold_crypto::Ciphertext {
71 fn consensus_decode<R: Read>(
72 reader: &mut R,
73 modules: &ModuleDecoderRegistry,
74 ) -> Result<Self, DecodeError> {
75 let ciphertext_bytes = Vec::<u8>::consensus_decode(reader, modules)?;
76 Self::from_bytes(&ciphertext_bytes).ok_or_else(|| {
77 DecodeError::from_str("Error decoding threshold_crypto::Ciphertext from bytes")
78 })
79 }
80}
81
82impl Encodable for threshold_crypto::DecryptionShare {
83 fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<usize, Error> {
84 self.to_bytes().consensus_encode(writer)
85 }
86}
87
88impl Decodable for threshold_crypto::DecryptionShare {
89 fn consensus_decode<R: Read>(
90 reader: &mut R,
91 modules: &ModuleDecoderRegistry,
92 ) -> Result<Self, DecodeError> {
93 let decryption_share_bytes = <[u8; 48]>::consensus_decode(reader, modules)?;
94 Self::from_bytes(&decryption_share_bytes).ok_or_else(|| {
95 DecodeError::from_str("Error decoding threshold_crypto::DecryptionShare from bytes")
96 })
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use super::super::tests::test_roundtrip;
103
104 #[test_log::test]
105 fn test_ciphertext() {
106 let sks = threshold_crypto::SecretKeySet::random(1, &mut rand::thread_rng());
107 let pks = sks.public_keys();
108 let pk = pks.public_key();
109
110 let message = b"Hello world!";
111 let ciphertext = pk.encrypt(message);
112 let decryption_share = sks.secret_key_share(0).decrypt_share(&ciphertext).unwrap();
113
114 test_roundtrip(&ciphertext);
115 test_roundtrip(&decryption_share);
116 }
117}