github.com/consensys/gnark-crypto@v0.14.0/internal/generator/config/hash_to_curve.go (about)

     1  package config
     2  
     3  import (
     4  	"math/big"
     5  
     6  	field "github.com/consensys/gnark-crypto/field/generator/config"
     7  )
     8  
     9  type FieldElementToCurvePoint string
    10  
    11  const (
    12  	SSWU FieldElementToCurvePoint = "SSWU"
    13  	SVDW FieldElementToCurvePoint = "SVDW"
    14  )
    15  
    16  type Isogeny struct {
    17  
    18  	//Isogeny to original curve
    19  	XMap RationalPolynomial
    20  	YMap RationalPolynomial // The y map is also evaluated on x. The result is multiplied by y.
    21  }
    22  
    23  type RationalPolynomial struct {
    24  	Num [][]string //Num is stored
    25  	Den [][]string //Den is stored. It is also monic. The leading coefficient (1) is omitted.
    26  }
    27  
    28  type HashSuite interface {
    29  	GetInfo(baseField *field.FieldConfig, g *Point, name string) HashSuiteInfo
    30  }
    31  
    32  type HashSuiteSswu struct {
    33  	//TODO: Move into Isogeny
    34  	A []string // A is the Weierstrass curve coefficient of x in the isogenous curve over which the SSWU map is evaluated.
    35  	B []string // B is the Weierstrass curve constant term in the isogenous curve over which the SSWU map is evaluated.
    36  
    37  	Z       []int // z (or zeta) is a quadratic non-residue with //TODO: some extra nice properties, refer to WB19
    38  	Isogeny *Isogeny
    39  }
    40  
    41  func toBigIntSlice(z []int) []big.Int {
    42  	res := make([]big.Int, len(z))
    43  	for i := 0; i < len(z); i++ {
    44  		res[i].SetInt64(int64(z[i]))
    45  	}
    46  	return res
    47  }
    48  
    49  type HashSuiteSvdw struct {
    50  	z  []string
    51  	c1 []string
    52  	c2 []string
    53  	c3 []string
    54  	c4 []string
    55  }
    56  
    57  func (parameters *HashSuiteSvdw) GetInfo(baseField *field.FieldConfig, g *Point, name string) HashSuiteInfo {
    58  	f := field.NewTower(baseField, g.CoordExtDegree, g.CoordExtRoot)
    59  	c := []field.Element{
    60  		field.NewElement(parameters.z),
    61  		field.NewElement(parameters.c1),
    62  		field.NewElement(parameters.c2),
    63  		field.NewElement(parameters.c3),
    64  		field.NewElement(parameters.c4),
    65  	}
    66  	return HashSuiteInfo{
    67  		PrecomputedParams: c,
    68  		CofactorClearing:  g.CofactorCleaning,
    69  		Point:             g,
    70  		MappingAlgorithm:  SVDW,
    71  		Name:              name,
    72  		FieldCoordName:    field.CoordNameForExtensionDegree(g.CoordExtDegree),
    73  		Field:             &f,
    74  	}
    75  }
    76  
    77  func (suite *HashSuiteSswu) GetInfo(baseField *field.FieldConfig, g *Point, name string) HashSuiteInfo {
    78  
    79  	f := field.NewTower(baseField, g.CoordExtDegree, g.CoordExtRoot)
    80  	fieldSizeMod256 := uint8(f.Size.Bits()[0])
    81  
    82  	Z := toBigIntSlice(suite.Z)
    83  	var c []field.Element
    84  
    85  	if fieldSizeMod256%4 == 3 {
    86  		c = make([]field.Element, 2)
    87  		c[0] = make([]big.Int, 1)
    88  		c[0][0].Rsh(&f.Size, 2)
    89  
    90  		c[1] = f.Neg(Z)
    91  		c[1] = f.Sqrt(c[1])
    92  
    93  	} else if fieldSizeMod256%8 == 5 {
    94  		c = make([]field.Element, 3)
    95  		c[0] = make([]big.Int, 1)
    96  		c[0][0].Rsh(&f.Size, 3)
    97  
    98  		c[1] = make([]big.Int, f.Degree)
    99  		c[1][0].SetInt64(-1)
   100  		c[1] = f.Sqrt(c[1])
   101  
   102  		c[2] = f.Inverse(c[1])
   103  		c[2] = f.Mul(Z, c[2])
   104  		c[2] = f.Sqrt(c[2])
   105  
   106  	} else if fieldSizeMod256%8 == 1 {
   107  		ONE := big.NewInt(1)
   108  		c = make([]field.Element, 3)
   109  
   110  		c[0] = make([]big.Int, 5)
   111  		// c1 .. c5 stored as c[0][0] .. c[0][4]
   112  		c[0][0].Sub(&f.Size, big.NewInt(1))
   113  		c1 := c[0][0].TrailingZeroBits()
   114  		c[0][0].SetUint64(uint64(c1))
   115  
   116  		var twoPowC1 big.Int
   117  		twoPowC1.Lsh(ONE, c1)
   118  		c[0][1].Rsh(&f.Size, c1)
   119  		c[0][2].Rsh(&c[0][1], 1)
   120  		c[0][3].Sub(&twoPowC1, ONE)
   121  		c[0][4].Rsh(&twoPowC1, 1)
   122  
   123  		// c6, c7 stored as c[1], c[2] respectively
   124  		c[1] = f.Exp(Z, &c[0][1])
   125  
   126  		var c7Pow big.Int
   127  		c7Pow.Add(&c[0][1], ONE)
   128  		c7Pow.Rsh(&c7Pow, 1)
   129  		c[2] = f.Exp(Z, &c7Pow)
   130  
   131  	} else {
   132  		panic("this is logically impossible")
   133  	}
   134  
   135  	return HashSuiteInfo{
   136  		A:                 field.NewElement(suite.A),
   137  		B:                 field.NewElement(suite.B),
   138  		Z:                 Z,
   139  		Point:             g,
   140  		CofactorClearing:  g.CofactorCleaning,
   141  		Name:              name,
   142  		Isogeny:           newIsogenousCurveInfoOptional(suite.Isogeny),
   143  		FieldSizeMod256:   fieldSizeMod256,
   144  		PrecomputedParams: c,
   145  		Field:             &f,
   146  		FieldCoordName:    field.CoordNameForExtensionDegree(g.CoordExtDegree),
   147  		MappingAlgorithm:  SSWU,
   148  	}
   149  }
   150  
   151  func stringMatrixToIntMatrix(s [][]string) []field.Element {
   152  	res := make([]field.Element, len(s))
   153  	for i, S := range s {
   154  		res[i] = field.NewElement(S)
   155  	}
   156  	return res
   157  }
   158  
   159  func newIsogenousCurveInfoOptional(isogenousCurve *Isogeny) *IsogenyInfo {
   160  	if isogenousCurve == nil {
   161  		return nil
   162  	}
   163  	return &IsogenyInfo{
   164  		XMap: RationalPolynomialInfo{
   165  			stringMatrixToIntMatrix(isogenousCurve.XMap.Num),
   166  			stringMatrixToIntMatrix(isogenousCurve.XMap.Den),
   167  		},
   168  		YMap: RationalPolynomialInfo{
   169  			stringMatrixToIntMatrix(isogenousCurve.YMap.Num),
   170  			stringMatrixToIntMatrix(isogenousCurve.YMap.Den),
   171  		},
   172  	}
   173  }
   174  
   175  type IsogenyInfo struct {
   176  	XMap RationalPolynomialInfo
   177  	YMap RationalPolynomialInfo // The y map is also evaluated on x. The result is multiplied by y.
   178  }
   179  
   180  type RationalPolynomialInfo struct {
   181  	Num []field.Element
   182  	Den []field.Element //denominator is monic. The leading coefficient (1) is omitted.
   183  }
   184  
   185  type HashSuiteInfo struct {
   186  	//Isogeny to original curve
   187  	Isogeny *IsogenyInfo //pointer so it's nullable.
   188  
   189  	A []big.Int //TODO: Move inside IsogenyInfo
   190  	B []big.Int
   191  
   192  	Point             *Point
   193  	Field             *field.Extension
   194  	FieldCoordName    string
   195  	Name              string
   196  	FieldSizeMod256   uint8
   197  	PrecomputedParams []field.Element // PrecomputedParams[0][n] correspond to integer cā‚™ā‚‹ā‚ in std doc
   198  	// PrecomputedParams[nā‰„1] correspond to field element c_( len(PrecomputedParams[0]) + n - 1 ) in std doc
   199  	Z                []big.Int // z (or zeta) is a quadratic non-residue with //TODO: some extra nice properties, refer to WB19
   200  	CofactorClearing bool
   201  	MappingAlgorithm FieldElementToCurvePoint
   202  }