cfrg / draft-irtf-cfrg-voprf

Oblivious Pseudorandom Functions (OPRFs) using Prime-Order Groups
https://cfrg.github.io/draft-irtf-cfrg-voprf/#go.draft-irtf-cfrg-voprf.html
Other
38 stars 15 forks source link

DST design #198

Closed bytemare closed 3 years ago

bytemare commented 3 years ago

Hello,

I have been following the project for some time now, and am trying to accompany this with an implementation: https://github.com/bytemare/voprf.

I have some questions regarding the draft and some decisions that have been taken. I'll start with these:

  1. DST length The DST used to instantiate hash-to-curve is constructed with "RFCXXXX-" + contextstring, where contextstring is 3 bytes ( mode + ciphersuite). This has 11 bytes and is shorter than the recommended length in the h2c draft ( 16 bytes ). Is this the intended design?

  2. DST design The DST not really constructed with the recommended way in h2c. On the other hand, the info bytestring should be used for domain separation in voprf and construction after the h2c guidance. One could argue that the DST above = info, but this is not explicitly stated in the document. This is a tad confusing.

  3. Hashing prefixes Four dst elements are used for hashing throughout the document:

    • "-challenge-"
    • "-composite-"
    • "-Finalize-"
    • "-seed-"

It's a non-issue, but there some are lower-case or upper-case in the first letter.


I also want to add that your work is amazing and that I take great pleasure in studying and working with it! Thank you. It would be a great pleasure if I can be of any use helping spot and fix things.

bytemare commented 3 years ago

The length aspect has also been raised by @claucece in https://github.com/cfrg/draft-irtf-cfrg-voprf/issues/165, but the issue got closed without this point being addressed.

armfazh commented 3 years ago

The current DST for the HashToGroup function is:

DST = "RFCXXXX-" + I2OSP(mode, 1)  + I2OSP(suite.ID, 2)
len(DST) = 11

Effectively, DST is short. Thanks for pointing this out.


To remedy, these issues I propose (in #204 ) to extend it as follows:

DST = "RFCXXXX-HashToGroup-" + I2OSP(mode, 1)  + I2OSP(suite.ID, 2)
len(DST) = 22

Now, let's see whether this proposal satisfy the requirements for a good DST:

From Section 3.1 of draft-irtf-cfrg-hash-to-curve-10

  1. Tags MUST be supplied as the DST parameter to hash_to_field, as described in Section 5.

Yes, this DST is the one passed to HashToGroup that internally passes to hash_to_field.

  1. Tags MUST have nonzero length. A minimum length of 16 bytes is RECOMMENDED to reduce the chance of collisions with other applications.

len(DST) = 22 > 16

  1. Tags SHOULD begin with a fixed identification string that is unique to the application.

DST begins with "RFCXXXX". The rfc number will correspond to a single application: the OPRF protocol.

  1. Tags SHOULD include a version number.

SHOULD is not enforced, however, the rfc number provides some sort of versioning.

  1. For applications that define multiple ciphersuites, each ciphersuite's tag MUST be different. For this purpose, it is RECOMMENDED to include a ciphersuite identifier in each tag.

OPRF does have multiple ciphersuites. So, following this recommendation, the DST includes a ciphersuite identifier (I2OSP(suite.ID, 2))

  1. For applications that use multiple encodings, either to the same curve or to different curves, each encoding MUST use a different tag. For this purpose, it is RECOMMENDED to include the encoding's Suite ID (Section 8) in the domain separation tag. For independent encodings based on the same suite, each tag should also include a distinct identifier, e.g., "ENC1" and "ENC2".

OPRF does not use multiple encodings, only one when Client blinds the input, which is the same for Server during FullEvaluate or VerifyFinalize.

Finally, the DST separates queries to HashToGroup() between (Base)Client and VerifiableClient. DST is separated since includes the mode (I2OSP(mode, 1))

chris-wood commented 3 years ago

This should be fixed by #204, so I'm closing this as resolve. @bytemare, please re-open if you think more needs to be done!

bytemare commented 3 years ago

Looks good to me!

As a note: I'm thinking about the usage in higher-level applications. When h2c says we should specify the app or protocol, does this apply to the one directly using the HashToGroup function? Over time, default values (e.g. base mode with ristretto255) would tend to make usage of the same DST very common, even if the higher-level application is different. "PrivacyPass" or "OPAQUE" are different applications and protocols, that would also justify having their names used in the DST. But we'll encounter the chicken and egg problem: even higher-level protocols could claim the same. Opening the API to use a custom DST could lead to other problems, and make the whole design very weird. Using what @armfazh suggests seems to be the best way to do it properly.

chris-wood commented 3 years ago

Yeah, I think in this context, OPRF is the "application protocol" using hash-to-curve, so it seems appropriate to bind the DST to OPRF rather than the higher-level protocol using the OPRF.