paulmillr / noble-curves

Audited & minimal JS implementation of elliptic curve cryptography.
https://paulmillr.com/noble
MIT License
664 stars 62 forks source link

Fp.fromBytes does not mod-reduce by default #111

Open vincenzoiovino opened 8 months ago

vincenzoiovino commented 8 months ago

Hi, Paul

Consider the array derived set to Uint8Array(32) [ 239, 58, 3, 206, 5, 236, 79, 101, 215, 253, 95, 44, 114, 216, 108, 195, 191, 131, 86, 158, 222, 211, 233, 216, 103, 133, 230, 212, 191, 1, 173, 98 ]

I have the following code that uses derived:

   bg = require('@noble/curves/bn254').bn254;
        const fp = mod.Field(bg.CURVE.Fp.ORDER);
        var three = fp.create(3n);
        var one = fp.create(1n);
        var x = fp.fromBytes(derived);
        var y;
        while (true) {
            y = fp.mul(x, x);
            y = fp.mul(y, x);
            y = fp.add(y, three);
            try {
                y = fp.sqrt(y);
                break;
            } catch (err) {
                console.log("iterate");
                x = fp.add(x, one);
            }
        }
        console.log("x:" + x + " order:" + bg.CURVE.Fp.ORDER + " x<order:" + (x < bg.CURVE.Fp.ORDER)); 

I get the result:

x:108205274200769640731677027225433911640053818717593242889612531000506144894306 order:21888242871839275222246405745257275088696311157297823662689037894645226208583 x<order:false

The code is just doing some modular computations with fp, where p is initialized to the prime p=21888242871839275222246405745257275088696311157297823662689037894645226208583 of the bn254 curve. The issue is that each output of fp.mul/add/sqrt should be than p, Instead I get values larger than p. Isn't that incorrect?

(Btw, this should be the code for a hash to point function for bn254 that uses the basic hash and pray approach.)

vincenzoiovino commented 8 months ago

However, I can bypass the issue adding x=fp.create(x) If I can kindly use this thread I would ask another question. I have now coordinates x and y, what is the easiest way to create a G1 Point with coordinates x and y? It is not clear from the README.

paulmillr commented 8 months ago

fp.fromBytes does not do modulo-reducing by default. Maybe it's a bad idea, but it works like that now. So you need to do instead:

var x = fp.create(fp.fromBytes(derived));

I have now coordinates x and y, what is the easiest way to create a G1 Point with coordinates x and y?

bn254 is just an ordinary weierstrass curve - just like with any other, use bn254.ProjectivePoint class.