From 8b720f78c3f78ff4b8d32a33f0a41999e645e1b7 Mon Sep 17 00:00:00 2001 From: samkim-crypto Date: Thu, 14 Nov 2024 20:36:30 +0900 Subject: [PATCH] [zk-sdk] Expose ElGamal decryption and proof program to wasm target (#3601) * expose `zk_elgamal_proof_program` to wasm target * expose ElGamal decryption to wasm target --- zk-sdk/Cargo.toml | 2 +- zk-sdk/src/encryption/discrete_log.rs | 1 + zk-sdk/src/encryption/elgamal.rs | 60 +++++++++++++-------------- zk-sdk/src/encryption/mod.rs | 2 +- zk-sdk/src/lib.rs | 1 - 5 files changed, 31 insertions(+), 35 deletions(-) diff --git a/zk-sdk/Cargo.toml b/zk-sdk/Cargo.toml index c822ab002105c8..797f4a1ab13099 100644 --- a/zk-sdk/Cargo.toml +++ b/zk-sdk/Cargo.toml @@ -17,7 +17,7 @@ merlin = { workspace = true } num-derive = { workspace = true } num-traits = { workspace = true } solana-instruction = { workspace = true, features = ["std"] } -solana-pubkey = { workspace = true } +solana-pubkey = { workspace = true, features = ["bytemuck"] } solana-sdk-ids = { workspace = true } thiserror = { workspace = true } diff --git a/zk-sdk/src/encryption/discrete_log.rs b/zk-sdk/src/encryption/discrete_log.rs index 2e96a952029284..b5cd83f99172d3 100644 --- a/zk-sdk/src/encryption/discrete_log.rs +++ b/zk-sdk/src/encryption/discrete_log.rs @@ -146,6 +146,7 @@ impl DiscreteLog { /// Solves the discrete log problem under the assumption that the solution /// is a positive 32-bit number. pub fn decode_u32(self) -> Option { + #[allow(unused_variables)] if let Some(num_threads) = self.num_threads { #[cfg(not(target_arch = "wasm32"))] { diff --git a/zk-sdk/src/encryption/elgamal.rs b/zk-sdk/src/encryption/elgamal.rs index 25003eff60a351..9509e91f23a787 100644 --- a/zk-sdk/src/encryption/elgamal.rs +++ b/zk-sdk/src/encryption/elgamal.rs @@ -20,24 +20,10 @@ use wasm_bindgen::prelude::*; // types and functions exported for wasm targets in all of its dependencies // (https://github.com/rustwasm/wasm-bindgen/issues/3759). We specifically exclude some of the // dependencies that will cause unnecessary bloat to the wasm binary. -#[cfg(not(target_arch = "wasm32"))] -use { - crate::encryption::discrete_log::DiscreteLog, - sha3::Digest, - solana_derivation_path::DerivationPath, - solana_seed_derivable::SeedDerivable, - solana_seed_phrase::generate_seed_from_seed_phrase_and_passphrase, - solana_signature::Signature, - solana_signer::{EncodableKey, EncodableKeypair, Signer, SignerError}, - std::{ - error, - io::{Read, Write}, - path::Path, - }, -}; use { crate::{ encryption::{ + discrete_log::DiscreteLog, pedersen::{Pedersen, PedersenCommitment, PedersenOpening, G, H}, DECRYPT_HANDLE_LEN, ELGAMAL_CIPHERTEXT_LEN, ELGAMAL_KEYPAIR_LEN, ELGAMAL_PUBKEY_LEN, ELGAMAL_SECRET_KEY_LEN, PEDERSEN_COMMITMENT_LEN, @@ -58,6 +44,20 @@ use { subtle::{Choice, ConstantTimeEq}, zeroize::Zeroize, }; +#[cfg(not(target_arch = "wasm32"))] +use { + sha3::Digest, + solana_derivation_path::DerivationPath, + solana_seed_derivable::SeedDerivable, + solana_seed_phrase::generate_seed_from_seed_phrase_and_passphrase, + solana_signature::Signature, + solana_signer::{EncodableKey, EncodableKeypair, Signer, SignerError}, + std::{ + error, + io::{Read, Write}, + path::Path, + }, +}; /// Algorithm handle for the twisted ElGamal encryption scheme pub struct ElGamal; @@ -123,7 +123,6 @@ impl ElGamal { /// /// The output of this function is of type `DiscreteLog`. To recover, the originally encrypted /// amount, use `DiscreteLog::decode`. - #[cfg(not(target_arch = "wasm32"))] fn decrypt(secret: &ElGamalSecretKey, ciphertext: &ElGamalCiphertext) -> DiscreteLog { DiscreteLog::new( *G, @@ -136,7 +135,6 @@ impl ElGamal { /// /// If the originally encrypted amount is not a positive 32-bit number, then the function /// returns `None`. - #[cfg(not(target_arch = "wasm32"))] fn decrypt_u32(secret: &ElGamalSecretKey, ciphertext: &ElGamalCiphertext) -> Option { let discrete_log_instance = Self::decrypt(secret, ciphertext); discrete_log_instance.decode_u32() @@ -464,6 +462,19 @@ impl ElGamalSecretKey { pub fn as_bytes(&self) -> &[u8; ELGAMAL_SECRET_KEY_LEN] { self.0.as_bytes() } + + /// Decrypts a ciphertext using the ElGamal secret key. + /// + /// The output of this function is of type `DiscreteLog`. To recover, the originally encrypted + /// message, use `DiscreteLog::decode`. + pub fn decrypt(&self, ciphertext: &ElGamalCiphertext) -> DiscreteLog { + ElGamal::decrypt(self, ciphertext) + } + + /// Decrypts a ciphertext using the ElGamal secret key interpretting the message as type `u32`. + pub fn decrypt_u32(&self, ciphertext: &ElGamalCiphertext) -> Option { + ElGamal::decrypt_u32(self, ciphertext) + } } #[cfg(not(target_arch = "wasm32"))] @@ -514,19 +525,6 @@ impl ElGamalSecretKey { result.to_vec() } - - /// Decrypts a ciphertext using the ElGamal secret key. - /// - /// The output of this function is of type `DiscreteLog`. To recover, the originally encrypted - /// message, use `DiscreteLog::decode`. - pub fn decrypt(&self, ciphertext: &ElGamalCiphertext) -> DiscreteLog { - ElGamal::decrypt(self, ciphertext) - } - - /// Decrypts a ciphertext using the ElGamal secret key interpretting the message as type `u32`. - pub fn decrypt_u32(&self, ciphertext: &ElGamalCiphertext) -> Option { - ElGamal::decrypt_u32(self, ciphertext) - } } #[cfg(not(target_arch = "wasm32"))] @@ -663,7 +661,6 @@ impl ElGamalCiphertext { /// /// The output of this function is of type `DiscreteLog`. To recover, the originally encrypted /// amount, use `DiscreteLog::decode`. - #[cfg(not(target_arch = "wasm32"))] pub fn decrypt(&self, secret: &ElGamalSecretKey) -> DiscreteLog { ElGamal::decrypt(secret, self) } @@ -673,7 +670,6 @@ impl ElGamalCiphertext { /// /// If the originally encrypted amount is not a positive 32-bit number, then the function /// returns `None`. - #[cfg(not(target_arch = "wasm32"))] pub fn decrypt_u32(&self, secret: &ElGamalSecretKey) -> Option { ElGamal::decrypt_u32(secret, self) } diff --git a/zk-sdk/src/encryption/mod.rs b/zk-sdk/src/encryption/mod.rs index 28a9ae6bf7fded..8cad6217fc4c68 100644 --- a/zk-sdk/src/encryption/mod.rs +++ b/zk-sdk/src/encryption/mod.rs @@ -17,7 +17,7 @@ use crate::{RISTRETTO_POINT_LEN, SCALAR_LEN}; pub(crate) mod macros; #[cfg(not(target_os = "solana"))] pub mod auth_encryption; -#[cfg(all(not(target_os = "solana"), not(target_arch = "wasm32")))] +#[cfg(not(target_os = "solana"))] pub mod discrete_log; #[cfg(not(target_os = "solana"))] pub mod elgamal; diff --git a/zk-sdk/src/lib.rs b/zk-sdk/src/lib.rs index 8d7388475f2f36..824a4718f14c5c 100644 --- a/zk-sdk/src/lib.rs +++ b/zk-sdk/src/lib.rs @@ -25,7 +25,6 @@ pub mod pod; mod range_proof; mod sigma_proofs; mod transcript; -#[cfg(not(target_arch = "wasm32"))] pub mod zk_elgamal_proof_program; /// Byte length of a compressed Ristretto point or scalar in Curve255519