diff --git a/rust/catalyst-voting/Cargo.toml b/rust/catalyst-voting/Cargo.toml index ce8c106b76..d45d6b5be8 100644 --- a/rust/catalyst-voting/Cargo.toml +++ b/rust/catalyst-voting/Cargo.toml @@ -1,3 +1,5 @@ +# cspell: words getrandom + [package] name = "catalyst-voting" version = "0.0.1" @@ -12,7 +14,7 @@ workspace = true [dependencies] anyhow = "1.0.89" -rand_core = "0.6.4" +rand_core = { version = "0.6.4", features = ["getrandom"] } rand_chacha = "0.3.1" curve25519-dalek = { version = "4.1.3", features = ["digest", "rand_core"] } ed25519-dalek = { version = "2.1.1", features = ["rand_core"] } diff --git a/rust/catalyst-voting/src/crypto/ed25519/decoding.rs b/rust/catalyst-voting/src/crypto/ed25519/decoding.rs index ab4b5daa72..f40bf54163 100644 --- a/rust/catalyst-voting/src/crypto/ed25519/decoding.rs +++ b/rust/catalyst-voting/src/crypto/ed25519/decoding.rs @@ -1,10 +1,31 @@ //! `Ed25519` objects decoding implementation +use anyhow::anyhow; use ed25519_dalek::{ - Signature as Ed25519Signature, VerifyingKey, PUBLIC_KEY_LENGTH, SIGNATURE_LENGTH, + Signature as Ed25519Signature, SigningKey, VerifyingKey, PUBLIC_KEY_LENGTH, SECRET_KEY_LENGTH, + SIGNATURE_LENGTH, }; -use super::{PublicKey, Signature}; +use super::{PrivateKey, PublicKey, Signature}; + +impl PrivateKey { + /// `PrivateKey` bytes size + pub const BYTES_SIZE: usize = SECRET_KEY_LENGTH; + + /// Convert this `PrivateKey` to its underlying sequence of bytes. + #[must_use] + pub fn to_bytes(&self) -> [u8; Self::BYTES_SIZE] { + self.0.to_bytes() + } + + /// Attempt to construct a `PrivateKey` from a byte representation. + /// + /// # Errors + /// - Cannot decode public key. + pub fn from_bytes(bytes: &[u8; Self::BYTES_SIZE]) -> Self { + Self(SigningKey::from_bytes(bytes)) + } +} impl PublicKey { /// `PublicKey` bytes size @@ -21,7 +42,9 @@ impl PublicKey { /// # Errors /// - Cannot decode public key. pub fn from_bytes(bytes: &[u8; Self::BYTES_SIZE]) -> anyhow::Result { - Ok(Self(VerifyingKey::from_bytes(bytes)?)) + Ok(Self( + VerifyingKey::from_bytes(bytes).map_err(|_| anyhow!("Cannot decode public key."))?, + )) } } diff --git a/rust/catalyst-voting/src/crypto/group/ristretto255/decoding.rs b/rust/catalyst-voting/src/crypto/group/ristretto255/decoding.rs index 4076ee9b09..a577d84abe 100644 --- a/rust/catalyst-voting/src/crypto/group/ristretto255/decoding.rs +++ b/rust/catalyst-voting/src/crypto/group/ristretto255/decoding.rs @@ -14,9 +14,8 @@ impl Scalar { /// # Errors /// - Cannot decode scalar. pub fn from_bytes(bytes: [u8; Self::BYTES_SIZE]) -> anyhow::Result { - IScalar::from_canonical_bytes(bytes) + Into::>::into(IScalar::from_canonical_bytes(bytes)) .map(Scalar) - .into_option() .ok_or(anyhow!("Cannot decode scalar.")) } diff --git a/rust/catalyst-voting/src/txs/v1/mod.rs b/rust/catalyst-voting/src/txs/v1/mod.rs index fbc19d6e9e..c9672225dd 100644 --- a/rust/catalyst-voting/src/txs/v1/mod.rs +++ b/rust/catalyst-voting/src/txs/v1/mod.rs @@ -53,7 +53,7 @@ use crate::{ vote_protocol::{ committee::{ElectionPublicKey, ElectionSecretKey}, voter::{ - decrypt_vote, encrypt_vote_with_default_rng, + decrypt_vote, encrypt_vote, proof::{generate_voter_proof, verify_voter_proof, VoterProof, VoterProofCommitment}, EncryptedVote, Vote, }, @@ -272,8 +272,7 @@ impl VotePayload { ) -> anyhow::Result { let vote = Vote::new(choice.into(), proposal_voting_options.into())?; - let (encrypted_vote, randomness) = - encrypt_vote_with_default_rng(&vote, election_public_key); + let (encrypted_vote, randomness) = encrypt_vote(&vote, election_public_key, rng); let vote_plan_id_hash = Blake2b512Hasher::new().chain_update(vote_plan_id); let commitment = VoterProofCommitment::from_hash(vote_plan_id_hash); diff --git a/rust/catalyst-voting/src/vote_protocol/committee/decoding.rs b/rust/catalyst-voting/src/vote_protocol/committee/decoding.rs new file mode 100644 index 0000000000..3d2630c0b3 --- /dev/null +++ b/rust/catalyst-voting/src/vote_protocol/committee/decoding.rs @@ -0,0 +1,66 @@ +//! committee objects decoding implementation + +use anyhow::anyhow; + +use super::{ElectionPublicKey, ElectionSecretKey, GroupElement, Scalar}; + +impl ElectionSecretKey { + /// `ElectionSecretKey` bytes size + pub const BYTES_SIZE: usize = Scalar::BYTES_SIZE; + + /// Convert this `ElectionSecretKey` to its underlying sequence of bytes. + #[must_use] + pub fn to_bytes(&self) -> [u8; Self::BYTES_SIZE] { + self.0.to_bytes() + } + + /// Attempt to construct a `ElectionSecretKey` from a byte representation. + /// + /// # Errors + /// - Cannot decode election secret key. + pub fn from_bytes(bytes: [u8; Self::BYTES_SIZE]) -> anyhow::Result { + Ok(Self(Scalar::from_bytes(bytes).map_err(|_| { + anyhow!("Cannot decode election secret key.") + })?)) + } +} + +impl ElectionPublicKey { + /// `ElectionPublicKey` bytes size + pub const BYTES_SIZE: usize = GroupElement::BYTES_SIZE; + + /// Convert this `ElectionPublicKey` to its underlying sequence of bytes. + #[must_use] + pub fn to_bytes(&self) -> [u8; Self::BYTES_SIZE] { + self.0.to_bytes() + } + + /// Attempt to construct a `ElectionPublicKey` from a byte representation. + /// + /// # Errors + /// - Cannot decode election public key. + pub fn from_bytes(bytes: &[u8; Self::BYTES_SIZE]) -> anyhow::Result { + Ok(Self( + GroupElement::from_bytes(bytes).map_err(|_| anyhow!("Cannot decode public key."))?, + )) + } +} + +#[cfg(test)] +mod tests { + use test_strategy::proptest; + + use super::*; + + #[proptest] + fn election_keys_to_bytes_from_bytes_test(sk1: ElectionSecretKey) { + let bytes = sk1.to_bytes(); + let sk2 = ElectionSecretKey::from_bytes(bytes).unwrap(); + assert_eq!(sk1, sk2); + + let pk1 = sk1.public_key(); + let bytes = pk1.to_bytes(); + let pk2 = ElectionPublicKey::from_bytes(&bytes).unwrap(); + assert_eq!(pk1, pk2); + } +} diff --git a/rust/catalyst-voting/src/vote_protocol/committee.rs b/rust/catalyst-voting/src/vote_protocol/committee/mod.rs similarity index 98% rename from rust/catalyst-voting/src/vote_protocol/committee.rs rename to rust/catalyst-voting/src/vote_protocol/committee/mod.rs index 551dfe594f..0f11ea0bfd 100644 --- a/rust/catalyst-voting/src/vote_protocol/committee.rs +++ b/rust/catalyst-voting/src/vote_protocol/committee/mod.rs @@ -1,5 +1,7 @@ //! Module containing all primitives related to the committee. +mod decoding; + use rand_core::CryptoRngCore; use crate::crypto::{