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