WebAssembly / wasi-crypto

WASI Cryptography API Proposal
162 stars 25 forks source link

Comparing tags with tags or with bytes? #20

Closed jedisct1 closed 2 years ago

jedisct1 commented 4 years ago

What should we compare authentication tags with?

Proposal 1: compare tags with tags

A Tag object implements an equality function, that compares tags in constant time.

For application developers, computing a tag and comparing it with an existing one will be similar to:

expected_tag = Tag::from_bytes(expected_tag_as_bytes)?;
computed_tag = state.squeeze_tag();
if computed_tag == expected_tag {
  // success
} 

Proposal 2: compare tags with bytes

A Tag object implements a verify() function, that compares the tag to a bytes string:

computed_tag = state.squeeze_tag();
if computed_tag.verify(expected_tag_as_bytes) {
  // success
}

Tag objects are only returned by squeeze_tag(). They cannot be instantiated from existing data.

Which one should we use? (more ideas welcome!)

Both have the advantage of encouraging usage of a dedicated verification function, that will be guaranteed to be constant-time.

Possible advantages of proposal 1

As an example of the last point, a Tag can be exported along with all the public parameters required to recompute and verify it.

Verification of a stretched password:

// 1) let the application figure out how to store individual parameters
// 2) retrieve these parameters 
// 3) create a context for the previously used algorithm
// 4) initialize the context with these parameters
// 5) verify the password:

if computed_tag.verify(stored_tag_as_bytes) {
  // success
}

Alternatively, password stretching functions already define standard ways to output the tag and all the required parameters to recompute it as a string. That string even includes the algorithm identifier.

Using this representation of a tag instead, verification becomes easier:

// 1) create a generic context for password verification
// 2) verify the password:

if computed_tag.verify(stored_tag_as_a_string) {
 // success
}

Here, we have two ways to import and export a tag. But both are useful, and used.

Allowing a tag to be imported from existing data also allows the module to provide safe codecs that are constant-time for a given input size.

Possible advantages of proposal 2

Combining both?

Can we have two verification functions?

One that compares a Tag to a bytes string and another one that compares a Tag to a Tag?