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 }