Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions rln/src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -466,6 +466,12 @@ pub extern "C" fn key_gen(ctx: *const RLN, output_buffer: *mut Buffer) -> bool {
call_with_output_arg!(ctx, key_gen, output_buffer)
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn key_gen_be(ctx: *const RLN, output_buffer: *mut Buffer) -> bool {
call_with_output_arg!(ctx, key_gen_be, output_buffer)
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn seeded_key_gen(
Expand All @@ -476,12 +482,28 @@ pub extern "C" fn seeded_key_gen(
call_with_output_arg!(ctx, seeded_key_gen, output_buffer, input_buffer)
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn seeded_key_gen_be(
ctx: *const RLN,
input_buffer: *const Buffer,
output_buffer: *mut Buffer,
) -> bool {
call_with_output_arg!(ctx, seeded_key_gen_be, output_buffer, input_buffer)
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn extended_key_gen(ctx: *const RLN, output_buffer: *mut Buffer) -> bool {
call_with_output_arg!(ctx, extended_key_gen, output_buffer)
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn extended_key_gen_be(ctx: *const RLN, output_buffer: *mut Buffer) -> bool {
call_with_output_arg!(ctx, extended_key_gen_be, output_buffer)
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn seeded_extended_key_gen(
Expand All @@ -492,6 +514,16 @@ pub extern "C" fn seeded_extended_key_gen(
call_with_output_arg!(ctx, seeded_extended_key_gen, output_buffer, input_buffer)
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn seeded_extended_key_gen_be(
ctx: *const RLN,
input_buffer: *const Buffer,
output_buffer: *mut Buffer,
) -> bool {
call_with_output_arg!(ctx, seeded_extended_key_gen_be, output_buffer, input_buffer)
}

#[allow(clippy::not_unsafe_ptr_arg_deref)]
#[no_mangle]
pub extern "C" fn recover_id_secret(
Expand Down
42 changes: 40 additions & 2 deletions rln/src/protocol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,9 @@ use crate::hashers::{hash_to_field, poseidon_hash};
use crate::poseidon_tree::{MerkleProof, PoseidonTree};
use crate::public::RLN_IDENTIFIER;
use crate::utils::{
bytes_le_to_fr, bytes_le_to_vec_fr, bytes_le_to_vec_u8, fr_byte_size, fr_to_bytes_le,
normalize_usize, to_bigint, vec_fr_to_bytes_le, vec_u8_to_bytes_le,
bytes_be_to_fr, bytes_le_to_fr, bytes_le_to_vec_fr, bytes_le_to_vec_u8, fr_byte_size,
fr_to_bytes_be, fr_to_bytes_le, normalize_usize, to_bigint, vec_fr_to_bytes_le,
vec_u8_to_bytes_le,
};
use utils::{ZerokitMerkleProof, ZerokitMerkleTree};
///////////////////////////////////////////////////////
Expand Down Expand Up @@ -60,9 +61,17 @@ pub fn serialize_field_element(element: Fr) -> Vec<u8> {
fr_to_bytes_le(&element)
}

pub fn serialize_field_element_be(element: Fr) -> Vec<u8> {
fr_to_bytes_be(&element)
}

pub fn deserialize_field_element(serialized: Vec<u8>) -> Fr {
let (element, _) = bytes_le_to_fr(&serialized);
element
}

pub fn deserialize_field_element_be(serialized: Vec<u8>) -> Fr {
let (element, _) = bytes_be_to_fr(&serialized);
element
}

Expand All @@ -73,6 +82,13 @@ pub fn deserialize_identity_pair(serialized: Vec<u8>) -> (Fr, Fr) {
(identity_secret_hash, id_commitment)
}

pub fn deserialize_identity_pair_be(serialized: Vec<u8>) -> (Fr, Fr) {
let (identity_secret_hash, read) = bytes_be_to_fr(&serialized);
let (id_commitment, _) = bytes_be_to_fr(&serialized[read..]);

(identity_secret_hash, id_commitment)
}

pub fn deserialize_identity_tuple(serialized: Vec<u8>) -> (Fr, Fr, Fr, Fr) {
let mut all_read = 0;

Expand All @@ -95,6 +111,28 @@ pub fn deserialize_identity_tuple(serialized: Vec<u8>) -> (Fr, Fr, Fr, Fr) {
)
}

pub fn deserialize_identity_tuple_be(serialized: Vec<u8>) -> (Fr, Fr, Fr, Fr) {
let mut all_read = 0;

let (identity_trapdoor, read) = bytes_be_to_fr(&serialized[all_read..]);
all_read += read;

let (identity_nullifier, read) = bytes_be_to_fr(&serialized[all_read..]);
all_read += read;

let (identity_secret_hash, read) = bytes_be_to_fr(&serialized[all_read..]);
all_read += read;

let (identity_commitment, _) = bytes_be_to_fr(&serialized[all_read..]);

(
identity_trapdoor,
identity_nullifier,
identity_secret_hash,
identity_commitment,
)
}

/// Serializes witness
///
/// # Errors
Expand Down
89 changes: 87 additions & 2 deletions rln/src/public.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use crate::protocol::{
serialize_proof_values, serialize_witness, verify_proof,
};
use crate::utils::{
bytes_le_to_fr, bytes_le_to_vec_fr, bytes_le_to_vec_u8, fr_byte_size, fr_to_bytes_le,
vec_fr_to_bytes_le, vec_u8_to_bytes_le,
bytes_be_to_vec_fr, bytes_le_to_fr, bytes_le_to_vec_fr, bytes_le_to_vec_u8, fr_byte_size,
fr_to_bytes_be, fr_to_bytes_le, vec_fr_to_bytes_le, vec_u8_to_bytes_le,
};
#[cfg(not(target_arch = "wasm32"))]
use {
Expand Down Expand Up @@ -1139,6 +1139,15 @@ impl RLN {
Ok(())
}

/// Same as key_gen but serialized in BE format

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, I think it's better to add the full documentation when we merge the PR. There's no need for it right now while it's still a WIP, but let's not forget about it

pub fn key_gen_be<W: Write>(&self, mut output_data: W) -> Result<(), RLNError> {
let (identity_secret_hash, id_commitment) = keygen();
output_data.write_all(&fr_to_bytes_be(&identity_secret_hash))?;
output_data.write_all(&fr_to_bytes_be(&id_commitment))?;

Ok(())
}

/// Returns an identity trapdoor, nullifier, secret and commitment tuple.
///
/// The identity secret is the Poseidon hash of the identity trapdoor and identity nullifier.
Expand Down Expand Up @@ -1172,6 +1181,18 @@ impl RLN {
Ok(())
}

/// Same as extend_key_gen but serialized in BE format.
pub fn extended_key_gen_be<W: Write>(&self, mut output_data: W) -> Result<(), RLNError> {
let (identity_trapdoor, identity_nullifier, identity_secret_hash, id_commitment) =
extended_keygen();
output_data.write_all(&fr_to_bytes_be(&identity_trapdoor))?;
output_data.write_all(&fr_to_bytes_be(&identity_nullifier))?;
output_data.write_all(&fr_to_bytes_be(&identity_secret_hash))?;
output_data.write_all(&fr_to_bytes_be(&id_commitment))?;

Ok(())
}

/// Returns an identity secret and identity commitment pair generated using a seed.
///
/// The identity commitment is the Poseidon hash of the identity secret.
Expand Down Expand Up @@ -1211,6 +1232,22 @@ impl RLN {
Ok(())
}

/// Same as seeded_key_gen but in BE format
pub fn seeded_key_gen_be<R: Read, W: Write>(
&self,
mut input_data: R,
mut output_data: W,
) -> Result<(), RLNError> {
let mut serialized: Vec<u8> = Vec::new();
input_data.read_to_end(&mut serialized)?;

let (identity_secret_hash, id_commitment) = seeded_keygen(&serialized);
output_data.write_all(&fr_to_bytes_be(&identity_secret_hash))?;
output_data.write_all(&fr_to_bytes_be(&id_commitment))?;

Ok(())
}

/// Returns an identity trapdoor, nullifier, secret and commitment tuple generated using a seed.
///
/// The identity secret is the Poseidon hash of the identity trapdoor and identity nullifier.
Expand Down Expand Up @@ -1257,6 +1294,25 @@ impl RLN {
Ok(())
}

/// same as seeded_extended_key_gen but in BE format
pub fn seeded_extended_key_gen_be<R: Read, W: Write>(
&self,
mut input_data: R,
mut output_data: W,
) -> Result<(), RLNError> {
let mut serialized: Vec<u8> = Vec::new();
input_data.read_to_end(&mut serialized)?;

let (identity_trapdoor, identity_nullifier, identity_secret_hash, id_commitment) =
extended_seeded_keygen(&serialized);
output_data.write_all(&fr_to_bytes_be(&identity_trapdoor))?;
output_data.write_all(&fr_to_bytes_be(&identity_nullifier))?;
output_data.write_all(&fr_to_bytes_be(&identity_secret_hash))?;
output_data.write_all(&fr_to_bytes_be(&id_commitment))?;

Ok(())
}

/// Recovers the identity secret from two set of proof values computed for same secret in same epoch with same rln identifier.
///
/// Input values are:
Expand Down Expand Up @@ -1437,6 +1493,20 @@ pub fn hash<R: Read, W: Write>(
Ok(())
}

/// same as hash function but in BE format
pub fn hash_be<R: Read, W: Write>(
mut input_data: R,
mut output_data: W,
) -> Result<(), std::io::Error> {
let mut serialized: Vec<u8> = Vec::new();
input_data.read_to_end(&mut serialized)?;

let hash = hash_to_field(&serialized);
output_data.write_all(&fr_to_bytes_be(&hash))?;

Ok(())
}

/// Hashes a set of elements to a single element in the working prime field, using Poseidon.
///
/// The result is computed as the Poseidon Hash of the input signal.
Expand Down Expand Up @@ -1473,3 +1543,18 @@ pub fn poseidon_hash<R: Read, W: Write>(

Ok(())
}

/// same as poseidon_hash function but in BE format. Note that input is expected in BE format too.
pub fn poseidon_hash_be<R: Read, W: Write>(
mut input_data: R,
mut output_data: W,
) -> Result<(), RLNError> {
let mut serialized: Vec<u8> = Vec::new();
input_data.read_to_end(&mut serialized)?;

let (inputs, _) = bytes_be_to_vec_fr(&serialized)?;
let hash = utils_poseidon_hash(inputs.as_ref());
output_data.write_all(&fr_to_bytes_be(&hash))?;

Ok(())
}
54 changes: 54 additions & 0 deletions rln/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,15 @@ pub fn bytes_le_to_fr(input: &[u8]) -> (Fr, usize) {
)
}

#[inline(always)]
pub fn bytes_be_to_fr(input: &[u8]) -> (Fr, usize) {
let el_size = fr_byte_size();
(
Fr::from(BigUint::from_bytes_be(&input[0..el_size])),
el_size,
)
}

#[inline(always)]
pub fn fr_to_bytes_le(input: &Fr) -> Vec<u8> {
let input_biguint: BigUint = (*input).into();
Expand All @@ -56,6 +65,19 @@ pub fn fr_to_bytes_le(input: &Fr) -> Vec<u8> {
res
}

#[inline(always)]
pub fn fr_to_bytes_be(input: &Fr) -> Vec<u8> {
let input_biguint: BigUint = (*input).into();
let mut res = input_biguint.to_bytes_be();
// For BE, insert 0 at the start of the Vec (see also fr_to_bytes_le comments)
let to_insert_count = fr_byte_size().saturating_sub(res.len());
if to_insert_count > 0 {
// Insert multi 0 at index 0
res.splice(0..0, std::iter::repeat_n(0, to_insert_count));
}
res
}

#[inline(always)]
pub fn vec_fr_to_bytes_le(input: &[Fr]) -> Vec<u8> {
// Calculate capacity for Vec:
Expand Down Expand Up @@ -120,6 +142,24 @@ pub fn bytes_le_to_vec_fr(input: &[u8]) -> Result<(Vec<Fr>, usize), ConversionEr
Ok((res, read))
}

#[inline(always)]
pub fn bytes_be_to_vec_fr(input: &[u8]) -> Result<(Vec<Fr>, usize), ConversionError> {
let mut read: usize = 0;
let mut res: Vec<Fr> = Vec::new();

let len = usize::try_from(u64::from_be_bytes(input[0..8].try_into()?))?;
read += 8;

let el_size = fr_byte_size();
for i in 0..len {
let (curr_el, _) = bytes_be_to_fr(&input[8 + el_size * i..8 + el_size * (i + 1)]);
res.push(curr_el);
read += el_size;
}

Ok((res, read))
}

#[inline(always)]
pub fn bytes_le_to_vec_usize(input: &[u8]) -> Result<Vec<usize>, ConversionError> {
let nof_elem = usize::try_from(u64::from_le_bytes(input[0..8].try_into()?))?;
Expand Down Expand Up @@ -149,3 +189,17 @@ pub fn normalize_usize(input: usize) -> [u8; 8] {
pub fn generate_input_buffer() -> Cursor<String> {
Cursor::new(json!({}).to_string())
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn test_fr_be() {
let fr_1 = Fr::from(255);
let b = fr_to_bytes_be(&fr_1);
let fr_1_de = bytes_be_to_fr(&b).0;
assert_eq!(fr_1, fr_1_de);
}

}