-
Notifications
You must be signed in to change notification settings - Fork 15
Added padding to Poseidon duplex #26
base: master
Are you sure you want to change the base?
Conversation
We will need to examine the changes in this PR further and likely consider adding a Poseidon duplex wrapper that is less "raw" than what arkworks-rs currently has. I agree that:
The issue is this:
The second point you mentioned, regarding the limitation of the output, may be not necessary. Based on the paper, it seems that it limits the amount of bytes (in our case, field elements) that can be outputted "each round". But the sponge implementation in arkworks-rs permutes the state before outputting more bytes (so, the sponge enters the next round), so it should be fine---but padding is necessary to show that this round is different from other rounds, in that it has zero input. |
These are fair points. Some thoughts:
|
Also, st4d pointed me to a specification draft for this construction: C2SP/C2SP#3 |
I would actually suggest that the problem with the current API is that it is both "too raw" and "not raw enough". On the one hand, it's not yet safe for general use, but on the other hand, it doesn't expose the underlying permutation in a way that would allow implementing different constructions (fixed-length hashing, duplex variants, etc) on top. I think a path forward for this would be to split the current code into two levels, as suggested here: arkworks-rs/crypto-primitives#93 Then, the crate can provide a general-purpose, safe(ish) duplex API like this one, and allow users who want to optimize performance for fixed messages to use the underlying permutation directly. |
Description
The Poseidon duplex construction in this crate was trivially insecure. I wrote a regression test,
test_collision
, that demonstrates twoabsorb
inputs which produce the samesqueeze
output. The problem was that there was no padding applied to any absorbed messages.As mentioned in the duplex paper a "sponge-compliant" padding scheme (Definition 1) is crucial to the security claims of the sponge and duplex constructions. So I went ahead and adapted the multi-rate padding function (Section 7) to a finite field setting. The only caveat is that this doesn't work when F = Z/2Z. I assume that's not an issue though. If it is, I can make another version that ends up being even less efficient, requiring all Poseidon rates to be at least 3 in order to function.
Two things that still need to be done (and see Zcash's impl for a reference):
Don't chunk the contents of
absorb
and feed it all in. As the paper specifies,absorb
's input len should be limited to the maximum that can fit in arate
-sized block, after padding. The current auto-chunking trick makes it so thatabsorb(a || b)
andabsorb(a), absorb(b)
yield the same state. This isn't good. Instead, the duplex needs to limitabsorbs
and force the user to figure out message packet system that disambiguates the things that they care about. STROBE disambiguates by prepending every new operation with a special message.Don't allow
squeeze
to output more thanrate
bytes. This is also specified by the paper. I'm actually less confident about this suggestion because it seems fine to simplypermute()
when bytes run out. This is because, by the padding principle, the input will never collide with an actual message. Concretely, this mechanism still satisfies the injectivity claim proven by Lemma 4 in the paper. Also, if this functionality is removed, I'm not certain how one would get more bytes out of a stream.Finally, I commented out
test_poseidon_sponge_consistency
because I couldn't figure out how to re-derive the new expected values for the output. That's an easy fix if you know which traits give you a base-10 representation of your field elements (which I do not).Before we can merge this PR, please make sure that all the following items have been
checked off. If any of the checklist items are not applicable, please leave them but
write a little note why.
Pending
section inCHANGELOG.md
Files changed
in the Github PR explorer