Skip to content

Permutation iv design #66

@alxiong

Description

@alxiong

I ran into a use case where the Sponge is over >256 bits field, and I want to initialize the sponge state with a field element (think keyed hash, but algebraic with fields rather than bytes).

If I use DuplexSponge::new(f.into_bigint().to_bytes_be()[..32]), then i'm basically truncating some of the bytes, which is not ideal.
Ideally, I want a DuplexSponge::new_from(iv: U) where U: Permutation::U.
Ultimately I'm proposing an additional method on trait Permutation called: ::new_from(iv: U) or ::new_from_unit(iv: U).

(a somewhat related topic, the choice to use big-endian for PoseidonPermutation implementation is little inconvenient imo:

fn new(iv: [u8; 32]) -> Self {
assert!(N >= 1);
let mut sponge = Self::default();
sponge.state[R] = F::from_be_bytes_mod_order(&iv);
sponge
}

because if my field size is <32 bytes, and I want the "keyed iv" behavior, then i have to do this:

        let key_bigint_bytes = key.into_bigint().to_bytes_be();
        let mut key_bytes_be = [0u8; 32];
        let copy_len = usize::min(32, key_bigint_bytes.len());
        key_bytes_be[32 - copy_len..]
            .copy_from_slice(&key_bigint_bytes[key_bigint_bytes.len() - copy_len..]);

        let mut perm = PoseidonPermutation::new(key_bytes_be);

whereas if we use little-endian then it's eye-friendly:

        let mut key_bytes_le = [0u8; 32];
        key_bytes_le.copy_from_slice(&key.into_bigint().to_bytes_le());

        let mut perm = PoseidonPermutation::new(key_bytes_le);

But this is super nit-picky, and doesn't hurt either way. Just pointing out its small implication on the consumer side.

cc @mmaker

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions