This repository has been archived by the owner on Oct 3, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Add Secp256k1 Signed-off-by: bytemare <[email protected]>
- Loading branch information
Showing
49 changed files
with
1,955 additions
and
555 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,217 @@ | ||
// SPDX-License-Identifier: MIT | ||
// | ||
// Copyright (C) 2020-2023 Daniel Bourdrez. All Rights Reserved. | ||
// | ||
// This source code is licensed under the MIT license found in the | ||
// LICENSE file in the root directory of this source tree or at | ||
// https://spdx.org/licenses/MIT.html | ||
|
||
// Package field provides modular operations over very high integers. | ||
package field | ||
|
||
import ( | ||
"crypto/rand" | ||
"fmt" | ||
"math/big" | ||
) | ||
|
||
var ( | ||
zero = big.NewInt(0) | ||
one = big.NewInt(1) | ||
) | ||
|
||
// String2Int returns a big.Int representation of the integer s. | ||
func String2Int(s string) big.Int { | ||
if p, _ := new(big.Int).SetString(s, 0); p != nil { | ||
return *p | ||
} | ||
|
||
panic("invalid string to convert") | ||
} | ||
|
||
// Field represents a Gaulois Field. | ||
type Field struct { | ||
order big.Int | ||
pMinus1div2 big.Int // used in IsSquare | ||
pMinus2 big.Int // used for Field big.Int inversion | ||
exp big.Int | ||
} | ||
|
||
// NewField returns a newly instantiated field for the given prime order. | ||
func NewField(prime *big.Int) Field { | ||
// pMinus1div2 is used to determine whether a big Int is a quadratic square. | ||
pMinus1div2 := big.NewInt(1) | ||
pMinus1div2.Sub(prime, pMinus1div2) | ||
pMinus1div2.Rsh(pMinus1div2, 1) | ||
|
||
// pMinus2 is used for modular inversion. | ||
pMinus2 := big.NewInt(2) | ||
pMinus2.Sub(prime, pMinus2) | ||
|
||
// precompute e = (p + 1) / 4 | ||
exp := big.NewInt(1) | ||
exp.Add(prime, exp) | ||
exp.Rsh(exp, 2) | ||
|
||
return Field{ | ||
order: *prime, | ||
pMinus1div2: *pMinus1div2, | ||
pMinus2: *pMinus2, | ||
exp: *exp, | ||
} | ||
} | ||
|
||
// Zero returns the zero big.Int of the finite Field. | ||
func (f Field) Zero() *big.Int { | ||
return zero | ||
} | ||
|
||
// One returns one big.Int of the finite Field. | ||
func (f Field) One() *big.Int { | ||
return one | ||
} | ||
|
||
// Random sets res to a random big.Int in the Field. | ||
func (f Field) Random(res *big.Int) *big.Int { | ||
tmp, err := rand.Int(rand.Reader, &f.order) | ||
if err != nil { | ||
// We can as well not panic and try again in a loop | ||
panic(fmt.Errorf("unexpected error in generating random bytes : %w", err)) | ||
} | ||
|
||
res.Set(tmp) | ||
|
||
return res | ||
} | ||
|
||
// Order returns the size of the Field. | ||
func (f Field) Order() *big.Int { | ||
return &f.order | ||
} | ||
|
||
// BitLen of the order. | ||
func (f Field) BitLen() int { | ||
return f.order.BitLen() | ||
} | ||
|
||
// AreEqual returns whether both elements are equal. | ||
func (f Field) AreEqual(f1, f2 *big.Int) bool { | ||
return f.IsZero(f.Sub(&big.Int{}, f1, f2)) | ||
} | ||
|
||
// IsZero returns whether the big.Int is equivalent to zero. | ||
func (f Field) IsZero(e *big.Int) bool { | ||
return e.Sign() == 0 | ||
} | ||
|
||
// Inv sets res to the modular inverse of x mod field order. | ||
func (f Field) Inv(res, x *big.Int) { | ||
f.Exponent(res, x, &f.pMinus2) | ||
} | ||
|
||
// LegendreSymbol applies the Legendre symbole on (a/p) and returns either {-1, 0, 1} mod field order. | ||
func (f Field) LegendreSymbol(a *big.Int) *big.Int { | ||
var res big.Int | ||
return f.Exponent(&res, a, &f.pMinus1div2) | ||
} | ||
|
||
// Exponent returns x^n mod field order. | ||
func (f Field) Exponent(res, x, n *big.Int) *big.Int { | ||
return res.Exp(x, n, &f.order) | ||
} | ||
|
||
// IsSquare returns whether e is a quadratic square. | ||
func (f Field) IsSquare(e *big.Int) bool { | ||
return f.AreEqual(f.LegendreSymbol(e), f.One()) | ||
} | ||
|
||
// IsEqual returns whether the two fields have the same order. | ||
func (f Field) IsEqual(f2 *Field) bool { | ||
return f.order.Cmp(&f2.order) == 0 | ||
} | ||
|
||
// Mod reduces x modulo the field order. | ||
func (f Field) Mod(x *big.Int) *big.Int { | ||
return x.Mod(x, &f.order) | ||
} | ||
|
||
// Neg sets res to the -x modulo the field order. | ||
func (f Field) Neg(res, x *big.Int) *big.Int { | ||
return f.Mod(res.Neg(x)) | ||
} | ||
|
||
// CondNeg sets res to -x if cond == 1. | ||
func (f Field) CondNeg(res, x *big.Int, cond int) { | ||
var neg, cpy big.Int | ||
cpy.Set(x) | ||
f.Neg(&neg, x) | ||
|
||
if cond == 1 { | ||
res.Set(&neg) | ||
} else { | ||
res.Set(&cpy) | ||
} | ||
} | ||
|
||
// Add sets res to x + y modulo the field order. | ||
func (f Field) Add(res, x, y *big.Int) { | ||
f.Mod(res.Add(x, y)) | ||
} | ||
|
||
// Sub sets res to x - y modulo the field order. | ||
func (f Field) Sub(res, x, y *big.Int) *big.Int { | ||
return f.Mod(res.Sub(x, y)) | ||
} | ||
|
||
// Lsh sets res to the left shift of n bits on x modulo the field order. | ||
func (f Field) Lsh(res, x *big.Int, n uint) { | ||
f.Mod(res.Lsh(x, n)) | ||
} | ||
|
||
// Mul sets res to the multiplication of x and y modulo the field order. | ||
func (f Field) Mul(res, x, y *big.Int) { | ||
f.Mod(res.Mul(x, y)) | ||
} | ||
|
||
// Square sets res to the square of x modulo the field order. | ||
func (f Field) Square(res, x *big.Int) { | ||
f.Mod(res.Mul(x, x)) | ||
} | ||
|
||
// CondMov sets res to y if b true, and to x otherwise. | ||
func (f Field) CondMov(res, x, y *big.Int, b bool) { | ||
if b { | ||
res.Set(y) | ||
} else { | ||
res.Set(x) | ||
} | ||
} | ||
|
||
// Sgn0 returns the first bit in the big-endian representation. | ||
func (f Field) Sgn0(x *big.Int) int { | ||
return int(x.Bit(0)) | ||
} | ||
|
||
func (f Field) sqrt3mod4(res, e *big.Int) *big.Int { | ||
return f.Exponent(res, e, &f.exp) | ||
} | ||
|
||
// SquareRoot sets res to a square root of e mod the field's order, if such a square root exists. | ||
func (f Field) SquareRoot(res, e *big.Int) *big.Int { | ||
return f.sqrt3mod4(res, e) | ||
} | ||
|
||
// SqrtRatio res result to the square root of (e/v), and indicates whether (e/v) is a square. | ||
func (f Field) SqrtRatio(res, zMapConstant, e, v *big.Int) bool { | ||
f.Inv(res, v) | ||
f.Mul(res, res, e) | ||
|
||
square := f.IsSquare(res) | ||
if !square { | ||
f.Mul(res, res, zMapConstant) | ||
} | ||
|
||
f.SquareRoot(res, res) | ||
|
||
return square | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
// SPDX-License-Identifier: MIT | ||
// | ||
// Copyright (C)2020-2023 Daniel Bourdrez. All Rights Reserved. | ||
// | ||
// This source code is licensed under the MIT license found in the | ||
// LICENSE file in the root directory of this source tree or at | ||
// https://spdx.org/licenses/MIT.html | ||
|
||
// Package h2c provides hash-to-curve primitives and mapping. | ||
package h2c | ||
|
||
import ( | ||
"math/big" | ||
|
||
"github.com/bytemare/crypto/internal/field" | ||
) | ||
|
||
// MapToCurveSSWU implements the Simplified SWU method for Weierstrass curves for any base field. | ||
func MapToCurveSSWU(f *field.Field, a, b, z, fe *big.Int) (x, y *big.Int) { | ||
var tv1, tv2, tv3, tv4, tv5, tv6, _y1, _px, _py big.Int | ||
|
||
f.Square(&tv1, fe) // 1. tv1 = u^2 | ||
f.Mul(&tv1, z, &tv1) // 2. tv1 = Z * tv1 | ||
f.Square(&tv2, &tv1) // 3. tv2 = tv1^2 | ||
f.Add(&tv2, &tv2, &tv1) // 4. tv2 = tv2 + tv1 | ||
f.Add(&tv3, &tv2, f.One()) // 5. tv3 = tv2 + 1 | ||
f.Mul(&tv3, b, &tv3) // 6. tv3 = B * tv3 | ||
f.CondMov(&tv4, z, | ||
f.Neg(&big.Int{}, &tv2), | ||
!f.IsZero(&tv2)) // 7. tv4 = CMOV(Z, -tv2, tv2 != 0) | ||
f.Mul(&tv4, a, &tv4) // 8. tv4 = A * tv4 | ||
f.Square(&tv2, &tv3) // 9. tv2 = tv3^2 | ||
f.Square(&tv6, &tv4) // 10. tv6 = tv4^2 | ||
f.Mul(&tv5, a, &tv6) // 11. tv5 = A * tv6 | ||
f.Add(&tv2, &tv2, &tv5) // 12. tv2 = tv2 + tv5 | ||
f.Mul(&tv2, &tv2, &tv3) // 13. tv2 = tv2 * tv3 | ||
f.Mul(&tv6, &tv6, &tv4) // 14. tv6 = tv6 * tv4 | ||
f.Mul(&tv5, b, &tv6) // 15. tv5 = B * tv6 | ||
f.Add(&tv2, &tv2, &tv5) // 16. tv2 = tv2 + tv5 | ||
f.Mul(&_px, &tv1, &tv3) // 17. x = tv1 * tv3 | ||
isGx1Square := f.SqrtRatio(&_y1, z, &tv2, &tv6) // 18. isGx1Square, y1 = sqrt_ratio(tv2, tv6) | ||
f.Mul(&_py, &tv1, fe) // 19. y = tv1 * u | ||
f.Mul(&_py, &_py, &_y1) // 20. y = y * y1 | ||
f.CondMov(&_px, &_px, &tv3, isGx1Square) // 21. x = CMOV(x, tv3, isGx1Square) | ||
f.CondMov(&_py, &_py, &_y1, isGx1Square) // 22. y = CMOV(y, y1, isGx1Square) | ||
e1 := f.Sgn0(fe) == f.Sgn0(&_py) // 23. e1 = sgn0(u) == sgn0(y) | ||
f.CondMov(&_py, f.Neg(&big.Int{}, &_py), &_py, e1) // 24. y = CMOV(-y, y, e1) | ||
f.Inv(&tv4, &tv4) // 25. 1 / tv4 | ||
f.Mul(&_px, &_px, &tv4) // 26. x = x / tv4 | ||
|
||
return &_px, &_py | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.