/ fedimint-core / src / encoding / threshold_crypto.rs
threshold_crypto.rs
  1  use std::io::{Error, Read, Write};
  2  
  3  use threshold_crypto::group::Curve;
  4  use threshold_crypto::{G1Affine, G1Projective};
  5  
  6  use crate::encoding::{Decodable, DecodeError, Encodable};
  7  use crate::module::registry::ModuleDecoderRegistry;
  8  
  9  impl 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  
 24  impl 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| {
 45                  threshold_crypto::PublicKeySet::from(threshold_crypto::poly::Commitment::from(
 46                      coefficients,
 47                  ))
 48              })
 49      }
 50  }
 51  
 52  impl Encodable for threshold_crypto::PublicKey {
 53      fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<usize, Error> {
 54          self.to_bytes().consensus_encode(writer)
 55      }
 56  }
 57  
 58  impl Decodable for threshold_crypto::PublicKey {
 59      fn consensus_decode<R: Read>(
 60          r: &mut R,
 61          modules: &ModuleDecoderRegistry,
 62      ) -> Result<Self, DecodeError> {
 63          let bytes: [u8; 48] = Decodable::consensus_decode(r, modules)?;
 64          threshold_crypto::PublicKey::from_bytes(bytes).map_err(DecodeError::from_err)
 65      }
 66  }
 67  
 68  impl Encodable for threshold_crypto::Ciphertext {
 69      fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<usize, Error> {
 70          self.to_bytes().consensus_encode(writer)
 71      }
 72  }
 73  
 74  impl Decodable for threshold_crypto::Ciphertext {
 75      fn consensus_decode<R: Read>(
 76          reader: &mut R,
 77          modules: &ModuleDecoderRegistry,
 78      ) -> Result<Self, DecodeError> {
 79          let ciphertext_bytes = Vec::<u8>::consensus_decode(reader, modules)?;
 80          threshold_crypto::Ciphertext::from_bytes(&ciphertext_bytes).ok_or_else(|| {
 81              DecodeError::from_str("Error decoding threshold_crypto::Ciphertext from bytes")
 82          })
 83      }
 84  }
 85  
 86  impl Encodable for threshold_crypto::DecryptionShare {
 87      fn consensus_encode<W: Write>(&self, writer: &mut W) -> Result<usize, Error> {
 88          self.to_bytes().consensus_encode(writer)
 89      }
 90  }
 91  
 92  impl Decodable for threshold_crypto::DecryptionShare {
 93      fn consensus_decode<R: Read>(
 94          reader: &mut R,
 95          modules: &ModuleDecoderRegistry,
 96      ) -> Result<Self, DecodeError> {
 97          let decryption_share_bytes = <[u8; 48]>::consensus_decode(reader, modules)?;
 98          threshold_crypto::DecryptionShare::from_bytes(&decryption_share_bytes).ok_or_else(|| {
 99              DecodeError::from_str("Error decoding threshold_crypto::DecryptionShare from bytes")
100          })
101      }
102  }
103  
104  #[cfg(test)]
105  mod tests {
106      use super::super::tests::test_roundtrip;
107  
108      #[test_log::test]
109      fn test_ciphertext() {
110          let sks = threshold_crypto::SecretKeySet::random(1, &mut rand::thread_rng());
111          let pks = sks.public_keys();
112          let pk = pks.public_key();
113  
114          let message = b"Hello world!";
115          let ciphertext = pk.encrypt(message);
116          let decryption_share = sks.secret_key_share(0).decrypt_share(&ciphertext).unwrap();
117  
118          test_roundtrip(ciphertext);
119          test_roundtrip(decryption_share);
120      }
121  }