mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-19 21:31:37 +00:00
Merge pull request #790 from gzliudan/upgrade_crypto
upgrade crypto package
This commit is contained in:
commit
5cff4564aa
20 changed files with 435 additions and 159 deletions
|
|
@ -105,8 +105,8 @@ func (e *gfP12) Mul(a, b *gfP12) *gfP12 {
|
|||
}
|
||||
|
||||
func (e *gfP12) MulScalar(a *gfP12, b *gfP6) *gfP12 {
|
||||
e.x.Mul(&e.x, b)
|
||||
e.y.Mul(&e.y, b)
|
||||
e.x.Mul(&a.x, b)
|
||||
e.y.Mul(&a.y, b)
|
||||
return e
|
||||
}
|
||||
|
||||
|
|
|
|||
51
crypto/bn256/gnark/g1.go
Normal file
51
crypto/bn256/gnark/g1.go
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package bn256
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc/bn254"
|
||||
)
|
||||
|
||||
// G1 is the affine representation of a G1 group element.
|
||||
//
|
||||
// Since this code is used for precompiles, using Jacobian
|
||||
// points are not beneficial because there are no intermediate
|
||||
// points to allow us to save on inversions.
|
||||
//
|
||||
// Note: We also use this struct so that we can conform to the existing API
|
||||
// that the precompiles want.
|
||||
type G1 struct {
|
||||
inner bn254.G1Affine
|
||||
}
|
||||
|
||||
// Add adds `a` and `b` together, storing the result in `g`
|
||||
func (g *G1) Add(a, b *G1) {
|
||||
g.inner.Add(&a.inner, &b.inner)
|
||||
}
|
||||
|
||||
// ScalarMult computes the scalar multiplication between `a` and
|
||||
// `scalar`, storing the result in `g`
|
||||
func (g *G1) ScalarMult(a *G1, scalar *big.Int) {
|
||||
g.inner.ScalarMultiplication(&a.inner, scalar)
|
||||
}
|
||||
|
||||
// Unmarshal deserializes `buf` into `g`
|
||||
//
|
||||
// Note: whether the deserialization is of a compressed
|
||||
// or an uncompressed point, is encoded in the bytes.
|
||||
//
|
||||
// For our purpose, the point will always be serialized
|
||||
// as uncompressed, ie 64 bytes.
|
||||
//
|
||||
// This method also checks whether the point is on the
|
||||
// curve and in the prime order subgroup.
|
||||
func (g *G1) Unmarshal(buf []byte) (int, error) {
|
||||
return g.inner.SetBytes(buf)
|
||||
}
|
||||
|
||||
// Marshal serializes the point into a byte slice.
|
||||
//
|
||||
// Note: The point is serialized as uncompressed.
|
||||
func (p *G1) Marshal() []byte {
|
||||
return p.inner.Marshal()
|
||||
}
|
||||
38
crypto/bn256/gnark/g2.go
Normal file
38
crypto/bn256/gnark/g2.go
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
package bn256
|
||||
|
||||
import (
|
||||
"github.com/consensys/gnark-crypto/ecc/bn254"
|
||||
)
|
||||
|
||||
// G2 is the affine representation of a G2 group element.
|
||||
//
|
||||
// Since this code is used for precompiles, using Jacobian
|
||||
// points are not beneficial because there are no intermediate
|
||||
// points and G2 in particular is only used for the pairing input.
|
||||
//
|
||||
// Note: We also use this struct so that we can conform to the existing API
|
||||
// that the precompiles want.
|
||||
type G2 struct {
|
||||
inner bn254.G2Affine
|
||||
}
|
||||
|
||||
// Unmarshal deserializes `buf` into `g`
|
||||
//
|
||||
// Note: whether the deserialization is of a compressed
|
||||
// or an uncompressed point, is encoded in the bytes.
|
||||
//
|
||||
// For our purpose, the point will always be serialized
|
||||
// as uncompressed, ie 128 bytes.
|
||||
//
|
||||
// This method also checks whether the point is on the
|
||||
// curve and in the prime order subgroup.
|
||||
func (g *G2) Unmarshal(buf []byte) (int, error) {
|
||||
return g.inner.SetBytes(buf)
|
||||
}
|
||||
|
||||
// Marshal serializes the point into a byte slice.
|
||||
//
|
||||
// Note: The point is serialized as uncompressed.
|
||||
func (g *G2) Marshal() []byte {
|
||||
return g.inner.Marshal()
|
||||
}
|
||||
65
crypto/bn256/gnark/gt.go
Normal file
65
crypto/bn256/gnark/gt.go
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package bn256
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/consensys/gnark-crypto/ecc/bn254"
|
||||
)
|
||||
|
||||
// GT is the affine representation of a GT field element.
|
||||
//
|
||||
// Note: GT is not explicitly used in mainline code.
|
||||
// It is needed for fuzzing.
|
||||
type GT struct {
|
||||
inner bn254.GT
|
||||
}
|
||||
|
||||
// Pair compute the optimal Ate pairing between a G1 and
|
||||
// G2 element.
|
||||
//
|
||||
// Note: This method is not explicitly used in mainline code.
|
||||
// It is needed for fuzzing. It should also be noted,
|
||||
// that the output of this function may not match other
|
||||
func Pair(a_ *G1, b_ *G2) *GT {
|
||||
a := a_.inner
|
||||
b := b_.inner
|
||||
|
||||
pairingOutput, err := bn254.Pair([]bn254.G1Affine{a}, []bn254.G2Affine{b})
|
||||
|
||||
if err != nil {
|
||||
// Since this method is only called during fuzzing, it is okay to panic here.
|
||||
// We do not return an error to match the interface of the other bn256 libraries.
|
||||
panic(fmt.Sprintf("gnark/bn254 encountered error: %v", err))
|
||||
}
|
||||
|
||||
return >{
|
||||
inner: pairingOutput,
|
||||
}
|
||||
}
|
||||
|
||||
// Unmarshal deserializes `buf` into `g`
|
||||
//
|
||||
// Note: This method is not explicitly used in mainline code.
|
||||
// It is needed for fuzzing.
|
||||
func (g *GT) Unmarshal(buf []byte) error {
|
||||
return g.inner.SetBytes(buf)
|
||||
}
|
||||
|
||||
// Marshal serializes the point into a byte slice.
|
||||
//
|
||||
// Note: This method is not explicitly used in mainline code.
|
||||
// It is needed for fuzzing.
|
||||
func (g *GT) Marshal() []byte {
|
||||
bytes := g.inner.Bytes()
|
||||
return bytes[:]
|
||||
}
|
||||
|
||||
// Exp raises `base` to the power of `exponent`
|
||||
//
|
||||
// Note: This method is not explicitly used in mainline code.
|
||||
// It is needed for fuzzing.
|
||||
func (g *GT) Exp(base GT, exponent *big.Int) *GT {
|
||||
g.inner.Exp(base.inner, exponent)
|
||||
return g
|
||||
}
|
||||
73
crypto/bn256/gnark/pairing.go
Normal file
73
crypto/bn256/gnark/pairing.go
Normal file
|
|
@ -0,0 +1,73 @@
|
|||
package bn256
|
||||
|
||||
import (
|
||||
"github.com/consensys/gnark-crypto/ecc/bn254"
|
||||
)
|
||||
|
||||
// Computes the following relation: ∏ᵢ e(Pᵢ, Qᵢ) =? 1
|
||||
//
|
||||
// To explain why gnark returns a (bool, error):
|
||||
//
|
||||
// - If the function `e` does not return a result then internally
|
||||
// an error is returned.
|
||||
// - If `e` returns a result, then error will be nil,
|
||||
// but if this value is not `1` then the boolean value will be false
|
||||
//
|
||||
// We therefore check for an error, and return false if its non-nil and
|
||||
// then return the value of the boolean if not.
|
||||
func PairingCheck(a_ []*G1, b_ []*G2) bool {
|
||||
a := getInnerG1s(a_)
|
||||
b := getInnerG2s(b_)
|
||||
|
||||
// Assume that len(a) == len(b)
|
||||
//
|
||||
// The pairing function will return
|
||||
// false, if this is not the case.
|
||||
size := len(a)
|
||||
|
||||
// Check if input is empty -- gnark will
|
||||
// return false on an empty input, however
|
||||
// the ossified behavior is to return true
|
||||
// on an empty input, so we add this if statement.
|
||||
if size == 0 {
|
||||
return true
|
||||
}
|
||||
|
||||
ok, err := bn254.PairingCheck(a, b)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
// getInnerG1s gets the inner gnark G1 elements.
|
||||
//
|
||||
// These methods are used for two reasons:
|
||||
//
|
||||
// - We use a new type `G1`, so we need to convert from
|
||||
// []*G1 to []*bn254.G1Affine
|
||||
// - The gnark API accepts slices of values and not slices of
|
||||
// pointers to values, so we need to return []bn254.G1Affine
|
||||
// instead of []*bn254.G1Affine.
|
||||
func getInnerG1s(pointerSlice []*G1) []bn254.G1Affine {
|
||||
gnarkValues := make([]bn254.G1Affine, 0, len(pointerSlice))
|
||||
for _, ptr := range pointerSlice {
|
||||
if ptr != nil {
|
||||
gnarkValues = append(gnarkValues, ptr.inner)
|
||||
}
|
||||
}
|
||||
return gnarkValues
|
||||
}
|
||||
|
||||
// getInnerG2s gets the inner gnark G2 elements.
|
||||
//
|
||||
// The rationale for this method is the same as `getInnerG1s`.
|
||||
func getInnerG2s(pointerSlice []*G2) []bn254.G2Affine {
|
||||
gnarkValues := make([]bn254.G2Affine, 0, len(pointerSlice))
|
||||
for _, ptr := range pointerSlice {
|
||||
if ptr != nil {
|
||||
gnarkValues = append(gnarkValues, ptr.inner)
|
||||
}
|
||||
}
|
||||
return gnarkValues
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ import (
|
|||
)
|
||||
|
||||
// BUG(agl): this implementation is not constant time.
|
||||
// TODO(agl): keep GF(p²) elements in Mongomery form.
|
||||
// TODO(agl): keep GF(p²) elements in Montgomery form.
|
||||
|
||||
// G1 is an abstract cyclic group. The zero value is suitable for use as the
|
||||
// output of an operation, but cannot be used as an input.
|
||||
|
|
|
|||
|
|
@ -125,8 +125,8 @@ func (e *gfP12) Mul(a, b *gfP12, pool *bnPool) *gfP12 {
|
|||
}
|
||||
|
||||
func (e *gfP12) MulScalar(a *gfP12, b *gfP6, pool *bnPool) *gfP12 {
|
||||
e.x.Mul(e.x, b, pool)
|
||||
e.y.Mul(e.y, b, pool)
|
||||
e.x.Mul(a.x, b, pool)
|
||||
e.y.Mul(a.y, b, pool)
|
||||
return e
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,12 +45,21 @@ const RecoveryIDOffset = 64
|
|||
const DigestLength = 32
|
||||
|
||||
var (
|
||||
secp256k1N, _ = new(big.Int).SetString("fffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141", 16)
|
||||
secp256k1N = S256().Params().N
|
||||
secp256k1halfN = new(big.Int).Div(secp256k1N, big.NewInt(2))
|
||||
)
|
||||
|
||||
var errInvalidPubkey = errors.New("invalid secp256k1 public key")
|
||||
|
||||
// EllipticCurve contains curve operations.
|
||||
type EllipticCurve interface {
|
||||
elliptic.Curve
|
||||
|
||||
// Point marshaling/unmarshaing.
|
||||
Marshal(x, y *big.Int) []byte
|
||||
Unmarshal(data []byte) (x, y *big.Int)
|
||||
}
|
||||
|
||||
// KeccakState wraps sha3.state. In addition to the usual hash methods, it also supports
|
||||
// Read to get a variable amount of data from the hash state. Read is faster than Sum
|
||||
// because it doesn't copy the internal state, but also modifies the internal state.
|
||||
|
|
@ -148,7 +157,7 @@ func toECDSA(d []byte, strict bool) (*ecdsa.PrivateKey, error) {
|
|||
return nil, errors.New("invalid private key, zero or negative")
|
||||
}
|
||||
|
||||
priv.PublicKey.X, priv.PublicKey.Y = priv.PublicKey.Curve.ScalarBaseMult(d)
|
||||
priv.PublicKey.X, priv.PublicKey.Y = S256().ScalarBaseMult(d)
|
||||
if priv.PublicKey.X == nil {
|
||||
return nil, errors.New("invalid private key")
|
||||
}
|
||||
|
|
@ -165,7 +174,7 @@ func FromECDSA(priv *ecdsa.PrivateKey) []byte {
|
|||
|
||||
// UnmarshalPubkey converts bytes to a secp256k1 public key.
|
||||
func UnmarshalPubkey(pub []byte) (*ecdsa.PublicKey, error) {
|
||||
x, y := elliptic.Unmarshal(S256(), pub)
|
||||
x, y := S256().Unmarshal(pub)
|
||||
if x == nil {
|
||||
return nil, errInvalidPubkey
|
||||
}
|
||||
|
|
@ -176,7 +185,7 @@ func FromECDSAPub(pub *ecdsa.PublicKey) []byte {
|
|||
if pub == nil || pub.X == nil || pub.Y == nil {
|
||||
return nil
|
||||
}
|
||||
return elliptic.Marshal(S256(), pub.X, pub.Y)
|
||||
return S256().Marshal(pub.X, pub.Y)
|
||||
}
|
||||
|
||||
// HexToECDSA parses a secp256k1 private key.
|
||||
|
|
@ -278,7 +287,5 @@ func PubkeyToAddress(p ecdsa.PublicKey) common.Address {
|
|||
}
|
||||
|
||||
func zeroBytes(bytes []byte) {
|
||||
for i := range bytes {
|
||||
bytes[i] = 0
|
||||
}
|
||||
clear(bytes)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,8 @@ import (
|
|||
"hash"
|
||||
"io"
|
||||
"math/big"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -95,15 +97,15 @@ func ImportECDSA(prv *ecdsa.PrivateKey) *PrivateKey {
|
|||
// Generate an elliptic curve public / private keypair. If params is nil,
|
||||
// the recommended default parameters for the key will be chosen.
|
||||
func GenerateKey(rand io.Reader, curve elliptic.Curve, params *ECIESParams) (prv *PrivateKey, err error) {
|
||||
pb, x, y, err := elliptic.GenerateKey(curve, rand)
|
||||
sk, err := ecdsa.GenerateKey(curve, rand)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
prv = new(PrivateKey)
|
||||
prv.PublicKey.X = x
|
||||
prv.PublicKey.Y = y
|
||||
prv.PublicKey.X = sk.X
|
||||
prv.PublicKey.Y = sk.Y
|
||||
prv.PublicKey.Curve = curve
|
||||
prv.D = new(big.Int).SetBytes(pb)
|
||||
prv.D = new(big.Int).Set(sk.D)
|
||||
if params == nil {
|
||||
params = ParamsFromCurve(curve)
|
||||
}
|
||||
|
|
@ -255,12 +257,15 @@ func Encrypt(rand io.Reader, pub *PublicKey, m, s1, s2 []byte) (ct []byte, err e
|
|||
|
||||
d := messageTag(params.Hash, Km, em, s2)
|
||||
|
||||
Rb := elliptic.Marshal(pub.Curve, R.PublicKey.X, R.PublicKey.Y)
|
||||
ct = make([]byte, len(Rb)+len(em)+len(d))
|
||||
copy(ct, Rb)
|
||||
copy(ct[len(Rb):], em)
|
||||
copy(ct[len(Rb)+len(em):], d)
|
||||
return ct, nil
|
||||
if curve, ok := pub.Curve.(crypto.EllipticCurve); ok {
|
||||
Rb := curve.Marshal(R.PublicKey.X, R.PublicKey.Y)
|
||||
ct = make([]byte, len(Rb)+len(em)+len(d))
|
||||
copy(ct, Rb)
|
||||
copy(ct[len(Rb):], em)
|
||||
copy(ct[len(Rb)+len(em):], d)
|
||||
return ct, nil
|
||||
}
|
||||
return nil, ErrInvalidCurve
|
||||
}
|
||||
|
||||
// Decrypt decrypts an ECIES ciphertext.
|
||||
|
|
@ -297,21 +302,24 @@ func (prv *PrivateKey) Decrypt(c, s1, s2 []byte) (m []byte, err error) {
|
|||
|
||||
R := new(PublicKey)
|
||||
R.Curve = prv.PublicKey.Curve
|
||||
R.X, R.Y = elliptic.Unmarshal(R.Curve, c[:rLen])
|
||||
if R.X == nil {
|
||||
return nil, ErrInvalidPublicKey
|
||||
}
|
||||
|
||||
z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
Ke, Km := deriveKeys(hash, z, s1, params.KeyLen)
|
||||
if curve, ok := R.Curve.(crypto.EllipticCurve); ok {
|
||||
R.X, R.Y = curve.Unmarshal(c[:rLen])
|
||||
if R.X == nil {
|
||||
return nil, ErrInvalidPublicKey
|
||||
}
|
||||
|
||||
d := messageTag(params.Hash, Km, c[mStart:mEnd], s2)
|
||||
if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 {
|
||||
return nil, ErrInvalidMessage
|
||||
}
|
||||
z, err := prv.GenerateShared(R, params.KeyLen, params.KeyLen)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
Ke, Km := deriveKeys(hash, z, s1, params.KeyLen)
|
||||
|
||||
return symDecrypt(params, Ke, c[mStart:mEnd])
|
||||
}
|
||||
d := messageTag(params.Hash, Km, c[mStart:mEnd], s2)
|
||||
if subtle.ConstantTimeCompare(c[mEnd:], d) != 1 {
|
||||
return nil, ErrInvalidMessage
|
||||
}
|
||||
return symDecrypt(params, Ke, c[mStart:mEnd])
|
||||
}
|
||||
return nil, ErrInvalidCurve
|
||||
}
|
||||
|
|
@ -79,52 +79,52 @@ type BitCurve struct {
|
|||
BitSize int // the size of the underlying field
|
||||
}
|
||||
|
||||
func (BitCurve *BitCurve) Params() *elliptic.CurveParams {
|
||||
func (bitCurve *BitCurve) Params() *elliptic.CurveParams {
|
||||
return &elliptic.CurveParams{
|
||||
P: BitCurve.P,
|
||||
N: BitCurve.N,
|
||||
B: BitCurve.B,
|
||||
Gx: BitCurve.Gx,
|
||||
Gy: BitCurve.Gy,
|
||||
BitSize: BitCurve.BitSize,
|
||||
P: bitCurve.P,
|
||||
N: bitCurve.N,
|
||||
B: bitCurve.B,
|
||||
Gx: bitCurve.Gx,
|
||||
Gy: bitCurve.Gy,
|
||||
BitSize: bitCurve.BitSize,
|
||||
}
|
||||
}
|
||||
|
||||
// IsOnCurve returns true if the given (x,y) lies on the BitCurve.
|
||||
func (BitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool {
|
||||
func (bitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool {
|
||||
// y² = x³ + b
|
||||
y2 := new(big.Int).Mul(y, y) //y²
|
||||
y2.Mod(y2, BitCurve.P) //y²%P
|
||||
y2.Mod(y2, bitCurve.P) //y²%P
|
||||
|
||||
x3 := new(big.Int).Mul(x, x) //x²
|
||||
x3.Mul(x3, x) //x³
|
||||
|
||||
x3.Add(x3, BitCurve.B) //x³+B
|
||||
x3.Mod(x3, BitCurve.P) //(x³+B)%P
|
||||
x3.Add(x3, bitCurve.B) //x³+B
|
||||
x3.Mod(x3, bitCurve.P) //(x³+B)%P
|
||||
|
||||
return x3.Cmp(y2) == 0
|
||||
}
|
||||
|
||||
// affineFromJacobian reverses the Jacobian transform. See the comment at the
|
||||
// top of the file.
|
||||
func (BitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
|
||||
func (bitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.Int) {
|
||||
if z.Sign() == 0 {
|
||||
return new(big.Int), new(big.Int)
|
||||
}
|
||||
|
||||
zinv := new(big.Int).ModInverse(z, BitCurve.P)
|
||||
zinv := new(big.Int).ModInverse(z, bitCurve.P)
|
||||
zinvsq := new(big.Int).Mul(zinv, zinv)
|
||||
|
||||
xOut = new(big.Int).Mul(x, zinvsq)
|
||||
xOut.Mod(xOut, BitCurve.P)
|
||||
xOut.Mod(xOut, bitCurve.P)
|
||||
zinvsq.Mul(zinvsq, zinv)
|
||||
yOut = new(big.Int).Mul(y, zinvsq)
|
||||
yOut.Mod(yOut, BitCurve.P)
|
||||
yOut.Mod(yOut, bitCurve.P)
|
||||
return
|
||||
}
|
||||
|
||||
// Add returns the sum of (x1,y1) and (x2,y2)
|
||||
func (BitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
|
||||
func (bitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
|
||||
// If one point is at infinity, return the other point.
|
||||
// Adding the point at infinity to any point will preserve the other point.
|
||||
if x1.Sign() == 0 && y1.Sign() == 0 {
|
||||
|
|
@ -135,27 +135,27 @@ func (BitCurve *BitCurve) Add(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) {
|
|||
}
|
||||
z := new(big.Int).SetInt64(1)
|
||||
if x1.Cmp(x2) == 0 && y1.Cmp(y2) == 0 {
|
||||
return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z))
|
||||
return bitCurve.affineFromJacobian(bitCurve.doubleJacobian(x1, y1, z))
|
||||
}
|
||||
return BitCurve.affineFromJacobian(BitCurve.addJacobian(x1, y1, z, x2, y2, z))
|
||||
return bitCurve.affineFromJacobian(bitCurve.addJacobian(x1, y1, z, x2, y2, z))
|
||||
}
|
||||
|
||||
// addJacobian takes two points in Jacobian coordinates, (x1, y1, z1) and
|
||||
// (x2, y2, z2) and returns their sum, also in Jacobian form.
|
||||
func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
|
||||
func (bitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int, *big.Int, *big.Int) {
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#addition-add-2007-bl
|
||||
z1z1 := new(big.Int).Mul(z1, z1)
|
||||
z1z1.Mod(z1z1, BitCurve.P)
|
||||
z1z1.Mod(z1z1, bitCurve.P)
|
||||
z2z2 := new(big.Int).Mul(z2, z2)
|
||||
z2z2.Mod(z2z2, BitCurve.P)
|
||||
z2z2.Mod(z2z2, bitCurve.P)
|
||||
|
||||
u1 := new(big.Int).Mul(x1, z2z2)
|
||||
u1.Mod(u1, BitCurve.P)
|
||||
u1.Mod(u1, bitCurve.P)
|
||||
u2 := new(big.Int).Mul(x2, z1z1)
|
||||
u2.Mod(u2, BitCurve.P)
|
||||
u2.Mod(u2, bitCurve.P)
|
||||
h := new(big.Int).Sub(u2, u1)
|
||||
if h.Sign() == -1 {
|
||||
h.Add(h, BitCurve.P)
|
||||
h.Add(h, bitCurve.P)
|
||||
}
|
||||
i := new(big.Int).Lsh(h, 1)
|
||||
i.Mul(i, i)
|
||||
|
|
@ -163,13 +163,13 @@ func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
|
|||
|
||||
s1 := new(big.Int).Mul(y1, z2)
|
||||
s1.Mul(s1, z2z2)
|
||||
s1.Mod(s1, BitCurve.P)
|
||||
s1.Mod(s1, bitCurve.P)
|
||||
s2 := new(big.Int).Mul(y2, z1)
|
||||
s2.Mul(s2, z1z1)
|
||||
s2.Mod(s2, BitCurve.P)
|
||||
s2.Mod(s2, bitCurve.P)
|
||||
r := new(big.Int).Sub(s2, s1)
|
||||
if r.Sign() == -1 {
|
||||
r.Add(r, BitCurve.P)
|
||||
r.Add(r, bitCurve.P)
|
||||
}
|
||||
r.Lsh(r, 1)
|
||||
v := new(big.Int).Mul(u1, i)
|
||||
|
|
@ -179,7 +179,7 @@ func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
|
|||
x3.Sub(x3, j)
|
||||
x3.Sub(x3, v)
|
||||
x3.Sub(x3, v)
|
||||
x3.Mod(x3, BitCurve.P)
|
||||
x3.Mod(x3, bitCurve.P)
|
||||
|
||||
y3 := new(big.Int).Set(r)
|
||||
v.Sub(v, x3)
|
||||
|
|
@ -187,33 +187,33 @@ func (BitCurve *BitCurve) addJacobian(x1, y1, z1, x2, y2, z2 *big.Int) (*big.Int
|
|||
s1.Mul(s1, j)
|
||||
s1.Lsh(s1, 1)
|
||||
y3.Sub(y3, s1)
|
||||
y3.Mod(y3, BitCurve.P)
|
||||
y3.Mod(y3, bitCurve.P)
|
||||
|
||||
z3 := new(big.Int).Add(z1, z2)
|
||||
z3.Mul(z3, z3)
|
||||
z3.Sub(z3, z1z1)
|
||||
if z3.Sign() == -1 {
|
||||
z3.Add(z3, BitCurve.P)
|
||||
z3.Add(z3, bitCurve.P)
|
||||
}
|
||||
z3.Sub(z3, z2z2)
|
||||
if z3.Sign() == -1 {
|
||||
z3.Add(z3, BitCurve.P)
|
||||
z3.Add(z3, bitCurve.P)
|
||||
}
|
||||
z3.Mul(z3, h)
|
||||
z3.Mod(z3, BitCurve.P)
|
||||
z3.Mod(z3, bitCurve.P)
|
||||
|
||||
return x3, y3, z3
|
||||
}
|
||||
|
||||
// Double returns 2*(x,y)
|
||||
func (BitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
|
||||
func (bitCurve *BitCurve) Double(x1, y1 *big.Int) (*big.Int, *big.Int) {
|
||||
z1 := new(big.Int).SetInt64(1)
|
||||
return BitCurve.affineFromJacobian(BitCurve.doubleJacobian(x1, y1, z1))
|
||||
return bitCurve.affineFromJacobian(bitCurve.doubleJacobian(x1, y1, z1))
|
||||
}
|
||||
|
||||
// doubleJacobian takes a point in Jacobian coordinates, (x, y, z), and
|
||||
// returns its double, also in Jacobian form.
|
||||
func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
|
||||
func (bitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int, *big.Int) {
|
||||
// See http://hyperelliptic.org/EFD/g1p/auto-shortw-jacobian-0.html#doubling-dbl-2009-l
|
||||
|
||||
a := new(big.Int).Mul(x, x) //X1²
|
||||
|
|
@ -231,30 +231,30 @@ func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
|
|||
|
||||
x3 := new(big.Int).Mul(big.NewInt(2), d) //2*D
|
||||
x3.Sub(f, x3) //F-2*D
|
||||
x3.Mod(x3, BitCurve.P)
|
||||
x3.Mod(x3, bitCurve.P)
|
||||
|
||||
y3 := new(big.Int).Sub(d, x3) //D-X3
|
||||
y3.Mul(e, y3) //E*(D-X3)
|
||||
y3.Sub(y3, new(big.Int).Mul(big.NewInt(8), c)) //E*(D-X3)-8*C
|
||||
y3.Mod(y3, BitCurve.P)
|
||||
y3.Mod(y3, bitCurve.P)
|
||||
|
||||
z3 := new(big.Int).Mul(y, z) //Y1*Z1
|
||||
z3.Mul(big.NewInt(2), z3) //3*Y1*Z1
|
||||
z3.Mod(z3, BitCurve.P)
|
||||
z3.Mod(z3, bitCurve.P)
|
||||
|
||||
return x3, y3, z3
|
||||
}
|
||||
|
||||
// ScalarBaseMult returns k*G, where G is the base point of the group and k is
|
||||
// an integer in big-endian form.
|
||||
func (BitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
|
||||
return BitCurve.ScalarMult(BitCurve.Gx, BitCurve.Gy, k)
|
||||
func (bitCurve *BitCurve) ScalarBaseMult(k []byte) (*big.Int, *big.Int) {
|
||||
return bitCurve.ScalarMult(bitCurve.Gx, bitCurve.Gy, k)
|
||||
}
|
||||
|
||||
// Marshal converts a point into the form specified in section 4.3.6 of ANSI
|
||||
// X9.62.
|
||||
func (BitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
|
||||
byteLen := (BitCurve.BitSize + 7) >> 3
|
||||
func (bitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
|
||||
byteLen := (bitCurve.BitSize + 7) >> 3
|
||||
ret := make([]byte, 1+2*byteLen)
|
||||
ret[0] = 4 // uncompressed point flag
|
||||
readBits(x, ret[1:1+byteLen])
|
||||
|
|
@ -264,8 +264,8 @@ func (BitCurve *BitCurve) Marshal(x, y *big.Int) []byte {
|
|||
|
||||
// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On
|
||||
// error, x = nil.
|
||||
func (BitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) {
|
||||
byteLen := (BitCurve.BitSize + 7) >> 3
|
||||
func (bitCurve *BitCurve) Unmarshal(data []byte) (x, y *big.Int) {
|
||||
byteLen := (bitCurve.BitSize + 7) >> 3
|
||||
if len(data) != 1+2*byteLen {
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ extern int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, const unsigned
|
|||
*/
|
||||
import "C"
|
||||
|
||||
func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
|
||||
func (bitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
|
||||
// Ensure scalar is exactly 32 bytes. We pad always, even if
|
||||
// scalar is 32 bytes long, to avoid a timing side channel.
|
||||
if len(scalar) > 32 {
|
||||
|
|
@ -44,12 +44,8 @@ func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int,
|
|||
// Unpack the result and clear temporaries.
|
||||
x := new(big.Int).SetBytes(point[:32])
|
||||
y := new(big.Int).SetBytes(point[32:])
|
||||
for i := range point {
|
||||
point[i] = 0
|
||||
}
|
||||
for i := range padded {
|
||||
scalar[i] = 0
|
||||
}
|
||||
clear(point)
|
||||
clear(scalar)
|
||||
if res != 1 {
|
||||
return nil, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@ package secp256k1
|
|||
|
||||
import "math/big"
|
||||
|
||||
func (BitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
|
||||
func (bitCurve *BitCurve) ScalarMult(Bx, By *big.Int, scalar []byte) (*big.Int, *big.Int) {
|
||||
panic("ScalarMult is not available when secp256k1 is built without cgo")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,6 @@ package secp256k1
|
|||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/rand"
|
||||
"encoding/hex"
|
||||
"io"
|
||||
|
|
@ -24,7 +23,7 @@ func generateKeyPair() (pubkey, privkey []byte) {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pubkey = elliptic.Marshal(S256(), key.X, key.Y)
|
||||
pubkey = S256().Marshal(key.X, key.Y)
|
||||
|
||||
privkey = make([]byte, 32)
|
||||
blob := key.D.Bytes()
|
||||
|
|
@ -49,7 +48,7 @@ func randSig() []byte {
|
|||
}
|
||||
|
||||
// tests for malleability
|
||||
// highest bit of signature ECDSA s value must be 0, in the 33th byte
|
||||
// the highest bit of signature ECDSA s value must be 0, in the 33th byte
|
||||
func compactSigCheck(t *testing.T, sig []byte) {
|
||||
var b = int(sig[32])
|
||||
if b < 0 {
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@ package crypto
|
|||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
|
|
@ -40,9 +39,7 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
x, y := elliptic.Unmarshal(S256(), s)
|
||||
return &ecdsa.PublicKey{Curve: S256(), X: x, Y: y}, nil
|
||||
return UnmarshalPubkey(s)
|
||||
}
|
||||
|
||||
// Sign calculates an ECDSA signature.
|
||||
|
|
@ -84,6 +81,6 @@ func CompressPubkey(pubkey *ecdsa.PublicKey) []byte {
|
|||
}
|
||||
|
||||
// S256 returns an instance of the secp256k1 curve.
|
||||
func S256() elliptic.Curve {
|
||||
func S256() EllipticCurve {
|
||||
return secp256k1.S256()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,12 +21,12 @@ package crypto
|
|||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math/big"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
btc_ecdsa "github.com/btcsuite/btcd/btcec/v2/ecdsa"
|
||||
"github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
decred_ecdsa "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
|
||||
)
|
||||
|
||||
// Ecrecover returns the uncompressed public key that created the given signature.
|
||||
|
|
@ -39,16 +39,16 @@ func Ecrecover(hash, sig []byte) ([]byte, error) {
|
|||
return bytes, err
|
||||
}
|
||||
|
||||
func sigToPub(hash, sig []byte) (*btcec.PublicKey, error) {
|
||||
func sigToPub(hash, sig []byte) (*secp256k1.PublicKey, error) {
|
||||
if len(sig) != SignatureLength {
|
||||
return nil, errors.New("invalid signature")
|
||||
}
|
||||
// Convert to btcec input format with 'recovery id' v at the beginning.
|
||||
// Convert to secp256k1 input format with 'recovery id' v at the beginning.
|
||||
btcsig := make([]byte, SignatureLength)
|
||||
btcsig[0] = sig[RecoveryIDOffset] + 27
|
||||
copy(btcsig[1:], sig)
|
||||
|
||||
pub, _, err := btc_ecdsa.RecoverCompact(btcsig, hash)
|
||||
pub, _, err := decred_ecdsa.RecoverCompact(btcsig, hash)
|
||||
return pub, err
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +58,13 @@ func SigToPub(hash, sig []byte) (*ecdsa.PublicKey, error) {
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return pub.ToECDSA(), nil
|
||||
// We need to explicitly set the curve here, because we're wrapping
|
||||
// the original curve to add (un-)marshalling
|
||||
return &ecdsa.PublicKey{
|
||||
Curve: S256(),
|
||||
X: pub.X(),
|
||||
Y: pub.Y(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Sign calculates an ECDSA signature.
|
||||
|
|
@ -73,19 +79,16 @@ func Sign(hash []byte, prv *ecdsa.PrivateKey) ([]byte, error) {
|
|||
if len(hash) != 32 {
|
||||
return nil, fmt.Errorf("hash is required to be exactly 32 bytes (%d)", len(hash))
|
||||
}
|
||||
if prv.Curve != btcec.S256() {
|
||||
if prv.Curve != S256() {
|
||||
return nil, errors.New("private key curve is not secp256k1")
|
||||
}
|
||||
// ecdsa.PrivateKey -> btcec.PrivateKey
|
||||
var priv btcec.PrivateKey
|
||||
// ecdsa.PrivateKey -> secp256k1.PrivateKey
|
||||
var priv secp256k1.PrivateKey
|
||||
if overflow := priv.Key.SetByteSlice(prv.D.Bytes()); overflow || priv.Key.IsZero() {
|
||||
return nil, errors.New("invalid private key")
|
||||
}
|
||||
defer priv.Zero()
|
||||
sig, err := btc_ecdsa.SignCompact(&priv, hash, false) // ref uncompressed pubkey
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
sig := decred_ecdsa.SignCompact(&priv, hash, false) // ref uncompressed pubkey
|
||||
// Convert to Ethereum signature format with 'recovery id' v at the end.
|
||||
v := sig[0] - 27
|
||||
copy(sig, sig[1:])
|
||||
|
|
@ -100,19 +103,19 @@ func VerifySignature(pubkey, hash, signature []byte) bool {
|
|||
if len(signature) != 64 {
|
||||
return false
|
||||
}
|
||||
var r, s btcec.ModNScalar
|
||||
var r, s secp256k1.ModNScalar
|
||||
if r.SetByteSlice(signature[:32]) {
|
||||
return false // overflow
|
||||
}
|
||||
if s.SetByteSlice(signature[32:]) {
|
||||
return false
|
||||
}
|
||||
sig := btc_ecdsa.NewSignature(&r, &s)
|
||||
key, err := btcec.ParsePubKey(pubkey)
|
||||
sig := decred_ecdsa.NewSignature(&r, &s)
|
||||
key, err := secp256k1.ParsePubKey(pubkey)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
// Reject malleable signatures. libsecp256k1 does this check but btcec doesn't.
|
||||
// Reject malleable signatures. libsecp256k1 does this check but decred doesn't.
|
||||
if s.IsOverHalfOrder() {
|
||||
return false
|
||||
}
|
||||
|
|
@ -124,11 +127,17 @@ func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) {
|
|||
if len(pubkey) != 33 {
|
||||
return nil, errors.New("invalid compressed public key length")
|
||||
}
|
||||
key, err := btcec.ParsePubKey(pubkey)
|
||||
key, err := secp256k1.ParsePubKey(pubkey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return key.ToECDSA(), nil
|
||||
// We need to explicitly set the curve here, because we're wrapping
|
||||
// the original curve to add (un-)marshalling
|
||||
return &ecdsa.PublicKey{
|
||||
Curve: S256(),
|
||||
X: key.X(),
|
||||
Y: key.Y(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// CompressPubkey encodes a public key to the 33-byte compressed format. The
|
||||
|
|
@ -139,14 +148,46 @@ func DecompressPubkey(pubkey []byte) (*ecdsa.PublicKey, error) {
|
|||
// when constructing a PrivateKey.
|
||||
func CompressPubkey(pubkey *ecdsa.PublicKey) []byte {
|
||||
// NOTE: the coordinates may be validated with
|
||||
// btcec.ParsePubKey(FromECDSAPub(pubkey))
|
||||
var x, y btcec.FieldVal
|
||||
// secp256k1.ParsePubKey(FromECDSAPub(pubkey))
|
||||
var x, y secp256k1.FieldVal
|
||||
x.SetByteSlice(pubkey.X.Bytes())
|
||||
y.SetByteSlice(pubkey.Y.Bytes())
|
||||
return btcec.NewPublicKey(&x, &y).SerializeCompressed()
|
||||
return secp256k1.NewPublicKey(&x, &y).SerializeCompressed()
|
||||
}
|
||||
|
||||
// S256 returns an instance of the secp256k1 curve.
|
||||
func S256() elliptic.Curve {
|
||||
return btcec.S256()
|
||||
func S256() EllipticCurve {
|
||||
return btCurve{secp256k1.S256()}
|
||||
}
|
||||
|
||||
type btCurve struct {
|
||||
*secp256k1.KoblitzCurve
|
||||
}
|
||||
|
||||
// Marshal converts a point given as (x, y) into a byte slice.
|
||||
func (curve btCurve) Marshal(x, y *big.Int) []byte {
|
||||
byteLen := (curve.Params().BitSize + 7) / 8
|
||||
|
||||
ret := make([]byte, 1+2*byteLen)
|
||||
ret[0] = 4 // uncompressed point
|
||||
|
||||
x.FillBytes(ret[1 : 1+byteLen])
|
||||
y.FillBytes(ret[1+byteLen : 1+2*byteLen])
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
// Unmarshal converts a point, serialised by Marshal, into an x, y pair. On
|
||||
// error, x = nil.
|
||||
func (curve btCurve) Unmarshal(data []byte) (x, y *big.Int) {
|
||||
byteLen := (curve.Params().BitSize + 7) / 8
|
||||
if len(data) != 1+2*byteLen {
|
||||
return nil, nil
|
||||
}
|
||||
if data[0] != 4 { // uncompressed form
|
||||
return nil, nil
|
||||
}
|
||||
x = new(big.Int).SetBytes(data[1 : 1+byteLen])
|
||||
y = new(big.Int).SetBytes(data[1+byteLen:])
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,7 @@ func TestVerifySignature(t *testing.T) {
|
|||
wrongkey := common.CopyBytes(testpubkey)
|
||||
wrongkey[10]++
|
||||
if VerifySignature(wrongkey, testmsg, sig) {
|
||||
t.Errorf("signature valid with with wrong public key")
|
||||
t.Errorf("signature valid with wrong public key")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
3
go.mod
3
go.mod
|
|
@ -41,10 +41,10 @@ require (
|
|||
)
|
||||
|
||||
require (
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.4
|
||||
github.com/consensys/gnark-crypto v0.10.0
|
||||
github.com/crate-crypto/go-kzg-4844 v0.7.0
|
||||
github.com/deckarep/golang-set v1.8.0
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1
|
||||
github.com/dop251/goja v0.0.0-20200721192441-a695b0cdd498
|
||||
github.com/ethereum/c-kzg-4844 v0.4.0
|
||||
github.com/go-yaml/yaml v2.1.0+incompatible
|
||||
|
|
@ -64,7 +64,6 @@ require (
|
|||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/consensys/bavard v0.1.13 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.6.0 // indirect
|
||||
github.com/dlclark/regexp2 v1.10.0 // indirect
|
||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
||||
|
|
|
|||
2
go.sum
2
go.sum
|
|
@ -8,8 +8,6 @@ github.com/bits-and-blooms/bitset v1.5.0 h1:NpE8frKRLGHIcEzkR+gZhiioW1+WbYV6fKwD
|
|||
github.com/bits-and-blooms/bitset v1.5.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA=
|
||||
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6 h1:Eey/GGQ/E5Xp1P2Lyx1qj007hLZfbi0+CoVeJruGCtI=
|
||||
github.com/btcsuite/btcd v0.0.0-20171128150713-2e60448ffcc6/go.mod h1:Dmm/EzmjnCiweXmzRIAiUWCInVmPgjkzgv5k4tVyXiQ=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.4 h1:3EJjcN70HCu/mwqlUsGK8GcNVyLVxFDlWurTXGPFfiQ=
|
||||
github.com/btcsuite/btcd/btcec/v2 v2.3.4/go.mod h1:zYzJ8etWJQIv1Ogk7OzpWjowwOdXY1W/17j2MW85J04=
|
||||
github.com/cespare/cp v1.1.1 h1:nCb6ZLdB7NRaqsm91JtQTAme2SKJzXVsdPIPkyJr1MU=
|
||||
github.com/cespare/cp v1.1.1/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
|
||||
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
|
|
|
|||
|
|
@ -23,11 +23,11 @@ import (
|
|||
"math/big"
|
||||
|
||||
cloudflare "github.com/XinFinOrg/XDPoSChain/crypto/bn256/cloudflare"
|
||||
gnark "github.com/XinFinOrg/XDPoSChain/crypto/bn256/gnark"
|
||||
google "github.com/XinFinOrg/XDPoSChain/crypto/bn256/google"
|
||||
"github.com/consensys/gnark-crypto/ecc/bn254"
|
||||
)
|
||||
|
||||
func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *bn254.G1Affine) {
|
||||
func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *gnark.G1) {
|
||||
_, xc, err := cloudflare.RandomG1(input)
|
||||
if err != nil {
|
||||
// insufficient input
|
||||
|
|
@ -37,14 +37,14 @@ func getG1Points(input io.Reader) (*cloudflare.G1, *google.G1, *bn254.G1Affine)
|
|||
if _, err := xg.Unmarshal(xc.Marshal()); err != nil {
|
||||
panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err))
|
||||
}
|
||||
xs := new(bn254.G1Affine)
|
||||
if err := xs.Unmarshal(xc.Marshal()); err != nil {
|
||||
xs := new(gnark.G1)
|
||||
if _, err := xs.Unmarshal(xc.Marshal()); err != nil {
|
||||
panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err))
|
||||
}
|
||||
return xc, xg, xs
|
||||
}
|
||||
|
||||
func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *bn254.G2Affine) {
|
||||
func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *gnark.G2) {
|
||||
_, xc, err := cloudflare.RandomG2(input)
|
||||
if err != nil {
|
||||
// insufficient input
|
||||
|
|
@ -54,14 +54,14 @@ func getG2Points(input io.Reader) (*cloudflare.G2, *google.G2, *bn254.G2Affine)
|
|||
if _, err := xg.Unmarshal(xc.Marshal()); err != nil {
|
||||
panic(fmt.Sprintf("Could not marshal cloudflare -> google: %v", err))
|
||||
}
|
||||
xs := new(bn254.G2Affine)
|
||||
if err := xs.Unmarshal(xc.Marshal()); err != nil {
|
||||
xs := new(gnark.G2)
|
||||
if _, err := xs.Unmarshal(xc.Marshal()); err != nil {
|
||||
panic(fmt.Sprintf("Could not marshal cloudflare -> gnark: %v", err))
|
||||
}
|
||||
return xc, xg, xs
|
||||
}
|
||||
|
||||
// fuzzAdd fuzzez bn256 addition between the Google and Cloudflare libraries.
|
||||
// fuzzAdd fuzzes bn256 addition between the Google, Cloudflare and Gnark libraries.
|
||||
func fuzzAdd(data []byte) int {
|
||||
input := bytes.NewReader(data)
|
||||
xc, xg, xs := getG1Points(input)
|
||||
|
|
@ -72,7 +72,7 @@ func fuzzAdd(data []byte) int {
|
|||
if yc == nil {
|
||||
return 0
|
||||
}
|
||||
// Ensure both libs can parse the second curve point
|
||||
// Ensure libs can parse the second curve point
|
||||
// Add the two points and ensure they result in the same output
|
||||
rc := new(cloudflare.G1)
|
||||
rc.Add(xc, yc)
|
||||
|
|
@ -80,9 +80,8 @@ func fuzzAdd(data []byte) int {
|
|||
rg := new(google.G1)
|
||||
rg.Add(xg, yg)
|
||||
|
||||
tmpX := new(bn254.G1Jac).FromAffine(xs)
|
||||
tmpY := new(bn254.G1Jac).FromAffine(ys)
|
||||
rs := new(bn254.G1Affine).FromJacobian(tmpX.AddAssign(tmpY))
|
||||
rs := new(gnark.G1)
|
||||
rs.Add(xs, ys)
|
||||
|
||||
if !bytes.Equal(rc.Marshal(), rg.Marshal()) {
|
||||
panic("add mismatch: cloudflare/google")
|
||||
|
|
@ -94,8 +93,8 @@ func fuzzAdd(data []byte) int {
|
|||
return 1
|
||||
}
|
||||
|
||||
// fuzzMul fuzzez bn256 scalar multiplication between the Google and Cloudflare
|
||||
// libraries.
|
||||
// fuzzMul fuzzes bn256 scalar multiplication between the Google, Cloudflare
|
||||
// and Gnark libraries.
|
||||
func fuzzMul(data []byte) int {
|
||||
input := bytes.NewReader(data)
|
||||
pc, pg, ps := getG1Points(input)
|
||||
|
|
@ -122,15 +121,13 @@ func fuzzMul(data []byte) int {
|
|||
rg := new(google.G1)
|
||||
rg.ScalarMult(pg, new(big.Int).SetBytes(buf))
|
||||
|
||||
rs := new(bn254.G1Jac)
|
||||
psJac := new(bn254.G1Jac).FromAffine(ps)
|
||||
rs.ScalarMultiplication(psJac, new(big.Int).SetBytes(buf))
|
||||
rsAffine := new(bn254.G1Affine).FromJacobian(rs)
|
||||
rs := new(gnark.G1)
|
||||
rs.ScalarMult(ps, new(big.Int).SetBytes(buf))
|
||||
|
||||
if !bytes.Equal(rc.Marshal(), rg.Marshal()) {
|
||||
panic("scalar mul mismatch: cloudflare/google")
|
||||
}
|
||||
if !bytes.Equal(rc.Marshal(), rsAffine.Marshal()) {
|
||||
if !bytes.Equal(rc.Marshal(), rs.Marshal()) {
|
||||
panic("scalar mul mismatch: cloudflare/gnark")
|
||||
}
|
||||
return 1
|
||||
|
|
@ -150,17 +147,26 @@ func fuzzPair(data []byte) int {
|
|||
// Pair the two points and ensure they result in the same output
|
||||
clPair := cloudflare.Pair(pc, tc).Marshal()
|
||||
gPair := google.Pair(pg, tg).Marshal()
|
||||
sPair := gnark.Pair(ps, ts).Marshal()
|
||||
|
||||
if !bytes.Equal(clPair, gPair) {
|
||||
panic("pairing mismatch: cloudflare/google")
|
||||
}
|
||||
cPair, err := bn254.Pair([]bn254.G1Affine{*ps}, []bn254.G2Affine{*ts})
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("gnark/bn254 encountered error: %v", err))
|
||||
|
||||
normalizedClPair := normalizeGTToGnark(clPair).Marshal()
|
||||
if !bytes.Equal(normalizedClPair, sPair) {
|
||||
panic("pairing mismatch: cloudflare/gnark")
|
||||
}
|
||||
|
||||
// gnark uses a different pairing algorithm which might produce
|
||||
// different but also correct outputs, we need to scale the output by s
|
||||
return 1
|
||||
}
|
||||
|
||||
// normalizeGTToGnark scales a Cloudflare/Google GT element by `s`
|
||||
// so that it can be compared with a gnark GT point.
|
||||
//
|
||||
// For the definition of `s` see 3.5 in https://eprint.iacr.org/2015/192.pdf
|
||||
func normalizeGTToGnark(cloudflareOrGoogleGT []byte) *gnark.GT {
|
||||
// Compute s = 2*u(6*u^2 + 3*u + 1)
|
||||
u, _ := new(big.Int).SetString("0x44e992b44a6909f1", 0)
|
||||
u_exp2 := new(big.Int).Exp(u, big.NewInt(2), nil) // u^2
|
||||
u_6_exp2 := new(big.Int).Mul(big.NewInt(6), u_exp2) // 6*u^2
|
||||
|
|
@ -170,14 +176,12 @@ func fuzzPair(data []byte) int {
|
|||
u_2 := new(big.Int).Mul(big.NewInt(2), u) // 2*u
|
||||
s := u_2.Mul(u_2, inner) // 2*u(6*u^2 + 3*u + 1)
|
||||
|
||||
gRes := new(bn254.GT)
|
||||
if err := gRes.SetBytes(clPair); err != nil {
|
||||
// Scale the Cloudflare/Google GT element by `s`
|
||||
gRes := new(gnark.GT)
|
||||
if err := gRes.Unmarshal(cloudflareOrGoogleGT); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
gRes = gRes.Exp(*gRes, s)
|
||||
if !bytes.Equal(cPair.Marshal(), gRes.Marshal()) {
|
||||
panic("pairing mismatch: cloudflare/gnark")
|
||||
}
|
||||
|
||||
return 1
|
||||
return gRes
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/XinFinOrg/XDPoSChain/crypto/secp256k1"
|
||||
"github.com/btcsuite/btcd/btcec/v2"
|
||||
dcred_secp256k1 "github.com/decred/dcrd/dcrec/secp256k1/v4"
|
||||
)
|
||||
|
||||
func TestFuzzer(t *testing.T) {
|
||||
|
|
@ -38,7 +38,7 @@ func Fuzz(f *testing.F) {
|
|||
func fuzz(dataP1, dataP2 []byte) {
|
||||
var (
|
||||
curveA = secp256k1.S256()
|
||||
curveB = btcec.S256()
|
||||
curveB = dcred_secp256k1.S256()
|
||||
)
|
||||
// first point
|
||||
x1, y1 := curveB.ScalarBaseMult(dataP1)
|
||||
|
|
|
|||
Loading…
Reference in a new issue