dusk-network / dusk-zerocaf

Zerocaf: A library built for EC operations in Zero Knowledge.
https://dusk.network/
MIT License
53 stars 11 forks source link

#ITEM 2 - Random point generation from Elligator does not produce valid points. #84

Closed CPerezz closed 5 years ago

CPerezz commented 5 years ago

As it was mentioned in 2683d3c.

This has been done like this instead of generating random RistrettoPoints directly since it caused the tests to fail, meaning that something was wrong on the random point generation using the Elligator hash-to-group function.

What this means is that generating random RistrettoPoints using the Elligator hash-to-group function is not working as expected since it does not produce valid RistretttoPoints.

It will be better, in my opinion, to implement the random RistrettoPoint generation following the double Elligator application to a [0; 64] random-bytes slice as it's done in the ristretto.rs implementation done in the curve25519-dalek library.

Why? As mentioned there, following this path, we get a uniformly distributed entropy -> Uniformly distributed random RistrettoPoint generation. Which is better than the one obtained multiplying the unique_basepoint by a random Scalar.

So we should take a look at the whole random-generation path to spot the error (if there is any) or otherways review the docs again.

CPerezz commented 5 years ago

elligator_ristretto_flavour tests are not passing even the values have been proved to be correct and obtained using the ristretto.sage file of curve25519-dalek repo.

These are the values that should verify the test:

 let expected_point = RistrettoPoint(EdwardsPoint {
            X: FieldElement([2540092001196116, 3784756715621701, 1814242880979619, 1117392456187628, 11990935440698]),
            Y: FieldElement([4303254075288083, 1561555891432216, 2751628063507233, 2858806956288226, 11214346266987]),
            Z: FieldElement([1, 0, 0, 0, 0]),
            T: FieldElement([1237065776631074, 2466024980578134, 2154449949014471, 1511195856276950, 11744736340970])
        });
        let raw_bytes = hex::decode("49e385259ab1290854d78e7b1f5fc9aaec60a316cac1a13e9359bf8823933864").unwrap();

Implementation has been double-checked, and the implementation follows the docs, so we need to take a deeper look into it.

CPerezz commented 5 years ago

The values were obtained on the following sage session:

sage: rand_bytes = randombytes(32)
sage: rand_bytes
bytearray(b'I\xe3\x85%\x9a\xb1)\x08T\xd7\x8e{\x1f_\xc9\xaa\xec`\xa3\x16\xca\xc1\xa1>\x93Y\xbf\x88#\x938d')
sage: binascii.hexlify(rand_bytes)
'49e385259ab1290854d78e7b1f5fc9aaec60a316cac1a13e9359bf8823933864'
sage: basep = SonnyPoint.base().elligator(rand_bytes)
sage: basep
SonnyPoint(0xae7db728d3a3f843346cfeec6720b567502a3d723757988d4590633416d9854,0xa330b20296ba2811dd1c68e29c6975547832158c3a1034ab18f49c96a892a13)