diff --git a/ecc/bls12-377/g1.go b/ecc/bls12-377/g1.go index 086be7bb32..44674529e4 100644 --- a/ecc/bls12-377/g1.go +++ b/ecc/bls12-377/g1.go @@ -61,7 +61,7 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) @@ -72,7 +72,7 @@ func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) diff --git a/ecc/bls12-377/g2.go b/ecc/bls12-377/g2.go index ec128397b9..d954f9ffad 100644 --- a/ecc/bls12-377/g2.go +++ b/ecc/bls12-377/g2.go @@ -66,7 +66,7 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) @@ -77,7 +77,7 @@ func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) diff --git a/ecc/bls12-377/hash_to_g1.go b/ecc/bls12-377/hash_to_g1.go index 45d71155da..04d0f9b60a 100644 --- a/ecc/bls12-377/hash_to_g1.go +++ b/ecc/bls12-377/hash_to_g1.go @@ -180,9 +180,9 @@ func g1MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG1 implements the SSWU map -// No cofactor clearing -func sswuMapG1(u *fp.Element) G1Affine { +// mapToCurve1 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve1(u *fp.Element) G1Affine { var tv1 fp.Element tv1.Square(u) @@ -254,7 +254,7 @@ func sswuMapG1(u *fp.Element) G1Affine { // MapToG1 invokes the SSWU map, and guarantees that the result is in g1 func MapToG1(u fp.Element) G1Affine { - res := sswuMapG1(&u) + res := mapToCurve1(&u) //this is in an isogenous curve g1Isogeny(&res) res.ClearCofactor(&res) @@ -273,7 +273,7 @@ func EncodeToG1(msg, dst []byte) (G1Affine, error) { return res, err } - res = sswuMapG1(&u[0]) + res = mapToCurve1(&u[0]) //this is in an isogenous curve g1Isogeny(&res) @@ -291,8 +291,8 @@ func HashToG1(msg, dst []byte) (G1Affine, error) { return G1Affine{}, err } - Q0 := sswuMapG1(&u[0]) - Q1 := sswuMapG1(&u[1]) + Q0 := mapToCurve1(&u[0]) + Q1 := mapToCurve1(&u[1]) //TODO: Add in E' first, then apply isogeny g1Isogeny(&Q0) diff --git a/ecc/bls12-377/hash_to_g1_test.go b/ecc/bls12-377/hash_to_g1_test.go index 1d47044980..0926109fa1 100644 --- a/ecc/bls12-377/hash_to_g1_test.go +++ b/ecc/bls12-377/hash_to_g1_test.go @@ -107,7 +107,7 @@ func TestG1SSWU(t *testing.T) { properties.Property("[G1] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG1(&a) + g := mapToCurve1(&a) if !isOnEPrimeG1(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bls12-377/hash_to_g2.go b/ecc/bls12-377/hash_to_g2.go index 9ca181bd61..0c60f7af30 100644 --- a/ecc/bls12-377/hash_to_g2.go +++ b/ecc/bls12-377/hash_to_g2.go @@ -629,9 +629,9 @@ func g2MulByZ(z *fptower.E2, x *fptower.E2) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG2 implements the SSWU map -// No cofactor clearing -func sswuMapG2(u *fptower.E2) G2Affine { +// mapToCurve2 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve2(u *fptower.E2) G2Affine { var tv1 fptower.E2 tv1.Square(u) @@ -718,7 +718,7 @@ func sswuMapG2(u *fptower.E2) G2Affine { // MapToG2 invokes the SSWU map, and guarantees that the result is in g2 func MapToG2(u fptower.E2) G2Affine { - res := sswuMapG2(&u) + res := mapToCurve2(&u) //this is in an isogenous curve g2Isogeny(&res) res.ClearCofactor(&res) @@ -737,7 +737,7 @@ func EncodeToG2(msg, dst []byte) (G2Affine, error) { return res, err } - res = sswuMapG2(&fptower.E2{ + res = mapToCurve2(&fptower.E2{ A0: u[0], A1: u[1], }) @@ -758,11 +758,11 @@ func HashToG2(msg, dst []byte) (G2Affine, error) { return G2Affine{}, err } - Q0 := sswuMapG2(&fptower.E2{ + Q0 := mapToCurve2(&fptower.E2{ A0: u[0], A1: u[1], }) - Q1 := sswuMapG2(&fptower.E2{ + Q1 := mapToCurve2(&fptower.E2{ A0: u[2+0], A1: u[2+1], }) diff --git a/ecc/bls12-377/hash_to_g2_test.go b/ecc/bls12-377/hash_to_g2_test.go index d11ec0240c..f592e837d7 100644 --- a/ecc/bls12-377/hash_to_g2_test.go +++ b/ecc/bls12-377/hash_to_g2_test.go @@ -109,7 +109,7 @@ func TestG2SSWU(t *testing.T) { properties.Property("[G2] hash outputs must be in appropriate groups", prop.ForAll( func(a fptower.E2) bool { - g := sswuMapG2(&a) + g := mapToCurve2(&a) if !isOnEPrimeG2(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bls12-378/g1.go b/ecc/bls12-378/g1.go index e1462c2a04..2ec1819973 100644 --- a/ecc/bls12-378/g1.go +++ b/ecc/bls12-378/g1.go @@ -61,7 +61,7 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) @@ -72,7 +72,7 @@ func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) diff --git a/ecc/bls12-378/g2.go b/ecc/bls12-378/g2.go index 1f59a23fb4..685ee98660 100644 --- a/ecc/bls12-378/g2.go +++ b/ecc/bls12-378/g2.go @@ -66,7 +66,7 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) @@ -77,7 +77,7 @@ func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) diff --git a/ecc/bls12-378/hash_to_g1.go b/ecc/bls12-378/hash_to_g1.go index 5031372599..273c8f8efb 100644 --- a/ecc/bls12-378/hash_to_g1.go +++ b/ecc/bls12-378/hash_to_g1.go @@ -182,9 +182,9 @@ func g1MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG1 implements the SSWU map -// No cofactor clearing -func sswuMapG1(u *fp.Element) G1Affine { +// mapToCurve1 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve1(u *fp.Element) G1Affine { var tv1 fp.Element tv1.Square(u) @@ -256,7 +256,7 @@ func sswuMapG1(u *fp.Element) G1Affine { // MapToG1 invokes the SSWU map, and guarantees that the result is in g1 func MapToG1(u fp.Element) G1Affine { - res := sswuMapG1(&u) + res := mapToCurve1(&u) //this is in an isogenous curve g1Isogeny(&res) res.ClearCofactor(&res) @@ -275,7 +275,7 @@ func EncodeToG1(msg, dst []byte) (G1Affine, error) { return res, err } - res = sswuMapG1(&u[0]) + res = mapToCurve1(&u[0]) //this is in an isogenous curve g1Isogeny(&res) @@ -293,8 +293,8 @@ func HashToG1(msg, dst []byte) (G1Affine, error) { return G1Affine{}, err } - Q0 := sswuMapG1(&u[0]) - Q1 := sswuMapG1(&u[1]) + Q0 := mapToCurve1(&u[0]) + Q1 := mapToCurve1(&u[1]) //TODO: Add in E' first, then apply isogeny g1Isogeny(&Q0) diff --git a/ecc/bls12-378/hash_to_g1_test.go b/ecc/bls12-378/hash_to_g1_test.go index bdd0d30bb3..3cfde28b51 100644 --- a/ecc/bls12-378/hash_to_g1_test.go +++ b/ecc/bls12-378/hash_to_g1_test.go @@ -107,7 +107,7 @@ func TestG1SSWU(t *testing.T) { properties.Property("[G1] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG1(&a) + g := mapToCurve1(&a) if !isOnEPrimeG1(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bls12-381/g1.go b/ecc/bls12-381/g1.go index 33050c6b92..143ba76f88 100644 --- a/ecc/bls12-381/g1.go +++ b/ecc/bls12-381/g1.go @@ -61,7 +61,7 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) @@ -72,7 +72,7 @@ func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) diff --git a/ecc/bls12-381/g2.go b/ecc/bls12-381/g2.go index 33f8cd315a..d2a773fed3 100644 --- a/ecc/bls12-381/g2.go +++ b/ecc/bls12-381/g2.go @@ -66,7 +66,7 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) @@ -77,7 +77,7 @@ func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) diff --git a/ecc/bls12-381/hash_to_g1.go b/ecc/bls12-381/hash_to_g1.go index 7b32888cf9..688e21022f 100644 --- a/ecc/bls12-381/hash_to_g1.go +++ b/ecc/bls12-381/hash_to_g1.go @@ -183,9 +183,9 @@ func g1MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG1 implements the SSWU map -// No cofactor clearing -func sswuMapG1(u *fp.Element) G1Affine { +// mapToCurve1 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve1(u *fp.Element) G1Affine { var tv1 fp.Element tv1.Square(u) @@ -257,7 +257,7 @@ func sswuMapG1(u *fp.Element) G1Affine { // MapToG1 invokes the SSWU map, and guarantees that the result is in g1 func MapToG1(u fp.Element) G1Affine { - res := sswuMapG1(&u) + res := mapToCurve1(&u) //this is in an isogenous curve g1Isogeny(&res) res.ClearCofactor(&res) @@ -276,7 +276,7 @@ func EncodeToG1(msg, dst []byte) (G1Affine, error) { return res, err } - res = sswuMapG1(&u[0]) + res = mapToCurve1(&u[0]) //this is in an isogenous curve g1Isogeny(&res) @@ -294,8 +294,8 @@ func HashToG1(msg, dst []byte) (G1Affine, error) { return G1Affine{}, err } - Q0 := sswuMapG1(&u[0]) - Q1 := sswuMapG1(&u[1]) + Q0 := mapToCurve1(&u[0]) + Q1 := mapToCurve1(&u[1]) //TODO: Add in E' first, then apply isogeny g1Isogeny(&Q0) diff --git a/ecc/bls12-381/hash_to_g1_test.go b/ecc/bls12-381/hash_to_g1_test.go index 61077661f1..f364e9ae76 100644 --- a/ecc/bls12-381/hash_to_g1_test.go +++ b/ecc/bls12-381/hash_to_g1_test.go @@ -107,7 +107,7 @@ func TestG1SSWU(t *testing.T) { properties.Property("[G1] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG1(&a) + g := mapToCurve1(&a) if !isOnEPrimeG1(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bls12-381/hash_to_g2.go b/ecc/bls12-381/hash_to_g2.go index 747e4d2d2a..f3d2061f82 100644 --- a/ecc/bls12-381/hash_to_g2.go +++ b/ecc/bls12-381/hash_to_g2.go @@ -229,9 +229,9 @@ func g2MulByZ(z *fptower.E2, x *fptower.E2) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG2 implements the SSWU map -// No cofactor clearing -func sswuMapG2(u *fptower.E2) G2Affine { +// mapToCurve2 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve2(u *fptower.E2) G2Affine { var tv1 fptower.E2 tv1.Square(u) @@ -318,7 +318,7 @@ func sswuMapG2(u *fptower.E2) G2Affine { // MapToG2 invokes the SSWU map, and guarantees that the result is in g2 func MapToG2(u fptower.E2) G2Affine { - res := sswuMapG2(&u) + res := mapToCurve2(&u) //this is in an isogenous curve g2Isogeny(&res) res.ClearCofactor(&res) @@ -337,7 +337,7 @@ func EncodeToG2(msg, dst []byte) (G2Affine, error) { return res, err } - res = sswuMapG2(&fptower.E2{ + res = mapToCurve2(&fptower.E2{ A0: u[0], A1: u[1], }) @@ -358,11 +358,11 @@ func HashToG2(msg, dst []byte) (G2Affine, error) { return G2Affine{}, err } - Q0 := sswuMapG2(&fptower.E2{ + Q0 := mapToCurve2(&fptower.E2{ A0: u[0], A1: u[1], }) - Q1 := sswuMapG2(&fptower.E2{ + Q1 := mapToCurve2(&fptower.E2{ A0: u[2+0], A1: u[2+1], }) diff --git a/ecc/bls12-381/hash_to_g2_test.go b/ecc/bls12-381/hash_to_g2_test.go index 7530c8bbb3..3fc1709f93 100644 --- a/ecc/bls12-381/hash_to_g2_test.go +++ b/ecc/bls12-381/hash_to_g2_test.go @@ -109,7 +109,7 @@ func TestG2SSWU(t *testing.T) { properties.Property("[G2] hash outputs must be in appropriate groups", prop.ForAll( func(a fptower.E2) bool { - g := sswuMapG2(&a) + g := mapToCurve2(&a) if !isOnEPrimeG2(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bls24-315/g1.go b/ecc/bls24-315/g1.go index 8b968f4f29..768d5565a7 100644 --- a/ecc/bls24-315/g1.go +++ b/ecc/bls24-315/g1.go @@ -61,7 +61,7 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) @@ -72,7 +72,7 @@ func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) diff --git a/ecc/bls24-315/g2.go b/ecc/bls24-315/g2.go index f30ca4590e..c2d17c9da9 100644 --- a/ecc/bls24-315/g2.go +++ b/ecc/bls24-315/g2.go @@ -66,7 +66,7 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) @@ -77,7 +77,7 @@ func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) diff --git a/ecc/bls24-315/hash_to_g1.go b/ecc/bls24-315/hash_to_g1.go index 893757338c..08ec4ce79d 100644 --- a/ecc/bls24-315/hash_to_g1.go +++ b/ecc/bls24-315/hash_to_g1.go @@ -182,9 +182,9 @@ func g1MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG1 implements the SSWU map -// No cofactor clearing -func sswuMapG1(u *fp.Element) G1Affine { +// mapToCurve1 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve1(u *fp.Element) G1Affine { var tv1 fp.Element tv1.Square(u) @@ -256,7 +256,7 @@ func sswuMapG1(u *fp.Element) G1Affine { // MapToG1 invokes the SSWU map, and guarantees that the result is in g1 func MapToG1(u fp.Element) G1Affine { - res := sswuMapG1(&u) + res := mapToCurve1(&u) //this is in an isogenous curve g1Isogeny(&res) res.ClearCofactor(&res) @@ -275,7 +275,7 @@ func EncodeToG1(msg, dst []byte) (G1Affine, error) { return res, err } - res = sswuMapG1(&u[0]) + res = mapToCurve1(&u[0]) //this is in an isogenous curve g1Isogeny(&res) @@ -293,8 +293,8 @@ func HashToG1(msg, dst []byte) (G1Affine, error) { return G1Affine{}, err } - Q0 := sswuMapG1(&u[0]) - Q1 := sswuMapG1(&u[1]) + Q0 := mapToCurve1(&u[0]) + Q1 := mapToCurve1(&u[1]) //TODO: Add in E' first, then apply isogeny g1Isogeny(&Q0) diff --git a/ecc/bls24-315/hash_to_g1_test.go b/ecc/bls24-315/hash_to_g1_test.go index 8e7031aa44..24973fd12b 100644 --- a/ecc/bls24-315/hash_to_g1_test.go +++ b/ecc/bls24-315/hash_to_g1_test.go @@ -107,7 +107,7 @@ func TestG1SSWU(t *testing.T) { properties.Property("[G1] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG1(&a) + g := mapToCurve1(&a) if !isOnEPrimeG1(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bls24-317/g1.go b/ecc/bls24-317/g1.go index 1d8da7d629..4868dc06b6 100644 --- a/ecc/bls24-317/g1.go +++ b/ecc/bls24-317/g1.go @@ -61,7 +61,7 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) @@ -72,7 +72,7 @@ func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) diff --git a/ecc/bls24-317/g2.go b/ecc/bls24-317/g2.go index 95f94cedb1..1e15e9294c 100644 --- a/ecc/bls24-317/g2.go +++ b/ecc/bls24-317/g2.go @@ -66,7 +66,7 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) @@ -77,7 +77,7 @@ func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) diff --git a/ecc/bls24-317/hash_to_g1.go b/ecc/bls24-317/hash_to_g1.go index a981d01e0f..03a3af54a8 100644 --- a/ecc/bls24-317/hash_to_g1.go +++ b/ecc/bls24-317/hash_to_g1.go @@ -151,9 +151,9 @@ func g1MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG1 implements the SSWU map -// No cofactor clearing -func sswuMapG1(u *fp.Element) G1Affine { +// mapToCurve1 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve1(u *fp.Element) G1Affine { var tv1 fp.Element tv1.Square(u) @@ -225,7 +225,7 @@ func sswuMapG1(u *fp.Element) G1Affine { // MapToG1 invokes the SSWU map, and guarantees that the result is in g1 func MapToG1(u fp.Element) G1Affine { - res := sswuMapG1(&u) + res := mapToCurve1(&u) //this is in an isogenous curve g1Isogeny(&res) res.ClearCofactor(&res) @@ -244,7 +244,7 @@ func EncodeToG1(msg, dst []byte) (G1Affine, error) { return res, err } - res = sswuMapG1(&u[0]) + res = mapToCurve1(&u[0]) //this is in an isogenous curve g1Isogeny(&res) @@ -262,8 +262,8 @@ func HashToG1(msg, dst []byte) (G1Affine, error) { return G1Affine{}, err } - Q0 := sswuMapG1(&u[0]) - Q1 := sswuMapG1(&u[1]) + Q0 := mapToCurve1(&u[0]) + Q1 := mapToCurve1(&u[1]) //TODO: Add in E' first, then apply isogeny g1Isogeny(&Q0) diff --git a/ecc/bls24-317/hash_to_g1_test.go b/ecc/bls24-317/hash_to_g1_test.go index c53248df9e..dc037fd31c 100644 --- a/ecc/bls24-317/hash_to_g1_test.go +++ b/ecc/bls24-317/hash_to_g1_test.go @@ -107,7 +107,7 @@ func TestG1SSWU(t *testing.T) { properties.Property("[G1] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG1(&a) + g := mapToCurve1(&a) if !isOnEPrimeG1(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bn254/g1.go b/ecc/bn254/g1.go index cc335f0bc5..b1a439f80c 100644 --- a/ecc/bn254/g1.go +++ b/ecc/bn254/g1.go @@ -61,7 +61,7 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) @@ -72,7 +72,7 @@ func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) diff --git a/ecc/bn254/g2.go b/ecc/bn254/g2.go index 2c3f76cda2..f3140767ff 100644 --- a/ecc/bn254/g2.go +++ b/ecc/bn254/g2.go @@ -66,7 +66,7 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) @@ -77,7 +77,7 @@ func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) diff --git a/ecc/bn254/hash_to_g1.go b/ecc/bn254/hash_to_g1.go index 98cae5fe61..a97a37ff45 100644 --- a/ecc/bn254/hash_to_g1.go +++ b/ecc/bn254/hash_to_g1.go @@ -21,75 +21,87 @@ import ( "github.com/consensys/gnark-crypto/ecc/bn254/fp" ) -// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-4.1 +// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-14#appendix-F.1 // Shallue and van de Woestijne method, works for any elliptic curve in Weierstrass curve -func svdwMapG1(u fp.Element) G1Affine { - - var res G1Affine - - // constants - // sage script to find z: https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-E.1 - var z, c1, c2, c3, c4 fp.Element - z.SetOne() +func mapToCurve1(u fp.Element) G1Affine { + var tv1, tv2, tv3, tv4 fp.Element + var x1, x2, x3, gx1, gx2, gx, x, y fp.Element + var one fp.Element + var gx1NotSquare, gx1SquareOrGx2Not int + + //constants + //c1 = g(Z) + //c2 = -Z / 2 + //c3 = sqrt(-g(Z) * (3 * Z² + 4 * A)) # sgn0(c3) MUST equal 0 + //c4 = -4 * g(Z) / (3 * Z² + 4 * A) + + var Z, c1, c2, c3, c4 fp.Element + Z.SetOne() c1.SetString("4") c2.SetString("10944121435919637611123202872628637544348155578648911831344518947322613104291") c3.SetString("8815841940592487685674414971303048083897117035520822607866") c4.SetString("7296080957279758407415468581752425029565437052432607887563012631548408736189") - var tv1, tv2, tv3, tv4, one, x1, gx1, x2, gx2, x3, x, gx, y fp.Element one.SetOne() - tv1.Square(&u).Mul(&tv1, &c1) - tv2.Add(&one, &tv1) - tv1.Sub(&one, &tv1) - tv3.Mul(&tv2, &tv1).Inverse(&tv3) - tv4.Mul(&u, &tv1) - tv4.Mul(&tv4, &tv3) - tv4.Mul(&tv4, &c3) - x1.Sub(&c2, &tv4) - gx1.Square(&x1) - // 12. gx1 = gx1 + A - gx1.Mul(&gx1, &x1) - gx1.Add(&gx1, &bCurveCoeff) - e1 := gx1.Legendre() - x2.Add(&c2, &tv4) - gx2.Square(&x2) - // 18. gx2 = gx2 + A - gx2.Mul(&gx2, &x2) - gx2.Add(&gx2, &bCurveCoeff) - e2 := gx2.Legendre() - e1 // 2 if is_square(gx2) AND NOT e1 - x3.Square(&tv2) - x3.Mul(&x3, &tv3) - x3.Square(&x3) - x3.Mul(&x3, &c4) - x3.Add(&x3, &z) - if e1 == 1 { - x.Set(&x1) - } else { - x.Set(&x3) - } - if e2 == 2 { - x.Set(&x2) - } - gx.Square(&x) - // gx = gx + A - gx.Mul(&gx, &x) - gx.Add(&gx, &bCurveCoeff) - y.Sqrt(&gx) - e3 := sign0(u) && sign0(y) - if !e3 { - y.Neg(&y) + + tv1.Square(&u) // 1. tv1 = u² + tv1.Mul(&tv1, &c1) // 2. tv1 = tv1 * c1 + tv2.Add(&one, &tv1) // 3. tv2 = 1 + tv1 + tv1.Sub(&one, &tv1) // 4. tv1 = 1 - tv1 + tv3.Mul(&tv1, &tv2) // 5. tv3 = tv1 * tv2 + + tv3.Inverse(&tv3) // 6. tv3 = inv0(tv3) + tv4.Mul(&u, &tv1) // 7. tv4 = u * tv1 + tv4.Mul(&tv4, &tv3) // 8. tv4 = tv4 * tv3 + tv4.Mul(&tv4, &c3) // 9. tv4 = tv4 * c3 + x1.Sub(&c2, &tv4) // 10. x1 = c2 - tv4 + + gx1.Square(&x1) // 11. gx1 = x1² + //12. gx1 = gx1 + A + gx1.Mul(&gx1, &x1) // 13. gx1 = gx1 * x1 + gx1.Add(&gx1, &bCurveCoeff) // 14. gx1 = gx1 + B + gx1NotSquare = gx1.Legendre() >> 1 // 15. e1 = is_square(gx1) + // gx1NotSquare = 0 if gx1 is a square, -1 otherwise + + x2.Add(&c2, &tv4) // 16. x2 = c2 + tv4 + gx2.Square(&x2) // 17. gx2 = x2² + // 18. gx2 = gx2 + A + gx2.Mul(&gx2, &x2) // 19. gx2 = gx2 * x2 + gx2.Add(&gx2, &bCurveCoeff) // 20. gx2 = gx2 + B + + { + gx2NotSquare := gx2.Legendre() >> 1 // gx2Square = 0 if gx2 is a square, -1 otherwise + gx1SquareOrGx2Not = gx2NotSquare | ^gx1NotSquare // 21. e2 = is_square(gx2) AND NOT e1 # Avoid short-circuit logic ops } - res.X.Set(&x) - res.Y.Set(&y) - return res + x3.Square(&tv2) // 22. x3 = tv2² + x3.Mul(&x3, &tv3) // 23. x3 = x3 * tv3 + x3.Square(&x3) // 24. x3 = x3² + x3.Mul(&x3, &c4) // 25. x3 = x3 * c4 + + x3.Add(&x3, &Z) // 26. x3 = x3 + Z + x.Select(gx1NotSquare, &x1, &x3) // 27. x = CMOV(x3, x1, e1) # x = x1 if gx1 is square, else x = x3 + // Select x1 iff gx1 is square iff gx1NotSquare = 0 + x.Select(gx1SquareOrGx2Not, &x2, &x) // 28. x = CMOV(x, x2, e2) # x = x2 if gx2 is square and gx1 is not + // Select x2 iff gx2 is square and gx1 is not, iff gx1SquareOrGx2Not = 0 + gx.Square(&x) // 29. gx = x² + // 30. gx = gx + A + + gx.Mul(&gx, &x) // 31. gx = gx * x + gx.Add(&gx, &bCurveCoeff) // 32. gx = gx + B + + y.Sqrt(&gx) // 33. y = sqrt(gx) + signsNotEqual := sign0(u) ^ sign0(y) // 34. e3 = sgn0(u) == sgn0(y) + + tv1.Neg(&y) + y.Select(int(signsNotEqual), &y, &tv1) // 35. y = CMOV(-y, y, e3) # Select correct sign of y + return G1Affine{x, y} } // MapToG1 maps an fp.Element to a point on the curve using the Shallue and van de Woestijne map // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-2.2.1 -// TODO: Get rid of this? func MapToG1(t fp.Element) G1Affine { - return svdwMapG1(t) + return mapToCurve1(t) } // EncodeToG1 maps an fp.Element to a point on the curve using the Shallue and van de Woestijne map @@ -122,9 +134,10 @@ func HashToG1(msg, dst []byte) (G1Affine, error) { return res, nil } -// returns false if u>-u when seen as a bigInt -func sign0(u fp.Element) bool { - return !u.LexicographicallyLargest() +func sign0(u fp.Element) uint64 { + x := u + x.FromMont() + return x[0] % 2 } // hashToFp hashes msg to count prime field elements. diff --git a/ecc/bn254/hash_to_g1_test.go b/ecc/bn254/hash_to_g1_test.go new file mode 100644 index 0000000000..9622795e4f --- /dev/null +++ b/ecc/bn254/hash_to_g1_test.go @@ -0,0 +1,114 @@ +package bn254 + +import ( + "github.com/consensys/gnark-crypto/ecc/bn254/fp" + "testing" +) + +func TestHashToFpG1Vectors(t *testing.T) { + for _, c := range encodeToG1Vector.cases { + elems, err := hashToFp([]byte(c.msg), encodeToG1Vector.dst, 1) + if err != nil { + t.Error(err) + } + g1TestMatchCoord(t, "u", c.msg, c.u, &elems[0]) + } + + for _, c := range hashToG1Vector.cases { + elems, err := hashToFp([]byte(c.msg), hashToG1Vector.dst, 2) + if err != nil { + t.Error(err) + } + g1TestMatchCoord(t, "u0", c.msg, c.u0, &elems[0]) + g1TestMatchCoord(t, "u1", c.msg, c.u1, &elems[1]) + } +} + +func TestMapToG1Vectors(t *testing.T) { + for _, c := range encodeToG1Vector.cases { + var u fp.Element + u.SetString(c.u) + q := mapToCurve1(u) + g1TestMatchPoint(t, "Q", c.msg, c.Q, &q) + } + + for _, c := range hashToG1Vector.cases { + var u fp.Element + u.SetString(c.u0) + q := mapToCurve1(u) + g1TestMatchPoint(t, "Q0", c.msg, c.Q0, &q) + + u.SetString(c.u1) + q = mapToCurve1(u) + g1TestMatchPoint(t, "Q1", c.msg, c.Q1, &q) + } +} + +func TestEncodeToG1Vectors(t *testing.T) { + for _, c := range encodeToG1Vector.cases { + p, err := EncodeToG1([]byte(c.msg), encodeToG1Vector.dst) + if err != nil { + t.Fatal(err) + } + g1TestMatchPoint(t, "P", c.msg, c.P, &p) + } +} + +func TestHashToG1Vectors(t *testing.T) { + for _, c := range hashToG1Vector.cases { + p, err := HashToG1([]byte(c.msg), hashToG1Vector.dst) + if err != nil { + t.Fatal(err) + } + g1TestMatchPoint(t, "P", c.msg, c.P, &p) + } +} + +func g1TestMatchCoord(t *testing.T, coordName string, msg string, expectedStr string, seen *fp.Element) { + var expected fp.Element + + expected.SetString(expectedStr) + + if !expected.Equal(seen) { + t.Errorf("mismatch on \"%s\", %s:\n\texpected %s\n\tsaw 0x%s", msg, coordName, expectedStr, seen.Text(16)) + } +} + +func g1TestMatchPoint(t *testing.T, pointName string, msg string, expected point, seen *G1Affine) { + g1TestMatchCoord(t, pointName+".x", msg, expected.x, &seen.X) + g1TestMatchCoord(t, pointName+".y", msg, expected.y, &seen.Y) +} + +type hashTestVector struct { + dst []byte + cases []hashTestCase +} + +type encodeTestVector struct { + dst []byte + cases []encodeTestCase +} + +type point struct { + x string + y string +} + +type encodeTestCase struct { + msg string + P point //pY a coordinate of P, the final output + u string //u hashed onto the field + Q point //Q map to curve output +} + +type hashTestCase struct { + msg string + P point //pY a coordinate of P, the final output + u0 string //u0 hashed onto the field + u1 string //u1 extra hashed onto the field + Q0 point //Q0 map to curve output + Q1 point //Q1 extra map to curve output +} + +var hashToG1Vector hashTestVector +var encodeToG1Vector encodeTestVector diff --git a/ecc/bn254/hash_to_g2.go b/ecc/bn254/hash_to_g2.go index 413b01c3df..8f55c28321 100644 --- a/ecc/bn254/hash_to_g2.go +++ b/ecc/bn254/hash_to_g2.go @@ -15,80 +15,94 @@ package bn254 import ( + "github.com/consensys/gnark-crypto/ecc/bn254/fp" "github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower" ) -// https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-4.1 +// https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-hash-to-curve-14#appendix-F.1 // Shallue and van de Woestijne method, works for any elliptic curve in Weierstrass curve -func svdwMapG2(u fptower.E2) G2Affine { +func mapToCurve2(u fptower.E2) G2Affine { + var tv1, tv2, tv3, tv4 fptower.E2 + var x1, x2, x3, gx1, gx2, gx, x, y fptower.E2 + var one fptower.E2 + var gx1NotSquare, gx1SquareOrGx2Not int - var res G2Affine + //constants + //c1 = g(Z) + //c2 = -Z / 2 + //c3 = sqrt(-g(Z) * (3 * Z² + 4 * A)) # sgn0(c3) MUST equal 0 + //c4 = -4 * g(Z) / (3 * Z² + 4 * A) + + var Z, c1, c2, c3, c4 fptower.E2 + Z.A0.SetString("1") + c1.A0.SetString("19485874751759354771024239261021720505790618469301721065564631296452457478374") + c1.A1.SetString("266929791119991161246907387137283842545076965332900288569378510910307636690") + c2.A0.SetString("10944121435919637611123202872628637544348155578648911831344518947322613104291") + c3.A0.SetString("18992192239972082890849143911285057164064277369389217330423471574879236301292") + c3.A1.SetString("21819008332247140148575583693947636719449476128975323941588917397607662637108") + c4.A0.SetString("10499238450719652342378357227399831140106360636427411350395554762472100376473") + c4.A1.SetString("6940174569119770192419592065569379906172001098655407502803841283667998553941") - // constants - // sage script to find z: https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#appendix-E.1 - var z, c1, c2, c3, c4 fptower.E2 - z.A1.SetString("1") - c1.A0.SetString("19485874751759354771024239261021720505790618469301721065564631296452457478373") - c1.A1.SetString("266929791119991161246907387137283842545076965332900288569378510910307636689") - c2.A1.SetString("10944121435919637611123202872628637544348155578648911831344518947322613104291") - c3.A0.SetString("13617985070220897759416741581922326973608167195618746963957740978229330444385") - c3.A1.SetString("6485072654231349560354894037339044590945718224403932749563131108378844487223") - c4.A0.SetString("18685085378399381287283517099609868978155387573303020199856495763721534568303") - c4.A1.SetString("355906388159988214995876516183045123393435953777200384759171347880410182252") - - var tv1, tv2, tv3, tv4, one, x1, gx1, x2, gx2, x3, x, gx, y fptower.E2 one.SetOne() - tv1.Square(&u).Mul(&tv1, &c1) - tv2.Add(&one, &tv1) - tv1.Sub(&one, &tv1) - tv3.Mul(&tv2, &tv1).Inverse(&tv3) - tv4.Mul(&u, &tv1) - tv4.Mul(&tv4, &tv3) - tv4.Mul(&tv4, &c3) - x1.Sub(&c2, &tv4) - gx1.Square(&x1) - // 12. gx1 = gx1 + A - gx1.Mul(&gx1, &x1) - gx1.Add(&gx1, &bTwistCurveCoeff) - e1 := gx1.Legendre() - x2.Add(&c2, &tv4) - gx2.Square(&x2) - // 18. gx2 = gx2 + A - gx2.Mul(&gx2, &x2) - gx2.Add(&gx2, &bTwistCurveCoeff) - e2 := gx2.Legendre() - e1 // 2 if is_square(gx2) AND NOT e1 - x3.Square(&tv2) - x3.Mul(&x3, &tv3) - x3.Square(&x3) - x3.Mul(&x3, &c4) - x3.Add(&x3, &z) - if e1 == 1 { - x.Set(&x1) - } else { - x.Set(&x3) - } - if e2 == 2 { - x.Set(&x2) - } - gx.Square(&x) - // gx = gx + A - gx.Mul(&gx, &x) - gx.Add(&gx, &bTwistCurveCoeff) - y.Sqrt(&gx) - e3 := sign0(u.A0) && sign0(y.A0) - if !e3 { - y.Neg(&y) + + tv1.Square(&u) // 1. tv1 = u² + tv1.Mul(&tv1, &c1) // 2. tv1 = tv1 * c1 + tv2.Add(&one, &tv1) // 3. tv2 = 1 + tv1 + tv1.Sub(&one, &tv1) // 4. tv1 = 1 - tv1 + tv3.Mul(&tv1, &tv2) // 5. tv3 = tv1 * tv2 + + tv3.Inverse(&tv3) // 6. tv3 = inv0(tv3) + tv4.Mul(&u, &tv1) // 7. tv4 = u * tv1 + tv4.Mul(&tv4, &tv3) // 8. tv4 = tv4 * tv3 + tv4.Mul(&tv4, &c3) // 9. tv4 = tv4 * c3 + x1.Sub(&c2, &tv4) // 10. x1 = c2 - tv4 + + gx1.Square(&x1) // 11. gx1 = x1² + //12. gx1 = gx1 + A + gx1.Mul(&gx1, &x1) // 13. gx1 = gx1 * x1 + gx1.Add(&gx1, &bTwistCurveCoeff) // 14. gx1 = gx1 + B + gx1NotSquare = gx1.Legendre() >> 1 // 15. e1 = is_square(gx1) + // gx1NotSquare = 0 if gx1 is a square, -1 otherwise + + x2.Add(&c2, &tv4) // 16. x2 = c2 + tv4 + gx2.Square(&x2) // 17. gx2 = x2² + // 18. gx2 = gx2 + A + gx2.Mul(&gx2, &x2) // 19. gx2 = gx2 * x2 + gx2.Add(&gx2, &bTwistCurveCoeff) // 20. gx2 = gx2 + B + + { + gx2NotSquare := gx2.Legendre() >> 1 // gx2Square = 0 if gx2 is a square, -1 otherwise + gx1SquareOrGx2Not = gx2NotSquare | ^gx1NotSquare // 21. e2 = is_square(gx2) AND NOT e1 # Avoid short-circuit logic ops } - res.X.Set(&x) - res.Y.Set(&y) - return res + x3.Square(&tv2) // 22. x3 = tv2² + x3.Mul(&x3, &tv3) // 23. x3 = x3 * tv3 + x3.Square(&x3) // 24. x3 = x3² + x3.Mul(&x3, &c4) // 25. x3 = x3 * c4 + + x3.Add(&x3, &Z) // 26. x3 = x3 + Z + x.Select(gx1NotSquare, &x1, &x3) // 27. x = CMOV(x3, x1, e1) # x = x1 if gx1 is square, else x = x3 + // Select x1 iff gx1 is square iff gx1NotSquare = 0 + x.Select(gx1SquareOrGx2Not, &x2, &x) // 28. x = CMOV(x, x2, e2) # x = x2 if gx2 is square and gx1 is not + // Select x2 iff gx2 is square and gx1 is not, iff gx1SquareOrGx2Not = 0 + gx.Square(&x) // 29. gx = x² + // 30. gx = gx + A + + gx.Mul(&gx, &x) // 31. gx = gx * x + gx.Add(&gx, &bTwistCurveCoeff) // 32. gx = gx + B + + y.Sqrt(&gx) // 33. y = sqrt(gx) + signsNotEqual := g2Sgn0(&u) ^ g2Sgn0(&y) // 34. e3 = sgn0(u) == sgn0(y) + + tv1.Neg(&y) + y.Select(int(signsNotEqual), &y, &tv1) // 35. y = CMOV(-y, y, e3) # Select correct sign of y + return G2Affine{x, y} } // MapToG2 maps an Fp2 to a point on the curve using the Shallue and van de Woestijne map // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-2.2.1 func MapToG2(t fptower.E2) G2Affine { - res := svdwMapG2(t) + res := mapToCurve2(t) res.ClearCofactor(&res) return res } @@ -96,16 +110,14 @@ func MapToG2(t fptower.E2) G2Affine { // EncodeToG2 maps an Fp2 to a point on the curve using the Shallue and van de Woestijne map // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-2.2.2 func EncodeToG2(msg, dst []byte) (G2Affine, error) { - var res G2Affine _t, err := hashToFp(msg, dst, 2) if err != nil { - return res, err + return G2Affine{}, err } var t fptower.E2 t.A0.Set(&_t[0]) t.A1.Set(&_t[1]) - res = MapToG2(t) - return res, nil + return MapToG2(t), nil } // HashToG2 maps an Fp2 to a point on the curve using the Shallue and van de Woestijne map @@ -121,12 +133,47 @@ func HashToG2(msg, dst []byte) (G2Affine, error) { u0.A1.Set(&u[1]) u1.A0.Set(&u[2]) u1.A1.Set(&u[3]) - Q0 := MapToG2(u0) - Q1 := MapToG2(u1) + Q0 := mapToCurve2(u0) + Q1 := mapToCurve2(u1) var _Q0, _Q1, _res G2Jac _Q0.FromAffine(&Q0) _Q1.FromAffine(&Q1) _res.Set(&_Q1).AddAssign(&_Q0) + _res.ClearCofactor(&_res) res.FromJacobian(&_res) return res, nil } + +func g1NotZero(x *fp.Element) uint64 { + + return x[0] | x[1] | x[2] | x[3] + +} + +// g2Sgn0 is an algebraic substitute for the notion of sign in ordered fields +// Namely, every non-zero quadratic residue in a finite field of characteristic =/= 2 has exactly two square roots, one of each sign +// Taken from https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/ section 4.1 +// The sign of an element is not obviously related to that of its Montgomery form +func g2Sgn0(z *fptower.E2) uint64 { + + nonMont := *z + nonMont.FromMont() + + sign := uint64(0) + zero := uint64(1) + var signI uint64 + var zeroI uint64 + + signI = nonMont.A0[0] % 2 + sign = sign | (zero & signI) + + zeroI = g1NotZero(&nonMont.A0) + zeroI = 1 ^ (zeroI|-zeroI)>>63 + zero = zero & zeroI + + signI = nonMont.A1[0] % 2 + sign = sign | (zero & signI) + + return sign + +} diff --git a/ecc/bn254/hash_to_g2_test.go b/ecc/bn254/hash_to_g2_test.go new file mode 100644 index 0000000000..2204ff1eec --- /dev/null +++ b/ecc/bn254/hash_to_g2_test.go @@ -0,0 +1,101 @@ +package bn254 + +import ( + "github.com/consensys/gnark-crypto/ecc/bn254/internal/fptower" + "strings" + "testing" +) + +func TestHashToFpG2Vectors(t *testing.T) { + for _, c := range encodeToG2Vector.cases { + elems, err := hashToFp([]byte(c.msg), encodeToG2Vector.dst, 2) + if err != nil { + t.Error(err) + } + u := fptower.E2{A0: elems[0], A1: elems[1]} + g2TestMatchCoord(t, "u", c.msg, c.u, &u) + } + + for _, c := range hashToG2Vector.cases { + elems, err := hashToFp([]byte(c.msg), hashToG2Vector.dst, 4) + if err != nil { + t.Error(err) + } + u0 := fptower.E2{A0: elems[0], A1: elems[1]} + u1 := fptower.E2{A0: elems[2], A1: elems[3]} + + g2TestMatchCoord(t, "u0", c.msg, c.u0, &u0) + g2TestMatchCoord(t, "u1", c.msg, c.u1, &u1) + } +} + +func TestMapToG2Vectors(t *testing.T) { + for _, c := range encodeToG2Vector.cases { + var u fptower.E2 + g2CoordSetString(&u, c.u) + q := mapToCurve2(u) + g2TestMatchPoint(t, "Q", c.msg, c.Q, &q) + } + + for _, c := range hashToG2Vector.cases { + var u fptower.E2 + g2CoordSetString(&u, c.u0) + q := mapToCurve2(u) + g2TestMatchPoint(t, "Q0", c.msg, c.Q0, &q) + + g2CoordSetString(&u, c.u1) + q = mapToCurve2(u) + g2TestMatchPoint(t, "Q1", c.msg, c.Q1, &q) + } +} + +func TestEncodeToG2Vectors(t *testing.T) { + for _, c := range encodeToG2Vector.cases { + p, err := EncodeToG2([]byte(c.msg), encodeToG2Vector.dst) + if err != nil { + t.Fatal(err) + } + g2TestMatchPoint(t, "P", c.msg, c.P, &p) + } +} + +func TestHashToG2Vectors(t *testing.T) { + for _, c := range hashToG2Vector.cases { + p, err := HashToG2([]byte(c.msg), hashToG2Vector.dst) + if err != nil { + t.Fatal(err) + } + g2TestMatchPoint(t, "P", c.msg, c.P, &p) + } +} + +func g2TestMatchCoord(t *testing.T, coordName string, msg string, expectedStr string, seen *fptower.E2) { + var expected fptower.E2 + + g2CoordSetString(&expected, expectedStr) + + if !expected.Equal(seen) { + t.Errorf("mismatch on \"%s\", %s:\n\texpected %s\n\tsaw %s", msg, coordName, expected.String(), seen) + } +} + +func g2TestMatchPoint(t *testing.T, pointName string, msg string, expected point, seen *G2Affine) { + g2TestMatchCoord(t, pointName+".x", msg, expected.x, &seen.X) + g2TestMatchCoord(t, pointName+".y", msg, expected.y, &seen.Y) +} + +//Only works on simple extensions (two-story towers) +func g2CoordSetString(z *fptower.E2, s string) { + ssplit := strings.Split(s, ",") + if len(ssplit) != 2 { + panic("not equal to tower size") + } + z.SetString( + + ssplit[0], + ssplit[1], + ) +} + +var hashToG2Vector hashTestVector +var encodeToG2Vector encodeTestVector diff --git a/ecc/bn254/hash_vectors_test.go b/ecc/bn254/hash_vectors_test.go new file mode 100644 index 0000000000..21eebd7db4 --- /dev/null +++ b/ecc/bn254/hash_vectors_test.go @@ -0,0 +1,114 @@ +package bn254 + +func init() { + encodeToG1Vector = encodeTestVector{ + dst: []byte("QUUX-V01-CS02-with-BN254G1_XMD:SHA-256_SVDW_NU_"), + cases: []encodeTestCase{ + { + msg: "", P: point{"0x1bb8810e2ceaf04786d4efd216fc2820ddd9363712efc736ada11049d8af5925", "0x1efbf8d54c60d865cce08437668ea30f5bf90d287dbd9b5af31da852915e8f11"}, + Q: point{"0x1bb8810e2ceaf04786d4efd216fc2820ddd9363712efc736ada11049d8af5925", "0x1efbf8d54c60d865cce08437668ea30f5bf90d287dbd9b5af31da852915e8f11"}, + u: "0xcb81538a98a2e3580076eed495256611813f6dae9e16d3d4f8de7af0e9833e1", + }, { + msg: "abc", P: point{"0xda4a96147df1f35b0f820bd35c6fac3b80e8e320de7c536b1e054667b22c332", "0x189bd3fbffe4c8740d6543754d95c790e44cd2d162858e3b733d2b8387983bb7"}, + Q: point{"0xda4a96147df1f35b0f820bd35c6fac3b80e8e320de7c536b1e054667b22c332", "0x189bd3fbffe4c8740d6543754d95c790e44cd2d162858e3b733d2b8387983bb7"}, + u: "0xba35e127276e9000b33011860904ddee28f1d48ddd3577e2a797ef4a5e62319", + }, { + msg: "abcdef0123456789", P: point{"0x2ff727cfaaadb3acab713fa22d91f5fddab3ed77948f3ef6233d7ea9b03f4da1", "0x304080768fd2f87a852155b727f97db84b191e41970506f0326ed4046d1141aa"}, + Q: point{"0x2ff727cfaaadb3acab713fa22d91f5fddab3ed77948f3ef6233d7ea9b03f4da1", "0x304080768fd2f87a852155b727f97db84b191e41970506f0326ed4046d1141aa"}, + u: "0x11852286660cd970e9d7f46f99c7cca2b75554245e91b9b19d537aa6147c28fc", + }, { + msg: "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", P: point{"0x11a2eaa8e3e89de056d1b3a288a7f733c8a1282efa41d28e71af065ab245df9b", "0x60f37c447ac29fd97b9bb83be98ddccf15e34831a9cdf5493b7fede0777ae06"}, + Q: point{"0x11a2eaa8e3e89de056d1b3a288a7f733c8a1282efa41d28e71af065ab245df9b", "0x60f37c447ac29fd97b9bb83be98ddccf15e34831a9cdf5493b7fede0777ae06"}, + u: "0x174d1c85d8a690a876cc1deba0166d30569fafdb49cb3ed28405bd1c5357a1cc", + }, { + msg: "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", P: point{"0x27409dccc6ee4ce90e24744fda8d72c0bc64e79766f778da0c1c0ef1c186ea84", "0x1ac201a542feca15e77f30370da183514dc99d8a0b2c136d64ede35cd0b51dc0"}, + Q: point{"0x27409dccc6ee4ce90e24744fda8d72c0bc64e79766f778da0c1c0ef1c186ea84", "0x1ac201a542feca15e77f30370da183514dc99d8a0b2c136d64ede35cd0b51dc0"}, + u: "0x73b81432b4cf3a8a9076201500d1b94159539f052a6e0928db7f2df74bff672", + }, + }} + hashToG1Vector = hashTestVector{ + dst: []byte("QUUX-V01-CS02-with-BN254G1_XMD:SHA-256_SVDW_RO_"), + cases: []hashTestCase{ + { + msg: "", P: point{"0xa976ab906170db1f9638d376514dbf8c42aef256a54bbd48521f20749e59e86", "0x2925ead66b9e68bfc309b014398640ab55f6619ab59bc1fab2210ad4c4d53d5"}, + Q0: point{"0xe449b959abbd0e5ab4c873eaeb1ccd887f1d9ad6cd671fd72cb8d77fb651892", "0x29ff1e36867c60374695ee0c298fcbef2af16f8f97ed356fa75e61a797ebb265"}, + Q1: point{"0x19388d9112a306fba595c3a8c63daa8f04205ad9581f7cf105c63c442d7c6511", "0x182da356478aa7776d1de8377a18b41e933036d0b71ab03f17114e4e673ad6e4"}, + u0: "0x2f87b81d9d6ef05ad4d249737498cc27e1bd485dca804487844feb3c67c1a9b5", u1: "0x6de2d0d7c0d9c7a5a6c0b74675e7543f5b98186b5dbf831067449000b2b1f8e", + }, { + msg: "abc", P: point{"0x23f717bee89b1003957139f193e6be7da1df5f1374b26a4643b0378b5baf53d1", "0x4142f826b71ee574452dbc47e05bc3e1a647478403a7ba38b7b93948f4e151d"}, + Q0: point{"0x1452c8cc24f8dedc25b24d89b87b64e25488191cecc78464fea84077dd156f8d", "0x209c3633505ba956f5ce4d974a868db972b8f1b69d63c218d360996bcec1ad41"}, + Q1: point{"0x4e8357c98524e6208ae2b771e370f0c449e839003988c2e4ce1eaf8d632559f", "0x4396ec43dd8ec8f2b4a705090b5892219759da30154c39490fc4d59d51bb817"}, + u0: "0x11945105b5e3d3b9392b5a2318409cbc28b7246aa47fa30da5739907737799a9", u1: "0x1255fc9ad5a6e0fb440916f091229bda611c41be2f2283c3d8f98c596be4c8c9", + }, { + msg: "abcdef0123456789", P: point{"0x187dbf1c3c89aceceef254d6548d7163fdfa43084145f92c4c91c85c21442d4a", "0xabd99d5b0000910b56058f9cc3b0ab0a22d47cf27615f588924fac1e5c63b4d"}, + Q0: point{"0x28d01790d2a1cc4832296774438acd46c2ce162d03099926478cf52319daba8d", "0x10227ab2707fd65fb45e87f0a48cfe3556f04113d27b1da9a7ae1709007355e1"}, + Q1: point{"0x7dc256c7aadac1b4e1d23b3b2bbb5e2ffd9c753b9073d8d952ead8f812ce1b3", "0x2589008b2e15dcb3d16cdc1fed2634778001b1b28f0ab433f4f5ec6635c55e1e"}, + u0: "0x2f7993a6b43a8dbb37060e790011a888157f456b895b925c3568690685f4983d", u1: "0x2677d0532b47a4cead2488845e7df7ebc16c0b8a2cd8a6b7f4ce99f51659794e", + }, { + msg: "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", P: point{"0xfe2b0743575324fc452d590d217390ad48e5a16cf051bee5c40a2eba233f5c", "0x794211e0cc72d3cbbdf8e4e5cd6e7d7e78d101ff94862caae8acbe63e9fdc78"}, + Q0: point{"0x1c53b05f2fce15ba0b9100650c0fb46de1fb62f1d0968b69151151bd25dfefa4", "0x1fe783faf4bdbd79b717784dc59619106e4acccfe3b5d9750799729d855e7b81"}, + Q1: point{"0x214a4e6e97adda47558f80088460eabd71ed35bc8ceafb99a493dd6f4e2b3f0a", "0xfaaeb29cc23f9d09b187a99741613aed84443e7c35736258f57982d336d13bd"}, + u0: "0x2a50be15282ee276b76db1dab761f75401cdc8bd9fff81fcf4d428db16092a7b", u1: "0x23b41953676183c30aca54b5c8bd3ffe3535a6238c39f6b15487a5467d5d20eb", + }, { + msg: "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", P: point{"0x1b05dc540bd79fd0fea4fbb07de08e94fc2e7bd171fe025c479dc212a2173ce", "0x1bf028afc00c0f843d113758968f580640541728cfc6d32ced9779aa613cd9b0"}, + Q0: point{"0x2298ba379768da62495af6bb390ffca9156fde1dc167235b89c6dd008d2f2f3b", "0x660564cf6fce5cdea4780f5976dd0932559336fd072b4ddd83ec37f00fc7699"}, + Q1: point{"0x2811dea430f7a1f6c8c941ecdf0e1e725b8ad1801ad15e832654bd8f10b62f16", "0x253390ed4fb39e58c30ca43892ab0428684cfb30b9df05fc239ab532eaa02444"}, + u0: "0x48527470f534978bae262c0f3ba8380d7f560916af58af9ad7dcb6a4238e633", u1: "0x19a6d8be25702820b9b11eada2d42f425343889637a01ecd7672fbcf590d9ffe", + }, + }} + encodeToG2Vector = encodeTestVector{ + dst: []byte("QUUX-V01-CS02-with-BN254G2_XMD:SHA-256_SVDW_NU_"), + cases: []encodeTestCase{ + { + msg: "", P: point{"0x4e9ea7f5807198397a99e234e91d4b9e6cadf0135ebedd97fd75cffed6e994d,0x70077acfda8443392fb30222ba96b63f4b734e678494bf4ed0e07074b440a7b", "0x2d3653bf41ec170ce2d48774d02393c8d5f60fee5690b4f8cbc8531e269227f9,0xa7cf5d0d356f0c4d163570209e5f8f749bf91dc2a7d9ba58199a95ce02242b4"}, + Q: point{"0x1aff45b8bec4d8c0b48638acd6aa6886d9c0202c8f415061673ec4a1eb520af6,0x19abe65fd87b71da2f78347494f28418dee2f1b75956f0dddc4efb98837e325d", "0x1f01deb60bef6c08b36bb2cb465efdd20b597532e05a27c45034a729f8fe8f59,0x2e76aede179fdb62bdba78c6f28566f68aa721f3220a853b65c79f135e427ef7"}, + u: "0x5952a51e848675c06172da425edc1c471c11db4bc51cfb84c097bdbcf22b6b5,0x4f8c1f037b231d08ea68f3e23b8e3c708d3993a1577d1bcfc92c2392a82c47e", + }, { + msg: "abc", P: point{"0x101e2f3d9fa22cb435ecb67d5284dc27c247856d6de4e420e1812e0bcea5afd8,0x29226a3ca7415a541599274bf9e805050c82d443fd953481b17236325be3b6b7", "0x290bf12841dd276211effe86af369c11a2cb364c443981d0faf347cfb7b68715,0x2e7c8a61fe36735852597ac564966560afe0ef8221918d5534e57f3096f7047d"}, + Q: point{"0x2216ec5165748117d5aecf12f1eff5f6380367163e351d591f5de9aebfe5f82e,0x2dc39518b60217999eadc27840962dd62ffb38e7d7e6c72a208206e6b2c07028", "0xb424f1cc74e01e0d61084ecfb3785bc8a66443d99be786c387a4d5e1ad91832,0xbb538ea60a53b3c933726e61a57e753a8919a75d8c600f8f6af6bbf460a57ee"}, + u: "0x25f701986d04721d21b118002eeaad1b8ecc8de722d4d8e7ad5f060518ea5c7c,0xf05f22acfb3bf7abb1f8f1b80e0de029a20a2b96c6eefa2f371431bbfca04a3", + }, { + msg: "abcdef0123456789", P: point{"0xfcda542dd52f0e527bf828e63fe2a1f63a05c9a5c7a28865cfef247c6e1e8a6,0x2d0bb492bb59847c106af8285fae5be0b5f96b6dcad56b3a0c7ddc364ae55a3a", "0x172d50b483e9bb9aa230e7cb82fbd522af1b73c1643bbd022614533311071780,0xafb68b6e28f44f49d6ab4c3014e73f7e07fd4d0b13a9519b798e9f1927a47b9"}, + Q: point{"0x1f3620223ed7115c479ed1150b509886c8ecf7411e004e943f544829ed3fc56f,0x3063a2d037058a1ff49edba42f2f78d3fdd03e592bd3df415d04176ba269c7c7", "0x1d1a9b20266ba09a594e299ca4c9e27564218986669d1fa90566764f5a8ac63a,0x7f48bbaf8c038ad3a2167a9e43e583a73d6a88795e574c4e26834fbcf2bb44b"}, + u: "0xeb05b113763043309faadf3c004ac0eb40f948faed5d83d4d1f0571112ca09c,0x1730924259ae2e94ae7ee719c1eeb5d6328b6963819ee4065541dfdefb5e7a07", + }, { + msg: "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", P: point{"0x1d050758368c65df07014cab4752d8244ddf21691ab6418a3493bcc2a946b38d,0x2596aa6bcb29439a9cdc7cfe0b9d247a890a4295dc17d053c293c7e40c27387f", "0x2f84eec5eaa87952d0d81c93c3f470c1e1a00d0ba307d8fda78b76841aca8e82,0x27aef639d6eb4157c6f076e9fdae2f9eb15042dea92304fc54ebd5f69c5c3443"}, + Q: point{"0x1db4c6c448341a408bd60ebf8d19bfc149927dbd5af0af598d4c6d2f1629bd8a,0x2d61dff76daa91b0044f83074f4c841e0bbf3711f5b8a7ac8e0618b29fce6d92", "0x1dedea44e27ea061f38fd062e2b1c6d93db96a32cf5a214da49f39eeeb803791,0x113a4cf8a33642670164f11b2ef257f6653ae8045ac58fc172f022f3f8107c4a"}, + u: "0x47b36a3ec43c92ae9070ef71f85016bd5a08c1bd0ca487672f176061ca09159,0x248076a8b63f52e5f3c7228411637e04cbd0cb36940ee3a257f60ce49e75fe86", + }, { + msg: "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", P: point{"0x13729abbd4fbe2a13bc742960afa9053a4e6be06ea712b0d18153a9ec3854a7,0x261e8ebaff3438064599465bb52880e8e8a663b27cfb6d794d90ac60437819a9", "0x132285a30dc36cc14da2d145390a6328e574155ebaece32856fb890d1f7ba16e,0x6bd9197b3c0c1cc4d17695042dcbaf0168329a113d358c3b17885f71a394986"}, + Q: point{"0x2376cb494d599bbe8523817d9702f0da6e6e0ba7f321dcccb720cd5696f57de7,0x2228f04e096f6802387d0d40b3b575afd66281de5d734b33da09fbb86cef5a1a", "0x17332e7ce9faf26d7f5c5cf247ea51f48594238faeb0be338462895016da6738,0xcbd6f12f78c47d3f46238782e5d297ab15a1b8f5c065a8ba52620c16d555fa0"}, + u: "0x2f3b24a712fbb1272e51db197d666cdad2cc94c2a6e7b77d99e97d8a705a8a50,0x253bcb542b718219fe2f6de276c6d86965d610b3e66bd0448576db18e1e9ab3f", + }, + }} + hashToG2Vector = hashTestVector{ + dst: []byte("QUUX-V01-CS02-with-BN254G2_XMD:SHA-256_SVDW_RO_"), + cases: []hashTestCase{ + { + msg: "", P: point{"0x1192005a0f121921a6d5629946199e4b27ff8ee4d6dd4f9581dc550ade851300,0x1747d950a6f23c16156e2171bce95d1189b04148ad12628869ed21c96a8c9335", "0x498f6bb5ac309a07d9a8b88e6ff4b8de0d5f27a075830e1eb0e68ea318201d8,0x2c9755350ca363ef2cf541005437221c5740086c2e909b71d075152484e845f4"}, + Q0: point{"0x71e460ff150e978d833ef69fdf228f0d2c0807e3dce076b17dccdaa64bf6b25,0xab3b378f44776bd951140bfc354e68554ca76a4369a6b20d0da39e18e31fa38", "0x2c6cdc66602f181b70022028cd584f9d021eb409af5bfcef716a180383140aaf,0x113b1e8168192dc9a8048152b61aab936ce3654bf5f67d3d63f53d4eee72e011"}, + Q1: point{"0x39f9c639d9261f6d96487bae68e2336ba7ed68af727960c371caa330f0f3c05,0x1bf10eb5452db5be04eb3469440f9008017f1c632252b13069a3a9aa6c7467ec", "0x229827ca645e88cccdf70f001f3051f4148bcbc1165796f8550ef055a211d685,0x4ffb54e9e9f23b1c84d262f273518f14a8873f4589d2227575d5c65141da706"}, + u0: "0x2c85988ecf26034a6d6c495c467150aeaead51fceb623aa99b0433275c8952c7,0x182126b31e6df7cf33844bf16a92f42072ee47f80539dace68dbfc3380d1fcbd", u1: "0x1c3035901eab4768d522b3d0eb7e58b05c130603c8f43587345dc51745fa3533,0x23597b1c4f238038ba6579d203e7fcb7d427c63d4e0d037185453168718203bb", + }, { + msg: "abc", P: point{"0x16c88b54eec9af86a41569608cd0f60aab43464e52ce7e6e298bf584b94fccd2,0xb5db3ca7e8ef5edf3a33dfc3242357fbccead98099c3eb564b3d9d13cba4efd", "0x1c42ba524cb74db8e2c680449746c028f7bea923f245e69f89256af2d6c5f3ac,0x22d02d2da7f288545ff8789e789902245ab08c6b1d253561eec789ec2c1bd630"}, + Q0: point{"0x254d44345e73654a4a41adc0b17f39b397c352693513b3439afe5596cba3c6b2,0x2d489087e8025d60a201c109bd6be0aac5e8b04593c1127e4f8cf9e654dd1f82", "0xf1b1989fb5b87287ba1eee6b04426b1b3afb72c0aa8e981e392e740c0b2045,0x20d48c7925d6e00cf89487c737f49a0b5946158ca515fcc12516aefd33f9a45b"}, + Q1: point{"0x1af57e1f34420bf4fc5d2d880fd69f8c58b0ff2647b9d8b3d98f03fe45300ae8,0x164ff536dd42039dbd2f6351f445cd76cb1a346ea1347cfd98500ec62996c94d", "0x304eeaafb7429b8fe754a567cf23c0d04be055baeb0e9a3a6d34e433f3aa8027,0x168b97f3e2a1bbe114931e35f3abd3614f99a58abb4ae0adda944c09d1bdc0e6"}, + u0: "0x234b244ed36d5acbb96a4f5fb67094945a0bb4ecf33d55bcc218ce834dc82c63,0x4ca11f51d0cf7e7393a0e6d7be3d0e6b07652d5ba308554a72dafe502dd59cc", u1: "0x1c31ec87881353ec57fc87c27e31099a0705390c52dbfc8c047d14260658df71,0x2daa8e05eb3367285b5de508d248b3153207498f3e9e51cbe6183ff7dae286a6", + }, { + msg: "abcdef0123456789", P: point{"0x1435fd84aa43c699230e371f6fea3545ce7e053cbbb06a320296a2b81efddc70,0x2a8a360585b6b05996ef69c3c09b2c6fb17afe2b1e944f07559c53178eabf171", "0x2820188dcdc13ffdca31694942418afa1d6dfaaf259d012fab4da52b0f592e38,0x142f08e2441ec431defc24621b73cfe0252d19b243cb55b84bdeb85de039207a"}, + Q0: point{"0x100476fddb9ea779a6fb6d42e56309214d17e9f977e55817d90d174c25da1da,0x119928ea6db28a02b97ffd78ca301352f59bf218283c4636ffd8630424d715f2", "0x1f8b75179bb45ec7dce4e80a6e5ff343354405fb37e0f00f05b6bd4576fe7325,0x217dc1c62afca9b764d6aad37652d2ceca98082e8a91278665fc69aa1086f42c"}, + Q1: point{"0x2eea8de62a9fe65f771b334f09895a941513447befc908c9bd92e379413f705,0x2116b794a45df430772983535769ee30a6b16383f402a45bfd061091423771c4", "0x1a236124a4be9b04860439e8ca5ff9c2b7309473b2235193befcd61c9e911b88,0x2abc966940a34cdd457e0505ea3884e90a804cee8b01b510f319fb5f5447c90c"}, + u0: "0x29c7f821157ab18e589d1e7d7bd393d20aff69af2ac4deadc7950998d594d201,0x860010a5c2ae9289f0d4f7099ff0d5904ded06f99d5960f734de36b82ff983c", u1: "0x1f3c50c3ccfbaad8e81f8a765c5465a034b55fb873be48fd60dc21fb2cca98b8,0x2fa095cba1059ef5e2d5ea1c976a87f4530225aa7759b5b9510bb76d7b1d4f3", + }, { + msg: "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", P: point{"0x2cffc213fb63d00d923cb22cda5a2904837bb93a2fe6e875c532c51744388341,0x2718ef38d1bc4347f0266c774c8ef4ee5fa7056cc27a4bd7ecf7a888efb95b26", "0x232553f728341afa64ce66d00535764557a052e38657594e10074ad28728c584,0x2206ec0a9288f31ed78531c37295df3b56c42a1284443ee9893adb1521779001"}, + Q0: point{"0xc18ed8f507c46c91c3cd68bbe67d84fedddf54aa36a0b724d8993c0e89d3473,0x216fd51ee739a5ea4bea5e0d02e3217399e001a1b1192494cad83778b265bf51", "0x86feb20cd348a7f6b10395367f6a94a7c0b6be76673ab847914302cfbef4c8d,0x184f467bdb87df3cf3616b88a2dfd4eb512627a8e7cb00ac4c0f0c256948693d"}, + Q1: point{"0x2ab06564fee17a6d71b4cb24b73798d44711fdd101f6368fdc53e34fb2a3e411,0x1924dbd030b8093ac48e7363505d25c53cb0a21f96d5d2e6c534b8e541c2f332", "0x89c25648c64971fc868a1c5ca178e336147f26d2984221ed1df72b2c1b49b1,0xaf10b749194f436828978b2428c7944d46f8fb8bc34461794bc1bc1d636003a"}, + u0: "0x859e4f9b60f7ce13f81da9da46435c8827ed53f553b4e1804a395af1354b2c7,0x368bfd8f29d990293171aee9be3bc4ad623c54d0db776d0fe87cfd579059a86", u1: "0x103aa84a49f14d0ca1dfda47fa93a43cece0c267ae8799123d63ccd027772f71,0x9ebcb7d529f69c5e7ab096ff1a727ec8bc6c5214ed1784cd7f9e325e121640c", + }, { + msg: "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", P: point{"0x242a0a159f36f87065e7c5170426012087023165ce47a486e53d6e2845ca625a,0x17f9f6292998cf18ccc155903c1fe6b6465d40c794a3e1ed644a4182ad639f4a", "0x2dc5b7b65c9c79e6ef4afab8fbe3083c66d4ce31c78f6621ece17ecc892cf4b3,0x18ef4886c818f01fdf309bc9a46dd904273917f85e74ecd0de62460a68122037"}, + Q0: point{"0x14909a7cf12c368a1ecf7dde981bee058f657b6c47aa2d8bbd0528afac6dbd7b,0x3691ff7c610402d3acc2494c72a2a8eb7b34f40f54953201ce87f6c1b0f4bee", "0x1b4f9ced14ace59a4469280f4ad25c2727cca98c74729f4491bbcd9e3c4ec65f,0x26616d464461190482f9583225c483a6df9a7c9bf76bef2c0f02f7b08913cda5"}, + Q1: point{"0x21641581efa27adfd51aa8605a6e5763c563d929e8157508387bb76239446dbc,0x2edc55e80aa268be53526cb82df2eea5aba8595c258b0da6b91e3798d1b901c5", "0x2e3312775b7af85c4acb0a67fcf5e0a7ea163dd6dae35021d97851dfa9778af4,0xe8d867d428e160f1597b1096f9c492519d9d5e663a4af02f20f272d589804cc"}, + u0: "0xf0a229a329e3df7fe4feea02aac7dad3a01d345f65efe512544699439aacd83,0x15b85241a3f8790e550026f37fd861babd3dba9e2bce0deced2df56f7440bbb4", u1: "0xfa59525a85744763ea88a78ca612cb8db4d6e08f3d192568749b90ef16c36b6,0x1c32e85696693c537a91a4283353fba8c24f4107278b82990cc0c595a4d4f6cc", + }, + }} +} diff --git a/ecc/bw6-633/g1.go b/ecc/bw6-633/g1.go index d30451a023..1cee4c015a 100644 --- a/ecc/bw6-633/g1.go +++ b/ecc/bw6-633/g1.go @@ -66,7 +66,7 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) @@ -77,7 +77,7 @@ func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) diff --git a/ecc/bw6-633/g2.go b/ecc/bw6-633/g2.go index 79d0e48a70..b497d88173 100644 --- a/ecc/bw6-633/g2.go +++ b/ecc/bw6-633/g2.go @@ -61,7 +61,7 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) @@ -72,7 +72,7 @@ func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) diff --git a/ecc/bw6-633/hash_to_g1.go b/ecc/bw6-633/hash_to_g1.go index c42bed7c5b..08212cb9fe 100644 --- a/ecc/bw6-633/hash_to_g1.go +++ b/ecc/bw6-633/hash_to_g1.go @@ -181,9 +181,9 @@ func g1MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG1 implements the SSWU map -// No cofactor clearing -func sswuMapG1(u *fp.Element) G1Affine { +// mapToCurve1 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve1(u *fp.Element) G1Affine { var tv1 fp.Element tv1.Square(u) @@ -255,7 +255,7 @@ func sswuMapG1(u *fp.Element) G1Affine { // MapToG1 invokes the SSWU map, and guarantees that the result is in g1 func MapToG1(u fp.Element) G1Affine { - res := sswuMapG1(&u) + res := mapToCurve1(&u) //this is in an isogenous curve g1Isogeny(&res) res.ClearCofactor(&res) @@ -274,7 +274,7 @@ func EncodeToG1(msg, dst []byte) (G1Affine, error) { return res, err } - res = sswuMapG1(&u[0]) + res = mapToCurve1(&u[0]) //this is in an isogenous curve g1Isogeny(&res) @@ -292,8 +292,8 @@ func HashToG1(msg, dst []byte) (G1Affine, error) { return G1Affine{}, err } - Q0 := sswuMapG1(&u[0]) - Q1 := sswuMapG1(&u[1]) + Q0 := mapToCurve1(&u[0]) + Q1 := mapToCurve1(&u[1]) //TODO: Add in E' first, then apply isogeny g1Isogeny(&Q0) diff --git a/ecc/bw6-633/hash_to_g1_test.go b/ecc/bw6-633/hash_to_g1_test.go index f77f67c4e9..be9dd0c476 100644 --- a/ecc/bw6-633/hash_to_g1_test.go +++ b/ecc/bw6-633/hash_to_g1_test.go @@ -107,7 +107,7 @@ func TestG1SSWU(t *testing.T) { properties.Property("[G1] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG1(&a) + g := mapToCurve1(&a) if !isOnEPrimeG1(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bw6-633/hash_to_g2.go b/ecc/bw6-633/hash_to_g2.go index 41a3cafa30..5a9c5f1f64 100644 --- a/ecc/bw6-633/hash_to_g2.go +++ b/ecc/bw6-633/hash_to_g2.go @@ -153,9 +153,9 @@ func g2MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG2 implements the SSWU map -// No cofactor clearing -func sswuMapG2(u *fp.Element) G2Affine { +// mapToCurve2 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve2(u *fp.Element) G2Affine { var tv1 fp.Element tv1.Square(u) @@ -227,7 +227,7 @@ func sswuMapG2(u *fp.Element) G2Affine { // MapToG2 invokes the SSWU map, and guarantees that the result is in g2 func MapToG2(u fp.Element) G2Affine { - res := sswuMapG2(&u) + res := mapToCurve2(&u) //this is in an isogenous curve g2Isogeny(&res) res.ClearCofactor(&res) @@ -246,7 +246,7 @@ func EncodeToG2(msg, dst []byte) (G2Affine, error) { return res, err } - res = sswuMapG2(&u[0]) + res = mapToCurve2(&u[0]) //this is in an isogenous curve g2Isogeny(&res) @@ -264,8 +264,8 @@ func HashToG2(msg, dst []byte) (G2Affine, error) { return G2Affine{}, err } - Q0 := sswuMapG2(&u[0]) - Q1 := sswuMapG2(&u[1]) + Q0 := mapToCurve2(&u[0]) + Q1 := mapToCurve2(&u[1]) //TODO: Add in E' first, then apply isogeny g2Isogeny(&Q0) diff --git a/ecc/bw6-633/hash_to_g2_test.go b/ecc/bw6-633/hash_to_g2_test.go index a8697d7810..9679ac8183 100644 --- a/ecc/bw6-633/hash_to_g2_test.go +++ b/ecc/bw6-633/hash_to_g2_test.go @@ -107,7 +107,7 @@ func TestG2SSWU(t *testing.T) { properties.Property("[G2] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG2(&a) + g := mapToCurve2(&a) if !isOnEPrimeG2(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bw6-756/g1.go b/ecc/bw6-756/g1.go index d44199ae7e..89beed892b 100644 --- a/ecc/bw6-756/g1.go +++ b/ecc/bw6-756/g1.go @@ -66,7 +66,7 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) @@ -77,7 +77,7 @@ func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) diff --git a/ecc/bw6-756/g2.go b/ecc/bw6-756/g2.go index 411613f230..0de6ce9113 100644 --- a/ecc/bw6-756/g2.go +++ b/ecc/bw6-756/g2.go @@ -61,7 +61,7 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) @@ -72,7 +72,7 @@ func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) diff --git a/ecc/bw6-756/hash_to_g1.go b/ecc/bw6-756/hash_to_g1.go index 0407b4306a..b02a3c4e27 100644 --- a/ecc/bw6-756/hash_to_g1.go +++ b/ecc/bw6-756/hash_to_g1.go @@ -182,9 +182,9 @@ func g1MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG1 implements the SSWU map -// No cofactor clearing -func sswuMapG1(u *fp.Element) G1Affine { +// mapToCurve1 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve1(u *fp.Element) G1Affine { var tv1 fp.Element tv1.Square(u) @@ -256,7 +256,7 @@ func sswuMapG1(u *fp.Element) G1Affine { // MapToG1 invokes the SSWU map, and guarantees that the result is in g1 func MapToG1(u fp.Element) G1Affine { - res := sswuMapG1(&u) + res := mapToCurve1(&u) //this is in an isogenous curve g1Isogeny(&res) res.ClearCofactor(&res) @@ -275,7 +275,7 @@ func EncodeToG1(msg, dst []byte) (G1Affine, error) { return res, err } - res = sswuMapG1(&u[0]) + res = mapToCurve1(&u[0]) //this is in an isogenous curve g1Isogeny(&res) @@ -293,8 +293,8 @@ func HashToG1(msg, dst []byte) (G1Affine, error) { return G1Affine{}, err } - Q0 := sswuMapG1(&u[0]) - Q1 := sswuMapG1(&u[1]) + Q0 := mapToCurve1(&u[0]) + Q1 := mapToCurve1(&u[1]) //TODO: Add in E' first, then apply isogeny g1Isogeny(&Q0) diff --git a/ecc/bw6-756/hash_to_g1_test.go b/ecc/bw6-756/hash_to_g1_test.go index f263d9d739..7fd95795a0 100644 --- a/ecc/bw6-756/hash_to_g1_test.go +++ b/ecc/bw6-756/hash_to_g1_test.go @@ -107,7 +107,7 @@ func TestG1SSWU(t *testing.T) { properties.Property("[G1] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG1(&a) + g := mapToCurve1(&a) if !isOnEPrimeG1(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bw6-756/hash_to_g2.go b/ecc/bw6-756/hash_to_g2.go index 3a04adde1d..094b1fb0ee 100644 --- a/ecc/bw6-756/hash_to_g2.go +++ b/ecc/bw6-756/hash_to_g2.go @@ -252,9 +252,9 @@ func g2MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG2 implements the SSWU map -// No cofactor clearing -func sswuMapG2(u *fp.Element) G2Affine { +// mapToCurve2 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve2(u *fp.Element) G2Affine { var tv1 fp.Element tv1.Square(u) @@ -326,7 +326,7 @@ func sswuMapG2(u *fp.Element) G2Affine { // MapToG2 invokes the SSWU map, and guarantees that the result is in g2 func MapToG2(u fp.Element) G2Affine { - res := sswuMapG2(&u) + res := mapToCurve2(&u) //this is in an isogenous curve g2Isogeny(&res) res.ClearCofactor(&res) @@ -345,7 +345,7 @@ func EncodeToG2(msg, dst []byte) (G2Affine, error) { return res, err } - res = sswuMapG2(&u[0]) + res = mapToCurve2(&u[0]) //this is in an isogenous curve g2Isogeny(&res) @@ -363,8 +363,8 @@ func HashToG2(msg, dst []byte) (G2Affine, error) { return G2Affine{}, err } - Q0 := sswuMapG2(&u[0]) - Q1 := sswuMapG2(&u[1]) + Q0 := mapToCurve2(&u[0]) + Q1 := mapToCurve2(&u[1]) //TODO: Add in E' first, then apply isogeny g2Isogeny(&Q0) diff --git a/ecc/bw6-756/hash_to_g2_test.go b/ecc/bw6-756/hash_to_g2_test.go index 59d2ec78de..6a64c017ae 100644 --- a/ecc/bw6-756/hash_to_g2_test.go +++ b/ecc/bw6-756/hash_to_g2_test.go @@ -107,7 +107,7 @@ func TestG2SSWU(t *testing.T) { properties.Property("[G2] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG2(&a) + g := mapToCurve2(&a) if !isOnEPrimeG2(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bw6-761/g1.go b/ecc/bw6-761/g1.go index ddd6bfb80c..60b3afe70d 100644 --- a/ecc/bw6-761/g1.go +++ b/ecc/bw6-761/g1.go @@ -66,7 +66,7 @@ func (p *G1Affine) ScalarMultiplication(a *G1Affine, s *big.Int) *G1Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) @@ -77,7 +77,7 @@ func (p *G1Affine) Add(a, b *G1Affine) *G1Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G1Affine) Sub(a, b *G1Affine) *G1Affine { var p1, p2 G1Jac p1.FromAffine(a) diff --git a/ecc/bw6-761/g2.go b/ecc/bw6-761/g2.go index 12f98d338b..4a9817da9f 100644 --- a/ecc/bw6-761/g2.go +++ b/ecc/bw6-761/g2.go @@ -61,7 +61,7 @@ func (p *G2Affine) ScalarMultiplication(a *G2Affine, s *big.Int) *G2Affine { } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) @@ -72,7 +72,7 @@ func (p *G2Affine) Add(a, b *G2Affine) *G2Affine { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *G2Affine) Sub(a, b *G2Affine) *G2Affine { var p1, p2 G2Jac p1.FromAffine(a) diff --git a/ecc/bw6-761/hash_to_g1.go b/ecc/bw6-761/hash_to_g1.go index a60eccccb9..c7bc801185 100644 --- a/ecc/bw6-761/hash_to_g1.go +++ b/ecc/bw6-761/hash_to_g1.go @@ -137,9 +137,9 @@ func g1MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG1 implements the SSWU map -// No cofactor clearing -func sswuMapG1(u *fp.Element) G1Affine { +// mapToCurve1 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve1(u *fp.Element) G1Affine { var tv1 fp.Element tv1.Square(u) @@ -211,7 +211,7 @@ func sswuMapG1(u *fp.Element) G1Affine { // MapToG1 invokes the SSWU map, and guarantees that the result is in g1 func MapToG1(u fp.Element) G1Affine { - res := sswuMapG1(&u) + res := mapToCurve1(&u) //this is in an isogenous curve g1Isogeny(&res) res.ClearCofactor(&res) @@ -230,7 +230,7 @@ func EncodeToG1(msg, dst []byte) (G1Affine, error) { return res, err } - res = sswuMapG1(&u[0]) + res = mapToCurve1(&u[0]) //this is in an isogenous curve g1Isogeny(&res) @@ -248,8 +248,8 @@ func HashToG1(msg, dst []byte) (G1Affine, error) { return G1Affine{}, err } - Q0 := sswuMapG1(&u[0]) - Q1 := sswuMapG1(&u[1]) + Q0 := mapToCurve1(&u[0]) + Q1 := mapToCurve1(&u[1]) //TODO: Add in E' first, then apply isogeny g1Isogeny(&Q0) diff --git a/ecc/bw6-761/hash_to_g1_test.go b/ecc/bw6-761/hash_to_g1_test.go index d2eb5f19d3..09b41191ed 100644 --- a/ecc/bw6-761/hash_to_g1_test.go +++ b/ecc/bw6-761/hash_to_g1_test.go @@ -107,7 +107,7 @@ func TestG1SSWU(t *testing.T) { properties.Property("[G1] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG1(&a) + g := mapToCurve1(&a) if !isOnEPrimeG1(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/bw6-761/hash_to_g2.go b/ecc/bw6-761/hash_to_g2.go index 3985a67f8e..1361f93c1b 100644 --- a/ecc/bw6-761/hash_to_g2.go +++ b/ecc/bw6-761/hash_to_g2.go @@ -311,9 +311,9 @@ func g2MulByZ(z *fp.Element, x *fp.Element) { } // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMapG2 implements the SSWU map -// No cofactor clearing -func sswuMapG2(u *fp.Element) G2Affine { +// mapToCurve2 implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve2(u *fp.Element) G2Affine { var tv1 fp.Element tv1.Square(u) @@ -385,7 +385,7 @@ func sswuMapG2(u *fp.Element) G2Affine { // MapToG2 invokes the SSWU map, and guarantees that the result is in g2 func MapToG2(u fp.Element) G2Affine { - res := sswuMapG2(&u) + res := mapToCurve2(&u) //this is in an isogenous curve g2Isogeny(&res) res.ClearCofactor(&res) @@ -404,7 +404,7 @@ func EncodeToG2(msg, dst []byte) (G2Affine, error) { return res, err } - res = sswuMapG2(&u[0]) + res = mapToCurve2(&u[0]) //this is in an isogenous curve g2Isogeny(&res) @@ -422,8 +422,8 @@ func HashToG2(msg, dst []byte) (G2Affine, error) { return G2Affine{}, err } - Q0 := sswuMapG2(&u[0]) - Q1 := sswuMapG2(&u[1]) + Q0 := mapToCurve2(&u[0]) + Q1 := mapToCurve2(&u[1]) //TODO: Add in E' first, then apply isogeny g2Isogeny(&Q0) diff --git a/ecc/bw6-761/hash_to_g2_test.go b/ecc/bw6-761/hash_to_g2_test.go index 5cc484e0e5..83487d0423 100644 --- a/ecc/bw6-761/hash_to_g2_test.go +++ b/ecc/bw6-761/hash_to_g2_test.go @@ -107,7 +107,7 @@ func TestG2SSWU(t *testing.T) { properties.Property("[G2] hash outputs must be in appropriate groups", prop.ForAll( func(a fp.Element) bool { - g := sswuMapG2(&a) + g := mapToCurve2(&a) if !isOnEPrimeG2(g) { t.Log("SSWU output not on E' curve") diff --git a/ecc/utils.go b/ecc/utils.go index aca2d8e3fa..d0e1fa5cda 100644 --- a/ecc/utils.go +++ b/ecc/utils.go @@ -170,6 +170,13 @@ func getVector(l *Lattice, a, b *big.Int) [2]big.Int { return res } +func min(a, b int) int { + if a < b { + return a + } + return b +} + // ExpandMsgXmd expands msg to a slice of lenInBytes bytes. // https://tools.ietf.org/html/draft-irtf-cfrg-hash-to-curve-06#section-5 // https://tools.ietf.org/html/rfc8017#section-4.1 (I2OSP/O2ISP) @@ -187,8 +194,8 @@ func ExpandMsgXmd(msg, dst []byte, lenInBytes int) ([]byte, error) { // Z_pad = I2OSP(0, r_in_bytes) // l_i_b_str = I2OSP(len_in_bytes, 2) - // DST_prime = I2OSP(len(DST), 1) || DST - // b_0 = H(Z_pad || msg || l_i_b_str || I2OSP(0, 1) || DST_prime) + // DST_prime = I2OSP(len(DST), 1) ∥ DST + // b₀ = H(Z_pad ∥ msg ∥ l_i_b_str ∥ I2OSP(0, 1) ∥ DST_prime) h.Reset() if _, err := h.Write(make([]byte, h.BlockSize())); err != nil { return nil, err @@ -207,7 +214,7 @@ func ExpandMsgXmd(msg, dst []byte, lenInBytes int) ([]byte, error) { } b0 := h.Sum(nil) - // b_1 = H(b_0 || I2OSP(1, 1) || DST_prime) + // b₁ = H(b₀ ∥ I2OSP(1, 1) ∥ DST_prime) h.Reset() if _, err := h.Write(b0); err != nil { return nil, err @@ -227,7 +234,7 @@ func ExpandMsgXmd(msg, dst []byte, lenInBytes int) ([]byte, error) { copy(res[:h.Size()], b1) for i := 2; i <= ell; i++ { - // b_i = H(strxor(b_0, b_(i - 1)) || I2OSP(i, 1) || DST_prime) + // b_i = H(strxor(b₀, b_(i - 1)) ∥ I2OSP(i, 1) ∥ DST_prime) h.Reset() strxor := make([]byte, h.Size()) for j := 0; j < h.Size(); j++ { @@ -246,7 +253,7 @@ func ExpandMsgXmd(msg, dst []byte, lenInBytes int) ([]byte, error) { return nil, err } b1 = h.Sum(nil) - copy(res[h.Size()*(i-1):h.Size()*i], b1) + copy(res[h.Size()*(i-1):min(h.Size()*i, len(res))], b1) } return res, nil } diff --git a/ecc/utils_test.go b/ecc/utils_test.go index 7f71dbe1b4..e4a98b16d5 100644 --- a/ecc/utils_test.go +++ b/ecc/utils_test.go @@ -62,17 +62,13 @@ func BenchmarkSplitting256(b *testing.B) { } -//TODO: The "prime" fields (not "prime fields") are for debugging and arguably do not belong in an automated test type expandMsgXmdTestCase struct { - msg string - lenInBytes int - // TODO @Tabaie these are not used. - _ string //dstPrimeHex string - _ string //msgPrimeHex string + msg string + lenInBytes int uniformBytesHex string } -//Test vectors from the IETF proposal (TODO: insert link) +//Test vectors from https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/14/ Page 148 Section K.1. func TestExpandMsgXmd(t *testing.T) { //name := "expand_message_xmd" dst := "QUUX-V01-CS02-with-expander-SHA256-128" @@ -83,84 +79,88 @@ func TestExpandMsgXmd(t *testing.T) { { "", 0x20, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "68a985b87eb6b46952128911f2a4412bbc302a9d759667f87f7a21d803f07235", }, { "abc", 0x20, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "d8ccab23b5985ccea865c6c97b6e5b8350e794e603b4b97902f53a8a0d605615", }, { "abcdef0123456789", 0x20, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "eff31487c770a893cfb36f912fbfcbff40d5661771ca4b2cb4eafe524333f5c1", }, { "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 0x20, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "b23a1d2b4d97b2ef7785562a7e8bac7eed54ed6e97e29aa51bfe3f12ddad1ff9", }, { "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0x20, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f61616161616161616161610000000000000000000000613531325f6161616161616161616161616161616161616161616161616161002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "4623227bcc01293b8c130bf771da8c298dede7383243dc0993d2d94823958c4c", }, { "", 0x80, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "af84c27ccfd45d41914fdff5df25293e221afc53d8ad2ac06d5e3e29485dadbee0d121587713a3e0dd4d5e69e93eb7cd4f5df4cd103e188cf60cb02edc3edf18eda8576c412b18ffb658e3dd6ec849469b979d444cf7b26911a08e63cf31f9dcc541708d3491184472c2c29bb749d4286b004ceb5ee6b9a7fa5b646c993f0ced", }, { "", 0x20, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "68a985b87eb6b46952128911f2a4412bbc302a9d759667f87f7a21d803f07235", }, { "abc", 0x80, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000616263008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "abba86a6129e366fc877aab32fc4ffc70120d8996c88aee2fe4b32d6c7b6437a647e6c3163d40b76a73cf6a5674ef1d890f95b664ee0afa5359a5c4e07985635bbecbac65d747d3d2da7ec2b8221b17b0ca9dc8a1ac1c07ea6a1e60583e2cb00058e77b7b72a298425cd1b941ad4ec65e8afc50303a22c0f99b0509b4c895f40", }, { "abcdef0123456789", 0x80, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000061626364656630313233343536373839008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "ef904a29bffc4cf9ee82832451c946ac3c8f8058ae97d8d629831a74c6572bd9ebd0df635cd1f208e2038e760c4994984ce73f0d55ea9f22af83ba4734569d4bc95e18350f740c07eef653cbb9f87910d833751825f0ebefa1abe5420bb52be14cf489b37fe1a72f7de2d10be453b2c9d9eb20c7e3f6edc5a60629178d9478df", }, { "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", 0x80, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000713132385f7171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171717171008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "80be107d0884f0d881bb460322f0443d38bd222db8bd0b0a5312a6fedb49c1bbd88fd75d8b9a09486c60123dfa1d73c1cc3169761b17476d3c6b7cbbd727acd0e2c942f4dd96ae3da5de368d26b32286e32de7e5a8cb2949f866a0b80c58116b29fa7fabb3ea7d520ee603e0c25bcaf0b9a5e92ec6a1fe4e0391d1cdbce8c68a", }, { "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 0x80, - "515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", - "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000613531325f6161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161008000515555582d5630312d435330322d776974682d657870616e6465722d5348413235362d31323826", "546aff5444b5b79aa6148bd81728704c32decb73a3ba76e9e75885cad9def1d06d6792f8a7d12794e90efed817d96920d728896a4510864370c207f99bd4a608ea121700ef01ed879745ee3e4ceef777eda6d9e5e38b90c86ea6fb0b36504ba4a45d22e86f6db5dd43d98a294bebb9125d5b794e9d2a81181066eb954966a487", }, + //test cases not in the standard + { + "", + 0x30, + "3808e9bb0ade2df3aa6f1b459eb5058a78142f439213ddac0c97dcab92ae5a8408d86b32bbcc87de686182cbdf65901f", + }, + { + "abc", + 0x30, + "2b877f5f0dfd881405426c6b87b39205ef53a548b0e4d567fc007cb37c6fa1f3b19f42871efefca518ac950c27ac4e28", + }, + { + "abcdef0123456789", + 0x30, + "226da1780b06e59723714f80da9a63648aebcfc1f08e0db87b5b4d16b108da118214c1450b0e86f9cefeb44903fd3aba", + }, + { + "q128_qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq", + 0x30, + "12b23ae2e888f442fd6d0d85d90a0d7ed5337d38113e89cdc7c22db91bd0abaec1023e9a8f0ef583a111104e2f8a0637", + }, + { + "a512_aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + 0x30, + "1aaee90016547a85ab4dc55e4f78a364c2e239c0e58b05753453c63e6e818334005e90d9ce8f047bddab9fbb315f8722", + }, } for _, testCase := range testCases { @@ -175,8 +175,14 @@ func TestExpandMsgXmd(t *testing.T) { t.Fatal(err) } + if len(uniformBytes) != testCase.lenInBytes { + t.Error("wrong length: expected", testCase.lenInBytes, "got", len(uniformBytes)) + } + if !bytes.Equal(uniformBytes, testCaseUniformBytes) { - t.Fail() + uniformBytesHex := make([]byte, len(uniformBytes)*2) + hex.Encode(uniformBytesHex, uniformBytes) + t.Errorf("expected \"%s\" got \"%s\"", testCase.uniformBytesHex, uniformBytesHex) } } } diff --git a/internal/generator/ecc/template/point.go.tmpl b/internal/generator/ecc/template/point.go.tmpl index 309837c216..9fe3e26f64 100644 --- a/internal/generator/ecc/template/point.go.tmpl +++ b/internal/generator/ecc/template/point.go.tmpl @@ -63,7 +63,7 @@ func (p *{{ $TAffine }}) ScalarMultiplication(a *{{ $TAffine }}, s *big.Int) *{{ } // Add adds two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *{{ $TAffine }}) Add(a, b *{{ $TAffine }}) *{{ $TAffine }} { var p1, p2 {{ $TJacobian }} p1.FromAffine(a) @@ -74,7 +74,7 @@ func (p *{{ $TAffine }}) Add(a, b *{{ $TAffine }}) *{{ $TAffine }} { } // Sub subs two point in affine coordinates. -// This should rarely be used as it is very inneficient compared to Jacobian +// This should rarely be used as it is very inefficient compared to Jacobian func (p *{{ $TAffine }}) Sub(a, b *{{ $TAffine }}) *{{ $TAffine }} { var p1, p2 {{ $TJacobian }} p1.FromAffine(a) diff --git a/internal/generator/ecc/template/sswu.go.tmpl b/internal/generator/ecc/template/sswu.go.tmpl index eea2729198..322d5a5595 100644 --- a/internal/generator/ecc/template/sswu.go.tmpl +++ b/internal/generator/ecc/template/sswu.go.tmpl @@ -6,6 +6,8 @@ {{$AffineType := print $CurveTitle "Affine"}} {{$JacType := print $CurveTitle "Jac"}} {{$IsG1 := eq $CurveTitle "G1"}} +{{$CurveIndex := "2"}} +{{if $IsG1}}{{$CurveIndex = "1"}}{{end}} //Note: This only works for simple extensions @@ -315,9 +317,9 @@ func {{$CurveName}}MulByZ(z *{{$CoordType}}, x *{{$CoordType}}) { {{ end }}} // From https://datatracker.ietf.org/doc/draft-irtf-cfrg-hash-to-curve/13/ Pg 80 -// sswuMap{{$CurveTitle}} implements the SSWU map -// No cofactor clearing -func sswuMap{{$CurveTitle}}(u *{{$CoordType}}) {{$AffineType}} { +// mapToCurve{{$CurveIndex}} implements the SSWU map +// No cofactor clearing or isogeny +func mapToCurve{{$CurveIndex}}(u *{{$CoordType}}) {{$AffineType}} { var tv1 {{$CoordType}} tv1.Square(u) @@ -389,7 +391,7 @@ func sswuMap{{$CurveTitle}}(u *{{$CoordType}}) {{$AffineType}} { // MapTo{{$CurveTitle}} invokes the SSWU map, and guarantees that the result is in {{$CurveName}} func MapTo{{$CurveTitle}}(u {{$CoordType}}) {{$AffineType}} { - res := sswuMap{{$CurveTitle}}(&u) + res := mapToCurve{{$CurveIndex}}(&u) {{- if $isogenyNeeded }} //this is in an isogenous curve {{$CurveName}}Isogeny(&res) @@ -413,9 +415,9 @@ func EncodeTo{{$CurveTitle}}(msg, dst []byte) ({{$AffineType}}, error) { } {{if eq $TowerDegree 1}} - res = sswuMap{{$CurveTitle}}(&u[0]) + res = mapToCurve{{$CurveIndex}}(&u[0]) {{else}} - res = sswuMap{{$CurveTitle}}( &{{$CoordType}} { + res = mapToCurve{{$CurveIndex}}( &{{$CoordType}} { {{range $i := interval 0 $TowerDegree }} {{if eq $TowerDegree 2}}A{{end}}{{$i}}: u[{{$i}}], {{end}} }) {{end}} @@ -441,13 +443,13 @@ func HashTo{{$CurveTitle}}(msg, dst []byte) ({{$AffineType}}, error) { } {{if eq $TowerDegree 1}} - Q0 := sswuMap{{$CurveTitle}}(&u[0]) - Q1 := sswuMap{{$CurveTitle}}(&u[1]) + Q0 := mapToCurve{{$CurveIndex}}(&u[0]) + Q1 := mapToCurve{{$CurveIndex}}(&u[1]) {{else}} - Q0 := sswuMap{{$CurveTitle}}( &{{$CoordType}} { + Q0 := mapToCurve{{$CurveIndex}}( &{{$CoordType}} { {{range $i := interval 0 $TowerDegree }} {{if eq $TowerDegree 2}}A{{end}}{{$i}}: u[{{$i}}], {{end}} }) - Q1 := sswuMap{{$CurveTitle}}( &{{$CoordType}} { + Q1 := mapToCurve{{$CurveIndex}}( &{{$CoordType}} { {{range $i := interval 0 $TowerDegree }} {{if eq $TowerDegree 2}}A{{end}}{{$i}}: u[{{$TowerDegree}} + {{$i}}], {{end}} }) {{end}} diff --git a/internal/generator/ecc/template/tests/sswu.go.tmpl b/internal/generator/ecc/template/tests/sswu.go.tmpl index 5549bf2f5b..0c4898e683 100644 --- a/internal/generator/ecc/template/tests/sswu.go.tmpl +++ b/internal/generator/ecc/template/tests/sswu.go.tmpl @@ -1,6 +1,8 @@ {{$CoordType := .Point.CoordType}} {{$CurveName := .Point.PointName}} {{$CurveTitle := toTitle $CurveName}} +{{$CurveIndex := "2"}} +{{if eq $CurveTitle "G1" }}{{$CurveIndex = "1"}}{{end}} {{$TowerDegree := .Field.Degree}} {{$isogenyNeeded := notNil .Isogeny}} @@ -111,7 +113,7 @@ func Test{{$CurveTitle}}SSWU(t *testing.T) { properties.Property("[{{$CurveTitle}}] hash outputs must be in appropriate groups", prop.ForAll( func(a {{$CoordType}}) bool { - g := sswuMap{{$CurveTitle}}(&a) + g := mapToCurve{{$CurveIndex}}(&a) if !isOnEPrime{{$CurveTitle}}(g) { t.Log("SSWU output not on E' curve")