Rename ElGamalCT to ElGamalCiphertext, ElGamalPK to ElGamalPubkey

This commit is contained in:
Michael Vines 2021-09-30 11:11:53 -07:00
parent f3e7e62813
commit 78799640ea
10 changed files with 219 additions and 171 deletions

View File

@ -22,7 +22,7 @@ pub struct ElGamal;
impl ElGamal {
/// Generates the public and secret keys for ElGamal encryption.
#[cfg(not(target_arch = "bpf"))]
pub fn keygen() -> (ElGamalPK, ElGamalSK) {
pub fn keygen() -> (ElGamalPubkey, ElGamalSK) {
ElGamal::keygen_with(&mut OsRng) // using OsRng for now
}
@ -30,7 +30,7 @@ impl ElGamal {
/// secret keys for ElGamal encryption.
#[cfg(not(target_arch = "bpf"))]
#[allow(non_snake_case)]
pub fn keygen_with<T: RngCore + CryptoRng>(rng: &mut T) -> (ElGamalPK, ElGamalSK) {
pub fn keygen_with<T: RngCore + CryptoRng>(rng: &mut T) -> (ElGamalPubkey, ElGamalSK) {
// sample a non-zero scalar
let mut s: Scalar;
loop {
@ -44,17 +44,17 @@ impl ElGamal {
let H = PedersenBase::default().H;
let P = s.invert() * H;
(ElGamalPK(P), ElGamalSK(s))
(ElGamalPubkey(P), ElGamalSK(s))
}
/// On input a public key and a message to be encrypted, the function
/// returns an ElGamal ciphertext of the message under the public key.
#[cfg(not(target_arch = "bpf"))]
pub fn encrypt<T: Into<Scalar>>(pk: &ElGamalPK, amount: T) -> ElGamalCT {
pub fn encrypt<T: Into<Scalar>>(pk: &ElGamalPubkey, amount: T) -> ElGamalCiphertext {
let (message_comm, open) = Pedersen::commit(amount);
let decrypt_handle = pk.gen_decrypt_handle(&open);
ElGamalCT {
ElGamalCiphertext {
message_comm,
decrypt_handle,
}
@ -64,14 +64,14 @@ impl ElGamal {
/// returns an ElGamal ciphertext of the message under the public key using
/// the opening.
pub fn encrypt_with<T: Into<Scalar>>(
pk: &ElGamalPK,
pk: &ElGamalPubkey,
amount: T,
open: &PedersenOpen,
) -> ElGamalCT {
) -> ElGamalCiphertext {
let message_comm = Pedersen::commit_with(amount, open);
let decrypt_handle = pk.gen_decrypt_handle(open);
ElGamalCT {
ElGamalCiphertext {
message_comm,
decrypt_handle,
}
@ -81,9 +81,9 @@ impl ElGamal {
///
/// The output of the function is of type `DiscreteLogInstance`. The exact message
/// can be recovered via the DiscreteLogInstance's decode method.
pub fn decrypt(sk: &ElGamalSK, ct: &ElGamalCT) -> DiscreteLogInstance {
pub fn decrypt(sk: &ElGamalSK, ct: &ElGamalCiphertext) -> DiscreteLogInstance {
let ElGamalSK(s) = sk;
let ElGamalCT {
let ElGamalCiphertext {
message_comm,
decrypt_handle,
} = ct;
@ -96,7 +96,7 @@ impl ElGamal {
/// On input a secret key and a ciphertext, the function decrypts the
/// ciphertext for a u32 value.
pub fn decrypt_u32(sk: &ElGamalSK, ct: &ElGamalCT) -> Option<u32> {
pub fn decrypt_u32(sk: &ElGamalSK, ct: &ElGamalCiphertext) -> Option<u32> {
let discrete_log_instance = ElGamal::decrypt(sk, ct);
discrete_log_instance.decode_u32()
}
@ -104,8 +104,8 @@ impl ElGamal {
/// Public key for the ElGamal encryption scheme.
#[derive(Serialize, Deserialize, Default, Clone, Copy, Debug, Eq, PartialEq)]
pub struct ElGamalPK(RistrettoPoint);
impl ElGamalPK {
pub struct ElGamalPubkey(RistrettoPoint);
impl ElGamalPubkey {
pub fn get_point(&self) -> RistrettoPoint {
self.0
}
@ -115,20 +115,20 @@ impl ElGamalPK {
self.0.compress().to_bytes()
}
pub fn from_bytes(bytes: &[u8]) -> Option<ElGamalPK> {
Some(ElGamalPK(
pub fn from_bytes(bytes: &[u8]) -> Option<ElGamalPubkey> {
Some(ElGamalPubkey(
CompressedRistretto::from_slice(bytes).decompress()?,
))
}
/// Utility method for code ergonomics.
#[cfg(not(target_arch = "bpf"))]
pub fn encrypt<T: Into<Scalar>>(&self, msg: T) -> ElGamalCT {
pub fn encrypt<T: Into<Scalar>>(&self, msg: T) -> ElGamalCiphertext {
ElGamal::encrypt(self, msg)
}
/// Utility method for code ergonomics.
pub fn encrypt_with<T: Into<Scalar>>(&self, msg: T, open: &PedersenOpen) -> ElGamalCT {
pub fn encrypt_with<T: Into<Scalar>>(&self, msg: T, open: &PedersenOpen) -> ElGamalCiphertext {
ElGamal::encrypt_with(self, msg, open)
}
@ -139,9 +139,9 @@ impl ElGamalPK {
}
}
impl From<RistrettoPoint> for ElGamalPK {
fn from(point: RistrettoPoint) -> ElGamalPK {
ElGamalPK(point)
impl From<RistrettoPoint> for ElGamalPubkey {
fn from(point: RistrettoPoint) -> ElGamalPubkey {
ElGamalPubkey(point)
}
}
@ -155,12 +155,12 @@ impl ElGamalSK {
}
/// Utility method for code ergonomics.
pub fn decrypt(&self, ct: &ElGamalCT) -> DiscreteLogInstance {
pub fn decrypt(&self, ct: &ElGamalCiphertext) -> DiscreteLogInstance {
ElGamal::decrypt(self, ct)
}
/// Utility method for code ergonomics.
pub fn decrypt_u32(&self, ct: &ElGamalCT) -> Option<u32> {
pub fn decrypt_u32(&self, ct: &ElGamalCiphertext) -> Option<u32> {
ElGamal::decrypt_u32(self, ct)
}
@ -197,14 +197,14 @@ impl ConstantTimeEq for ElGamalSK {
/// Ciphertext for the ElGamal encryption scheme.
#[allow(non_snake_case)]
#[derive(Serialize, Deserialize, Default, Clone, Copy, Debug, Eq, PartialEq)]
pub struct ElGamalCT {
pub struct ElGamalCiphertext {
pub message_comm: PedersenComm,
pub decrypt_handle: PedersenDecHandle,
}
impl ElGamalCT {
impl ElGamalCiphertext {
pub fn add_to_msg<T: Into<Scalar>>(&self, message: T) -> Self {
let diff_comm = Pedersen::commit_with(message, &PedersenOpen::default());
ElGamalCT {
ElGamalCiphertext {
message_comm: self.message_comm + diff_comm,
decrypt_handle: self.decrypt_handle,
}
@ -212,7 +212,7 @@ impl ElGamalCT {
pub fn sub_to_msg<T: Into<Scalar>>(&self, message: T) -> Self {
let diff_comm = Pedersen::commit_with(message, &PedersenOpen::default());
ElGamalCT {
ElGamalCiphertext {
message_comm: self.message_comm - diff_comm,
decrypt_handle: self.decrypt_handle,
}
@ -227,14 +227,14 @@ impl ElGamalCT {
bytes
}
pub fn from_bytes(bytes: &[u8]) -> Option<ElGamalCT> {
pub fn from_bytes(bytes: &[u8]) -> Option<ElGamalCiphertext> {
let bytes = array_ref![bytes, 0, 64];
let (message_comm, decrypt_handle) = array_refs![bytes, 32, 32];
let message_comm = CompressedRistretto::from_slice(message_comm).decompress()?;
let decrypt_handle = CompressedRistretto::from_slice(decrypt_handle).decompress()?;
Some(ElGamalCT {
Some(ElGamalCiphertext {
message_comm: PedersenComm(message_comm),
decrypt_handle: PedersenDecHandle(decrypt_handle),
})
@ -251,57 +251,73 @@ impl ElGamalCT {
}
}
impl<'a, 'b> Add<&'b ElGamalCT> for &'a ElGamalCT {
type Output = ElGamalCT;
impl<'a, 'b> Add<&'b ElGamalCiphertext> for &'a ElGamalCiphertext {
type Output = ElGamalCiphertext;
fn add(self, other: &'b ElGamalCT) -> ElGamalCT {
ElGamalCT {
fn add(self, other: &'b ElGamalCiphertext) -> ElGamalCiphertext {
ElGamalCiphertext {
message_comm: self.message_comm + other.message_comm,
decrypt_handle: self.decrypt_handle + other.decrypt_handle,
}
}
}
define_add_variants!(LHS = ElGamalCT, RHS = ElGamalCT, Output = ElGamalCT);
define_add_variants!(
LHS = ElGamalCiphertext,
RHS = ElGamalCiphertext,
Output = ElGamalCiphertext
);
impl<'a, 'b> Sub<&'b ElGamalCT> for &'a ElGamalCT {
type Output = ElGamalCT;
impl<'a, 'b> Sub<&'b ElGamalCiphertext> for &'a ElGamalCiphertext {
type Output = ElGamalCiphertext;
fn sub(self, other: &'b ElGamalCT) -> ElGamalCT {
ElGamalCT {
fn sub(self, other: &'b ElGamalCiphertext) -> ElGamalCiphertext {
ElGamalCiphertext {
message_comm: self.message_comm - other.message_comm,
decrypt_handle: self.decrypt_handle - other.decrypt_handle,
}
}
}
define_sub_variants!(LHS = ElGamalCT, RHS = ElGamalCT, Output = ElGamalCT);
define_sub_variants!(
LHS = ElGamalCiphertext,
RHS = ElGamalCiphertext,
Output = ElGamalCiphertext
);
impl<'a, 'b> Mul<&'b Scalar> for &'a ElGamalCT {
type Output = ElGamalCT;
impl<'a, 'b> Mul<&'b Scalar> for &'a ElGamalCiphertext {
type Output = ElGamalCiphertext;
fn mul(self, other: &'b Scalar) -> ElGamalCT {
ElGamalCT {
fn mul(self, other: &'b Scalar) -> ElGamalCiphertext {
ElGamalCiphertext {
message_comm: self.message_comm * other,
decrypt_handle: self.decrypt_handle * other,
}
}
}
define_mul_variants!(LHS = ElGamalCT, RHS = Scalar, Output = ElGamalCT);
define_mul_variants!(
LHS = ElGamalCiphertext,
RHS = Scalar,
Output = ElGamalCiphertext
);
impl<'a, 'b> Div<&'b Scalar> for &'a ElGamalCT {
type Output = ElGamalCT;
impl<'a, 'b> Div<&'b Scalar> for &'a ElGamalCiphertext {
type Output = ElGamalCiphertext;
fn div(self, other: &'b Scalar) -> ElGamalCT {
ElGamalCT {
fn div(self, other: &'b Scalar) -> ElGamalCiphertext {
ElGamalCiphertext {
message_comm: self.message_comm * other.invert(),
decrypt_handle: self.decrypt_handle * other.invert(),
}
}
}
define_div_variants!(LHS = ElGamalCT, RHS = Scalar, Output = ElGamalCT);
define_div_variants!(
LHS = ElGamalCiphertext,
RHS = Scalar,
Output = ElGamalCiphertext
);
#[cfg(test)]
mod tests {
@ -441,7 +457,7 @@ mod tests {
let ct = pk.encrypt(msg);
let encoded = bincode::serialize(&ct).unwrap();
let decoded: ElGamalCT = bincode::deserialize(&encoded).unwrap();
let decoded: ElGamalCiphertext = bincode::deserialize(&encoded).unwrap();
assert_eq!(ct, decoded);
}
@ -451,7 +467,7 @@ mod tests {
let (pk, _) = ElGamal::keygen();
let encoded = bincode::serialize(&pk).unwrap();
let decoded: ElGamalPK = bincode::deserialize(&encoded).unwrap();
let decoded: ElGamalPubkey = bincode::deserialize(&encoded).unwrap();
assert_eq!(pk, decoded);
}

View File

@ -2,7 +2,7 @@
use rand::{rngs::OsRng, CryptoRng, RngCore};
use {
crate::{
encryption::elgamal::{ElGamalCT, ElGamalPK},
encryption::elgamal::{ElGamalCiphertext, ElGamalPubkey},
errors::ProofError,
},
core::ops::{Add, Div, Mul, Sub},
@ -271,13 +271,13 @@ impl PedersenDecHandle {
self.0
}
pub fn generate_handle(open: &PedersenOpen, pk: &ElGamalPK) -> PedersenDecHandle {
pub fn generate_handle(open: &PedersenOpen, pk: &ElGamalPubkey) -> PedersenDecHandle {
PedersenDecHandle(open.get_scalar() * pk.get_point())
}
/// Maps a decryption token and Pedersen commitment to ElGamal ciphertext
pub fn to_elgamal_ctxt(self, comm: PedersenComm) -> ElGamalCT {
ElGamalCT {
pub fn to_elgamal_ctxt(self, comm: PedersenComm) -> ElGamalCiphertext {
ElGamalCiphertext {
message_comm: comm,
decrypt_handle: self,
}

View File

@ -14,6 +14,6 @@ pub enum ProofError {
InvalidBitsize,
/// This error occurs when there are insufficient generators for the proof.
InvalidGeneratorsLength,
/// This error occurs a `zk_token_elgamal::pod::ElGamalCT` contains invalid ElGamalCT ciphertext
/// This error occurs a `zk_token_elgamal::pod::ElGamalCiphertext` contains invalid ElGamalCiphertext ciphertext
InconsistentCTData,
}

View File

@ -5,7 +5,7 @@ use {
#[cfg(not(target_arch = "bpf"))]
use {
crate::{
encryption::elgamal::{ElGamalCT, ElGamalSK},
encryption::elgamal::{ElGamalCiphertext, ElGamalSK},
errors::ProofError,
instruction::Verifiable,
transcript::TranscriptProtocol,
@ -31,7 +31,7 @@ use {
#[repr(C)]
pub struct CloseAccountData {
/// The source account available balance in encrypted form
pub balance: pod::ElGamalCT, // 64 bytes
pub balance: pod::ElGamalCiphertext, // 64 bytes
/// Proof that the source account available balance is zero
pub proof: CloseAccountProof, // 64 bytes
@ -39,7 +39,7 @@ pub struct CloseAccountData {
#[cfg(not(target_arch = "bpf"))]
impl CloseAccountData {
pub fn new(source_sk: &ElGamalSK, balance: ElGamalCT) -> Self {
pub fn new(source_sk: &ElGamalSK, balance: ElGamalCiphertext) -> Self {
let proof = CloseAccountProof::new(source_sk, &balance);
CloseAccountData {
@ -74,7 +74,7 @@ impl CloseAccountProof {
Transcript::new(b"CloseAccountProof")
}
pub fn new(source_sk: &ElGamalSK, balance: &ElGamalCT) -> Self {
pub fn new(source_sk: &ElGamalSK, balance: &ElGamalCiphertext) -> Self {
let mut transcript = Self::transcript_new();
// add a domain separator to record the start of the protocol
@ -101,7 +101,7 @@ impl CloseAccountProof {
}
}
pub fn verify(&self, balance: &ElGamalCT) -> Result<(), ProofError> {
pub fn verify(&self, balance: &ElGamalCiphertext) -> Result<(), ProofError> {
let mut transcript = Self::transcript_new();
// add a domain separator to record the start of the protocol
@ -156,7 +156,7 @@ mod test {
assert!(proof.verify(&balance).is_err());
// A zeroed cyphertext should be considered as an account balance of 0
let zeroed_ct: ElGamalCT = pod::ElGamalCT::zeroed().try_into().unwrap();
let zeroed_ct: ElGamalCiphertext = pod::ElGamalCiphertext::zeroed().try_into().unwrap();
let proof = CloseAccountProof::new(&source_sk, &zeroed_ct);
assert!(proof.verify(&zeroed_ct).is_ok());
}

View File

@ -6,7 +6,7 @@ use {
use {
crate::{
encryption::{
elgamal::{ElGamalCT, ElGamalPK, ElGamalSK},
elgamal::{ElGamalCiphertext, ElGamalPubkey, ElGamalSK},
pedersen::{Pedersen, PedersenBase, PedersenComm, PedersenDecHandle, PedersenOpen},
},
errors::ProofError,
@ -36,11 +36,11 @@ impl TransferData {
pub fn new(
transfer_amount: u64,
spendable_balance: u64,
spendable_ct: ElGamalCT,
source_pk: ElGamalPK,
spendable_ct: ElGamalCiphertext,
source_pk: ElGamalPubkey,
source_sk: &ElGamalSK,
dest_pk: ElGamalPK,
auditor_pk: ElGamalPK,
dest_pk: ElGamalPubkey,
auditor_pk: ElGamalPubkey,
) -> Self {
// split and encrypt transfer amount
//
@ -94,7 +94,7 @@ impl TransferData {
let new_spendable_handle =
spendable_handle - combine_u32_handles(handle_source_lo, handle_source_hi);
let new_spendable_ct = ElGamalCT {
let new_spendable_ct = ElGamalCiphertext {
message_comm: new_spendable_comm,
decrypt_handle: new_spendable_handle,
};
@ -185,7 +185,7 @@ pub struct TransferValidityProofData {
pub transfer_public_keys: TransferPubKeys, // 96 bytes
/// The final spendable ciphertext after the transfer
pub new_spendable_ct: pod::ElGamalCT, // 64 bytes
pub new_spendable_ct: pod::ElGamalCiphertext, // 64 bytes
/// Proof that certifies that the decryption handles are generated correctly
pub proof: ValidityProof, // 160 bytes
@ -235,14 +235,14 @@ impl TransferProofs {
#[allow(clippy::many_single_char_names)]
pub fn new(
source_sk: &ElGamalSK,
source_pk: &ElGamalPK,
dest_pk: &ElGamalPK,
auditor_pk: &ElGamalPK,
source_pk: &ElGamalPubkey,
dest_pk: &ElGamalPubkey,
auditor_pk: &ElGamalPubkey,
transfer_amt: (u64, u64),
lo_open: &PedersenOpen,
hi_open: &PedersenOpen,
new_spendable_balance: u64,
new_spendable_ct: &ElGamalCT,
new_spendable_ct: &ElGamalCiphertext,
) -> (Self, TransferEphemeralState) {
// TODO: should also commit to pubkeys and commitments later
let mut transcript_validity_proof = merlin::Transcript::new(b"TransferValidityProof");
@ -347,7 +347,7 @@ pub struct ValidityProof {
impl ValidityProof {
pub fn verify(
self,
new_spendable_ct: &ElGamalCT,
new_spendable_ct: &ElGamalCiphertext,
decryption_handles_lo: &TransferHandles,
decryption_handles_hi: &TransferHandles,
transfer_public_keys: &TransferPubKeys,
@ -355,9 +355,9 @@ impl ValidityProof {
) -> Result<(), ProofError> {
let mut transcript = Transcript::new(b"TransferValidityProof");
let source_pk: ElGamalPK = transfer_public_keys.source_pk.try_into()?;
let dest_pk: ElGamalPK = transfer_public_keys.dest_pk.try_into()?;
let auditor_pk: ElGamalPK = transfer_public_keys.auditor_pk.try_into()?;
let source_pk: ElGamalPubkey = transfer_public_keys.source_pk.try_into()?;
let dest_pk: ElGamalPubkey = transfer_public_keys.dest_pk.try_into()?;
let auditor_pk: ElGamalPubkey = transfer_public_keys.auditor_pk.try_into()?;
// verify Pedersen commitment in the ephemeral state
let C_ephemeral: CompressedRistretto = ephemeral_state.spendable_comm_verification.into();
@ -455,9 +455,9 @@ impl ValidityProof {
#[derive(Clone, Copy, Pod, Zeroable)]
#[repr(C)]
pub struct TransferPubKeys {
pub source_pk: pod::ElGamalPK, // 32 bytes
pub dest_pk: pod::ElGamalPK, // 32 bytes
pub auditor_pk: pod::ElGamalPK, // 32 bytes
pub source_pk: pod::ElGamalPubkey, // 32 bytes
pub dest_pk: pod::ElGamalPubkey, // 32 bytes
pub auditor_pk: pod::ElGamalPubkey, // 32 bytes
}
/// The transfer amount commitments needed for a transfer
@ -504,7 +504,7 @@ pub fn combine_u32_handles(
}
/*
pub fn combine_u32_ciphertexts(ct_lo: ElGamalCT, ct_hi: ElGamalCT) -> ElGamalCT {
pub fn combine_u32_ciphertexts(ct_lo: ElGamalCiphertext, ct_hi: ElGamalCiphertext) -> ElGamalCiphertext {
ct_lo + ct_hi * Scalar::from(TWO_32)
}
*/

View File

@ -6,7 +6,7 @@ use {
use {
crate::{
encryption::{
elgamal::{ElGamalCT, ElGamalPK, ElGamalSK},
elgamal::{ElGamalCiphertext, ElGamalPubkey, ElGamalSK},
pedersen::PedersenBase,
},
errors::ProofError,
@ -34,16 +34,16 @@ use {
#[repr(C)]
pub struct UpdateAccountPkData {
/// Current ElGamal encryption key
pub current_pk: pod::ElGamalPK, // 32 bytes
pub current_pk: pod::ElGamalPubkey, // 32 bytes
/// Current encrypted available balance
pub current_ct: pod::ElGamalCT, // 64 bytes
pub current_ct: pod::ElGamalCiphertext, // 64 bytes
/// New ElGamal encryption key
pub new_pk: pod::ElGamalPK, // 32 bytes
pub new_pk: pod::ElGamalPubkey, // 32 bytes
/// New encrypted available balance
pub new_ct: pod::ElGamalCT, // 64 bytes
pub new_ct: pod::ElGamalCiphertext, // 64 bytes
/// Proof that the current and new ciphertexts are consistent
pub proof: UpdateAccountPkProof, // 160 bytes
@ -53,10 +53,10 @@ impl UpdateAccountPkData {
#[cfg(not(target_arch = "bpf"))]
pub fn new(
current_balance: u64,
current_ct: ElGamalCT,
current_pk: ElGamalPK,
current_ct: ElGamalCiphertext,
current_pk: ElGamalPubkey,
current_sk: &ElGamalSK,
new_pk: ElGamalPK,
new_pk: ElGamalPubkey,
new_sk: &ElGamalSK,
) -> Self {
let new_ct = new_pk.encrypt(current_balance);
@ -107,8 +107,8 @@ impl UpdateAccountPkProof {
current_balance: u64,
current_sk: &ElGamalSK,
new_sk: &ElGamalSK,
current_ct: &ElGamalCT,
new_ct: &ElGamalCT,
current_ct: &ElGamalCiphertext,
new_ct: &ElGamalCiphertext,
) -> Self {
let mut transcript = Self::transcript_new();
@ -153,7 +153,11 @@ impl UpdateAccountPkProof {
}
}
fn verify(&self, current_ct: &ElGamalCT, new_ct: &ElGamalCT) -> Result<(), ProofError> {
fn verify(
&self,
current_ct: &ElGamalCiphertext,
new_ct: &ElGamalCiphertext,
) -> Result<(), ProofError> {
let mut transcript = Self::transcript_new();
// add a domain separator to record the start of the protocol
@ -233,8 +237,9 @@ mod test {
// A zeroed cipehrtext should be considered as an account balance of 0
let balance: u64 = 0;
let zeroed_ct_as_current_ct: ElGamalCT = pod::ElGamalCT::zeroed().try_into().unwrap();
let new_ct: ElGamalCT = new_pk.encrypt(balance);
let zeroed_ct_as_current_ct: ElGamalCiphertext =
pod::ElGamalCiphertext::zeroed().try_into().unwrap();
let new_ct: ElGamalCiphertext = new_pk.encrypt(balance);
let proof = UpdateAccountPkProof::new(
balance,
&current_sk,
@ -244,8 +249,9 @@ mod test {
);
assert!(proof.verify(&zeroed_ct_as_current_ct, &new_ct).is_ok());
let current_ct: ElGamalCT = pod::ElGamalCT::zeroed().try_into().unwrap();
let zeroed_ct_as_new_ct: ElGamalCT = pod::ElGamalCT::zeroed().try_into().unwrap();
let current_ct: ElGamalCiphertext = pod::ElGamalCiphertext::zeroed().try_into().unwrap();
let zeroed_ct_as_new_ct: ElGamalCiphertext =
pod::ElGamalCiphertext::zeroed().try_into().unwrap();
let proof = UpdateAccountPkProof::new(
balance,
&current_sk,
@ -255,8 +261,10 @@ mod test {
);
assert!(proof.verify(&current_ct, &zeroed_ct_as_new_ct).is_ok());
let zeroed_ct_as_current_ct: ElGamalCT = pod::ElGamalCT::zeroed().try_into().unwrap();
let zeroed_ct_as_new_ct: ElGamalCT = pod::ElGamalCT::zeroed().try_into().unwrap();
let zeroed_ct_as_current_ct: ElGamalCiphertext =
pod::ElGamalCiphertext::zeroed().try_into().unwrap();
let zeroed_ct_as_new_ct: ElGamalCiphertext =
pod::ElGamalCiphertext::zeroed().try_into().unwrap();
let proof = UpdateAccountPkProof::new(
balance,
&current_sk,

View File

@ -6,7 +6,7 @@ use {
use {
crate::{
encryption::{
elgamal::{ElGamalCT, ElGamalPK, ElGamalSK},
elgamal::{ElGamalCiphertext, ElGamalPubkey, ElGamalSK},
pedersen::{PedersenBase, PedersenOpen},
},
errors::ProofError,
@ -32,7 +32,7 @@ use {
pub struct WithdrawData {
/// The source account available balance *after* the withdraw (encrypted by
/// `source_pk`
pub final_balance_ct: pod::ElGamalCT, // 64 bytes
pub final_balance_ct: pod::ElGamalCiphertext, // 64 bytes
/// Proof that the account is solvent
pub proof: WithdrawProof, // 736 bytes
@ -42,10 +42,10 @@ impl WithdrawData {
#[cfg(not(target_arch = "bpf"))]
pub fn new(
amount: u64,
source_pk: ElGamalPK,
source_pk: ElGamalPubkey,
source_sk: &ElGamalSK,
current_balance: u64,
current_balance_ct: ElGamalCT,
current_balance_ct: ElGamalCiphertext,
) -> Self {
// subtract withdraw amount from current balance
//
@ -95,7 +95,11 @@ impl WithdrawProof {
Transcript::new(b"WithdrawProof")
}
pub fn new(source_sk: &ElGamalSK, final_balance: u64, final_balance_ct: &ElGamalCT) -> Self {
pub fn new(
source_sk: &ElGamalSK,
final_balance: u64,
final_balance_ct: &ElGamalCiphertext,
) -> Self {
let mut transcript = Self::transcript_new();
// add a domain separator to record the start of the protocol
@ -138,7 +142,7 @@ impl WithdrawProof {
}
}
pub fn verify(&self, final_balance_ct: &ElGamalCT) -> Result<(), ProofError> {
pub fn verify(&self, final_balance_ct: &ElGamalCiphertext) -> Result<(), ProofError> {
let mut transcript = Self::transcript_new();
// Add a domain separator to record the start of the protocol

View File

@ -1,12 +1,12 @@
use super::pod;
pub use target_arch::*;
impl From<(pod::PedersenComm, pod::PedersenDecHandle)> for pod::ElGamalCT {
impl From<(pod::PedersenComm, pod::PedersenDecHandle)> for pod::ElGamalCiphertext {
fn from((comm, decrypt_handle): (pod::PedersenComm, pod::PedersenDecHandle)) -> Self {
let mut buf = [0_u8; 64];
buf[..32].copy_from_slice(&comm.0);
buf[32..].copy_from_slice(&decrypt_handle.0);
pod::ElGamalCT(buf)
pod::ElGamalCiphertext(buf)
}
}
@ -15,7 +15,7 @@ mod target_arch {
use {
super::pod,
crate::{
encryption::elgamal::{ElGamalCT, ElGamalPK},
encryption::elgamal::{ElGamalCiphertext, ElGamalPubkey},
encryption::pedersen::{PedersenComm, PedersenDecHandle},
errors::ProofError,
range_proof::RangeProof,
@ -36,41 +36,41 @@ mod target_arch {
}
}
impl From<ElGamalCT> for pod::ElGamalCT {
fn from(ct: ElGamalCT) -> Self {
impl From<ElGamalCiphertext> for pod::ElGamalCiphertext {
fn from(ct: ElGamalCiphertext) -> Self {
Self(ct.to_bytes())
}
}
impl TryFrom<pod::ElGamalCT> for ElGamalCT {
impl TryFrom<pod::ElGamalCiphertext> for ElGamalCiphertext {
type Error = ProofError;
fn try_from(ct: pod::ElGamalCT) -> Result<Self, Self::Error> {
fn try_from(ct: pod::ElGamalCiphertext) -> Result<Self, Self::Error> {
Self::from_bytes(&ct.0).ok_or(ProofError::InconsistentCTData)
}
}
impl fmt::Debug for pod::ElGamalCT {
impl fmt::Debug for pod::ElGamalCiphertext {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.0)
}
}
impl From<ElGamalPK> for pod::ElGamalPK {
fn from(pk: ElGamalPK) -> Self {
impl From<ElGamalPubkey> for pod::ElGamalPubkey {
fn from(pk: ElGamalPubkey) -> Self {
Self(pk.to_bytes())
}
}
impl TryFrom<pod::ElGamalPK> for ElGamalPK {
impl TryFrom<pod::ElGamalPubkey> for ElGamalPubkey {
type Error = ProofError;
fn try_from(pk: pod::ElGamalPK) -> Result<Self, Self::Error> {
fn try_from(pk: pod::ElGamalPubkey) -> Result<Self, Self::Error> {
Self::from_bytes(&pk.0).ok_or(ProofError::InconsistentCTData)
}
}
impl fmt::Debug for pod::ElGamalPK {
impl fmt::Debug for pod::ElGamalPubkey {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", self.0)
}

View File

@ -3,7 +3,7 @@ pub use target_arch::*;
#[cfg(not(target_arch = "bpf"))]
mod target_arch {
use {
crate::{encryption::elgamal::ElGamalCT, zk_token_elgamal::pod},
crate::{encryption::elgamal::ElGamalCiphertext, zk_token_elgamal::pod},
curve25519_dalek::{constants::RISTRETTO_BASEPOINT_COMPRESSED, scalar::Scalar},
std::convert::TryInto,
};
@ -13,69 +13,78 @@ mod target_arch {
// returns `Some(x0*ct0 + x1*ct1)` or `None` if the input was invalid
fn add_ciphertexts(
scalar_0: Scalar,
ct_0: pod::ElGamalCT,
ct_0: pod::ElGamalCiphertext,
scalar_1: Scalar,
ct_1: pod::ElGamalCT,
) -> Option<pod::ElGamalCT> {
let ct_0: ElGamalCT = ct_0.try_into().ok()?;
let ct_1: ElGamalCT = ct_1.try_into().ok()?;
ct_1: pod::ElGamalCiphertext,
) -> Option<pod::ElGamalCiphertext> {
let ct_0: ElGamalCiphertext = ct_0.try_into().ok()?;
let ct_1: ElGamalCiphertext = ct_1.try_into().ok()?;
let ct_sum = ct_0 * scalar_0 + ct_1 * scalar_1;
Some(pod::ElGamalCT::from(ct_sum))
Some(pod::ElGamalCiphertext::from(ct_sum))
}
pub(crate) fn combine_lo_hi(
ct_lo: pod::ElGamalCT,
ct_hi: pod::ElGamalCT,
) -> Option<pod::ElGamalCT> {
ct_lo: pod::ElGamalCiphertext,
ct_hi: pod::ElGamalCiphertext,
) -> Option<pod::ElGamalCiphertext> {
add_ciphertexts(Scalar::one(), ct_lo, Scalar::from(TWO_32), ct_hi)
}
pub fn add(ct_0: pod::ElGamalCT, ct_1: pod::ElGamalCT) -> Option<pod::ElGamalCT> {
pub fn add(
ct_0: pod::ElGamalCiphertext,
ct_1: pod::ElGamalCiphertext,
) -> Option<pod::ElGamalCiphertext> {
add_ciphertexts(Scalar::one(), ct_0, Scalar::one(), ct_1)
}
pub fn add_with_lo_hi(
ct_0: pod::ElGamalCT,
ct_1_lo: pod::ElGamalCT,
ct_1_hi: pod::ElGamalCT,
) -> Option<pod::ElGamalCT> {
ct_0: pod::ElGamalCiphertext,
ct_1_lo: pod::ElGamalCiphertext,
ct_1_hi: pod::ElGamalCiphertext,
) -> Option<pod::ElGamalCiphertext> {
let ct_1 = combine_lo_hi(ct_1_lo, ct_1_hi)?;
add_ciphertexts(Scalar::one(), ct_0, Scalar::one(), ct_1)
}
pub fn subtract(ct_0: pod::ElGamalCT, ct_1: pod::ElGamalCT) -> Option<pod::ElGamalCT> {
pub fn subtract(
ct_0: pod::ElGamalCiphertext,
ct_1: pod::ElGamalCiphertext,
) -> Option<pod::ElGamalCiphertext> {
add_ciphertexts(Scalar::one(), ct_0, -Scalar::one(), ct_1)
}
pub fn subtract_with_lo_hi(
ct_0: pod::ElGamalCT,
ct_1_lo: pod::ElGamalCT,
ct_1_hi: pod::ElGamalCT,
) -> Option<pod::ElGamalCT> {
ct_0: pod::ElGamalCiphertext,
ct_1_lo: pod::ElGamalCiphertext,
ct_1_hi: pod::ElGamalCiphertext,
) -> Option<pod::ElGamalCiphertext> {
let ct_1 = combine_lo_hi(ct_1_lo, ct_1_hi)?;
add_ciphertexts(Scalar::one(), ct_0, -Scalar::one(), ct_1)
}
pub fn add_to(ct: pod::ElGamalCT, amount: u64) -> Option<pod::ElGamalCT> {
pub fn add_to(ct: pod::ElGamalCiphertext, amount: u64) -> Option<pod::ElGamalCiphertext> {
let mut amount_as_ct = [0_u8; 64];
amount_as_ct[..32].copy_from_slice(RISTRETTO_BASEPOINT_COMPRESSED.as_bytes());
add_ciphertexts(
Scalar::one(),
ct,
Scalar::from(amount),
pod::ElGamalCT(amount_as_ct),
pod::ElGamalCiphertext(amount_as_ct),
)
}
pub fn subtract_from(ct: pod::ElGamalCT, amount: u64) -> Option<pod::ElGamalCT> {
pub fn subtract_from(
ct: pod::ElGamalCiphertext,
amount: u64,
) -> Option<pod::ElGamalCiphertext> {
let mut amount_as_ct = [0_u8; 64];
amount_as_ct[..32].copy_from_slice(RISTRETTO_BASEPOINT_COMPRESSED.as_bytes());
add_ciphertexts(
Scalar::one(),
ct,
-Scalar::from(amount),
pod::ElGamalCT(amount_as_ct),
pod::ElGamalCiphertext(amount_as_ct),
)
}
}
@ -85,35 +94,44 @@ mod target_arch {
mod target_arch {
use crate::zk_token_elgamal::pod;
pub fn add(ct_0: pod::ElGamalCT, ct_1: pod::ElGamalCT) -> Option<pod::ElGamalCT> {
pub fn add(
ct_0: pod::ElGamalCiphertext,
ct_1: pod::ElGamalCiphertext,
) -> Option<pod::ElGamalCiphertext> {
None
}
pub fn add_with_lo_hi(
ct_0: pod::ElGamalCT,
ct_1_lo: pod::ElGamalCT,
ct_1_hi: pod::ElGamalCT,
) -> Option<pod::ElGamalCT> {
ct_0: pod::ElGamalCiphertext,
ct_1_lo: pod::ElGamalCiphertext,
ct_1_hi: pod::ElGamalCiphertext,
) -> Option<pod::ElGamalCiphertext> {
None
}
pub fn subtract(ct_0: pod::ElGamalCT, ct_1: pod::ElGamalCT) -> Option<pod::ElGamalCT> {
pub fn subtract(
ct_0: pod::ElGamalCiphertext,
ct_1: pod::ElGamalCiphertext,
) -> Option<pod::ElGamalCiphertext> {
None
}
pub fn subtract_with_lo_hi(
ct_0: pod::ElGamalCT,
ct_1_lo: pod::ElGamalCT,
ct_1_hi: pod::ElGamalCT,
) -> Option<pod::ElGamalCT> {
ct_0: pod::ElGamalCiphertext,
ct_1_lo: pod::ElGamalCiphertext,
ct_1_hi: pod::ElGamalCiphertext,
) -> Option<pod::ElGamalCiphertext> {
None
}
pub fn add_to(ct: pod::ElGamalCT, amount: u64) -> Option<pod::ElGamalCT> {
pub fn add_to(ct: pod::ElGamalCiphertext, amount: u64) -> Option<pod::ElGamalCiphertext> {
None
}
pub fn subtract_from(ct: pod::ElGamalCT, amount: u64) -> Option<pod::ElGamalCT> {
pub fn subtract_from(
ct: pod::ElGamalCiphertext,
amount: u64,
) -> Option<pod::ElGamalCiphertext> {
None
}
}
@ -123,7 +141,7 @@ mod tests {
use {
crate::{
encryption::{
elgamal::{ElGamal, ElGamalCT},
elgamal::{ElGamal, ElGamalCiphertext},
pedersen::{Pedersen, PedersenOpen},
},
zk_token_elgamal::{ops, pod},
@ -136,8 +154,8 @@ mod tests {
#[test]
fn test_zero_ct() {
let spendable_balance = pod::ElGamalCT::zeroed();
let spendable_ct: ElGamalCT = spendable_balance.try_into().unwrap();
let spendable_balance = pod::ElGamalCiphertext::zeroed();
let spendable_ct: ElGamalCiphertext = spendable_balance.try_into().unwrap();
// spendable_ct should be an encryption of 0 for any public key when
// `PedersenOpen::default()` is used
@ -151,22 +169,23 @@ mod tests {
// homomorphism should work like any other ciphertext
let open = PedersenOpen::random(&mut OsRng);
let transfer_amount_ct = pk.encrypt_with(55_u64, &open);
let transfer_amount_pod: pod::ElGamalCT = transfer_amount_ct.into();
let transfer_amount_pod: pod::ElGamalCiphertext = transfer_amount_ct.into();
let sum = ops::add(spendable_balance, transfer_amount_pod).unwrap();
let expected: pod::ElGamalCT = pk.encrypt_with(55_u64, &open).into();
let expected: pod::ElGamalCiphertext = pk.encrypt_with(55_u64, &open).into();
assert_eq!(expected, sum);
}
#[test]
fn test_add_to() {
let spendable_balance = pod::ElGamalCT::zeroed();
let spendable_balance = pod::ElGamalCiphertext::zeroed();
let added_ct = ops::add_to(spendable_balance, 55).unwrap();
let (pk, _) = ElGamal::keygen();
let expected: pod::ElGamalCT = pk.encrypt_with(55_u64, &PedersenOpen::default()).into();
let expected: pod::ElGamalCiphertext =
pk.encrypt_with(55_u64, &PedersenOpen::default()).into();
assert_eq!(expected, added_ct);
}
@ -176,11 +195,11 @@ mod tests {
let amount = 77_u64;
let (pk, _) = ElGamal::keygen();
let open = PedersenOpen::random(&mut OsRng);
let encrypted_amount: pod::ElGamalCT = pk.encrypt_with(amount, &open).into();
let encrypted_amount: pod::ElGamalCiphertext = pk.encrypt_with(amount, &open).into();
let subtracted_ct = ops::subtract_from(encrypted_amount, 55).unwrap();
let expected: pod::ElGamalCT = pk.encrypt_with(22_u64, &open).into();
let expected: pod::ElGamalCiphertext = pk.encrypt_with(22_u64, &open).into();
assert_eq!(expected, subtracted_ct);
}
@ -228,15 +247,16 @@ mod tests {
let source_open = PedersenOpen::random(&mut OsRng);
let dest_open = PedersenOpen::random(&mut OsRng);
let source_spendable_ct: pod::ElGamalCT =
let source_spendable_ct: pod::ElGamalCiphertext =
source_pk.encrypt_with(77_u64, &source_open).into();
let dest_pending_ct: pod::ElGamalCT = dest_pk.encrypt_with(77_u64, &dest_open).into();
let dest_pending_ct: pod::ElGamalCiphertext =
dest_pk.encrypt_with(77_u64, &dest_open).into();
// program arithmetic for the source account
// 1. Combine commitments and handles
let source_lo_ct: pod::ElGamalCT = (comm_lo, handle_source_lo).into();
let source_hi_ct: pod::ElGamalCT = (comm_hi, handle_source_hi).into();
let source_lo_ct: pod::ElGamalCiphertext = (comm_lo, handle_source_lo).into();
let source_hi_ct: pod::ElGamalCiphertext = (comm_hi, handle_source_hi).into();
// 2. Combine lo and hi ciphertexts
let source_combined_ct = ops::combine_lo_hi(source_lo_ct, source_hi_ct).unwrap();
@ -248,15 +268,15 @@ mod tests {
// test
let final_source_open =
source_open - (open_lo.clone() + open_hi.clone() * Scalar::from(ops::TWO_32));
let expected_source: pod::ElGamalCT =
let expected_source: pod::ElGamalCiphertext =
source_pk.encrypt_with(22_u64, &final_source_open).into();
assert_eq!(expected_source, final_source_spendable);
// same for the destination account
// 1. Combine commitments and handles
let dest_lo_ct: pod::ElGamalCT = (comm_lo, handle_dest_lo).into();
let dest_hi_ct: pod::ElGamalCT = (comm_hi, handle_dest_hi).into();
let dest_lo_ct: pod::ElGamalCiphertext = (comm_lo, handle_dest_lo).into();
let dest_hi_ct: pod::ElGamalCiphertext = (comm_hi, handle_dest_hi).into();
// 2. Combine lo and hi ciphertexts
let dest_combined_ct = ops::combine_lo_hi(dest_lo_ct, dest_hi_ct).unwrap();
@ -265,7 +285,7 @@ mod tests {
let final_dest_pending = ops::add(dest_pending_ct, dest_combined_ct).unwrap();
let final_dest_open = dest_open + (open_lo + open_hi * Scalar::from(ops::TWO_32));
let expected_dest_ct: pod::ElGamalCT =
let expected_dest_ct: pod::ElGamalCiphertext =
dest_pk.encrypt_with(132_u64, &final_dest_open).into();
assert_eq!(expected_dest_ct, final_dest_pending);
}

View File

@ -10,11 +10,11 @@ pub struct CompressedRistretto(pub [u8; 32]);
#[derive(Clone, Copy, Pod, Zeroable, PartialEq)]
#[repr(transparent)]
pub struct ElGamalCT(pub [u8; 64]);
pub struct ElGamalCiphertext(pub [u8; 64]);
#[derive(Clone, Copy, Pod, Zeroable, PartialEq)]
#[repr(transparent)]
pub struct ElGamalPK(pub [u8; 32]);
pub struct ElGamalPubkey(pub [u8; 32]);
#[derive(Clone, Copy, Pod, Zeroable, PartialEq)]
#[repr(transparent)]