Skip to content

Fix Hash to scalar incomplete #3

Closed
@moCello

Description

@moCello

Summary

From the audit report point BLS01:

The h() function in hash.rs hashes to a subgroup element by truncating
a 64-byte BLAKE2B hash to BlsScalar::SIZE=32 bytes, then clearing the
top 2 bytes to obtain a value less than 2254:

/// Hash an arbitrary slice of bytes into a [`BlsScalar`]
fn h(msg: &[u8]) -> BlsScalar {
    let mut digest: [u8; BlsScalar::SIZE] = Blake2b::digest(msg).into();

    // Truncate the contract id to fit bls
    digest[31] &= 0x3f;

    let hash: Option<BlsScalar> = BlsScalar::from_bytes(&digest).into();
    hash.unwrap_or_default()
}

However with such an implementation, certain subgroup elements cannot be
reached: as the subgroup size
0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001 is
approx. 2254.857.

It means that certain points will never be reached by h0(), and
certain scalars will never be reached by h1() (approx.
2253.7.

This appears to us not to be exploitable, but it would be safer to
implement the standard hash_to_field() function, as defined in the
Hashing to Ellpitic
Curve

RFC and implemented in
zkcrypto/bls12_381.

Possible Solution

We can use our BlsScalar::hash_to_scalar(msg) here.

Metadata

Metadata

Assignees

No one assigned

    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