diff --git a/core/vm/privacy/ringct.go b/core/vm/privacy/ringct.go
index 9e70ddddf2..d52407b311 100644
--- a/core/vm/privacy/ringct.go
+++ b/core/vm/privacy/ringct.go
@@ -13,6 +13,8 @@ import (
"github.com/XinFinOrg/XDPoSChain/common"
"github.com/XinFinOrg/XDPoSChain/crypto"
+ "github.com/XinFinOrg/XDPoSChain/crypto/secp256k1"
+
"github.com/XinFinOrg/XDPoSChain/log"
)
@@ -259,6 +261,10 @@ func Deserialize(r []byte) (*RingSignature, error) {
sig.SerializedRing = r
+ if !Verify(sig, false) {
+ return nil, errors.New("failed to deserialize, invalid ring signature")
+ }
+
return sig, nil
}
@@ -357,7 +363,8 @@ func Sign(m [32]byte, rings []Ring, privkeys []*ecdsa.PrivateKey, s int) (*RingS
for i := 0; i < numRing; i++ {
pubkeys[i] = &privkeys[i].PublicKey
}
- curve := pubkeys[0].Curve
+ //cast to BitCurve used in go-eth since elliptic.Curve.Add() and elliptic.Curve.ScalarMult() is deprecated
+ curve := pubkeys[0].Curve.(*secp256k1.BitCurve)
sig := new(RingSignature)
sig.Size = ringsize
sig.NumRing = numRing
@@ -504,9 +511,24 @@ func Verify(sig *RingSignature, verifyMes bool) bool {
S := sig.S
C := make([]*big.Int, ringsize+1)
C[0] = sig.C
- curve := sig.Curve
+ //cast to BitCurve used in go-eth since elliptic.Curve.Add() and elliptic.Curve.ScalarMult() is deprecated
+ curve := sig.Curve.(*secp256k1.BitCurve)
image := sig.I
+ //check on curve
+ for i := 0; i < numRing; i++ {
+ onCurve := curve.IsOnCurve(image[i].X, image[i].Y)
+ if !onCurve {
+ return false
+ }
+ for j := 0; j < ringsize; j++ {
+ onCurve := curve.IsOnCurve(rings[i][j].X, rings[i][j].Y)
+ if !onCurve {
+ return false
+ }
+ }
+ }
+
// calculate c[i+1] = H(m, s[i]*G + c[i]*P[i])
// and c[0] = H)(m, s[n-1]*G + c[n-1]*P[n-1]) where n is the ring size
//log.Info("C", "0", common.Bytes2Hex(C[0].Bytes()))
diff --git a/core/vm/privacy/ringct_test.go b/core/vm/privacy/ringct_test.go
index faef37f86a..49dbc3a5ab 100644
--- a/core/vm/privacy/ringct_test.go
+++ b/core/vm/privacy/ringct_test.go
@@ -9,6 +9,8 @@ import (
"github.com/XinFinOrg/XDPoSChain/crypto"
"github.com/stretchr/testify/assert"
+
+ "github.com/XinFinOrg/XDPoSChain/crypto/secp256k1"
)
func TestSign(t *testing.T) {
@@ -130,6 +132,104 @@ func TestPadTo32Bytes(t *testing.T) {
assert.True(t, bytes.Equal(PadTo32Bytes(arr[10:41]), arr[9:41]), "Test PadTo32Bytes shorter than 32 bytes #10")
}
+func TestCurveAddNegative(t *testing.T) {
+ curve := crypto.S256().(*secp256k1.BitCurve)
+
+ x1, y1 := curve.ScalarBaseMult(new(big.Int).SetUint64(uint64(2)).Bytes())
+ fmt.Printf("Point(%x, %x)\n", x1, y1)
+
+ x2 := x1
+ y2 := new(big.Int).Neg(y1) // negative of point (x1,y1)
+
+ x3, y3 := curve.Add(x1, y1, x2, y2)
+ fmt.Printf("Output is Point(%x, %x)\n", x3, y3)
+
+ x0 := new(big.Int).SetUint64(uint64(0))
+ y0 := new(big.Int).SetUint64(uint64(0)) // infinity
+
+ if (x3.Cmp(x0) == 0) && (y3.Cmp(y0) == 0) {
+ // fmt.Printf("Correct, add negative of self should yield (0,0)")
+ } else {
+ t.Error("Incorrect, add negative of self did not yield (0,0)")
+ }
+}
+
+func TestCurveAddZero(t *testing.T) {
+ // curve := crypto.S256()
+ curve := crypto.S256().(*secp256k1.BitCurve)
+
+ x1, y1 := curve.ScalarBaseMult(new(big.Int).SetUint64(uint64(1)).Bytes())
+ fmt.Printf("Point(%x, %x)\n", x1, y1)
+
+ x0 := new(big.Int).SetUint64(uint64(0))
+ y0 := new(big.Int).SetUint64(uint64(0)) // infinity
+ fmt.Printf("Is point (%d,%d) on the curve: %t \n", x0, y0, curve.IsOnCurve(x0, y0))
+
+ x2, y2 := curve.Add(x1, y1, x0, y0)
+ fmt.Printf("Output is Point(%x, %x)\n", x2, y2)
+
+ if (x1.Cmp(x2) == 0) && (y1.Cmp(y2) == 0) {
+ // fmt.Printf("Correct, Point on curve is the same after Zero addition\n")
+ } else {
+ t.Error("Incorrect, Point on curve changed after Zero addition\n")
+ }
+}
+
+func TestOnCurveVerify(t *testing.T) {
+ numRing := 5
+ ringSize := 10
+ s := 5
+ rings, privkeys, m, err := GenerateMultiRingParams(numRing, ringSize, s)
+ ringSignature, err := Sign(m, rings, privkeys, s)
+ if err != nil {
+ t.Error("Failed to create Ring signature")
+ }
+
+ valid := Verify(ringSignature, false)
+ if !valid {
+ t.Error("Incorrect, unmodified ringSignature should be valid")
+ }
+
+ ringsModified := ringSignature.Ring
+ ringsModified[0][0].X = big.NewInt(1)
+ ringsModified[0][0].Y = big.NewInt(1)
+ valid = Verify(ringSignature, false)
+ if valid {
+ t.Error("Incorrect, modified ringSignature should be invalid")
+ }
+}
+
+func TestOnCurveDeserialize(t *testing.T) {
+ numRing := 5
+ ringSize := 10
+ s := 5
+ rings, privkeys, m, err := GenerateMultiRingParams(numRing, ringSize, s)
+ ringSignature, err := Sign(m, rings, privkeys, s)
+ if err != nil {
+ t.Error("Failed to create Ring signature")
+ }
+
+ sig, err := ringSignature.Serialize()
+ if err != nil {
+ t.Error("Failed to Serialize input Ring signature")
+ }
+ _, err = Deserialize(sig)
+ if err != nil {
+ t.Error("Failed to Deserialize")
+ }
+
+ ringsModified := ringSignature.Ring
+ ringsModified[0][0].X = big.NewInt(1)
+ ringsModified[0][0].Y = big.NewInt(1)
+
+ sig, err = ringSignature.Serialize()
+ if err != nil {
+ t.Error("Failed to Serialize input Ring signature")
+ }
+ _, err = Deserialize(sig)
+ assert.EqualError(t, err, "failed to deserialize, invalid ring signature")
+}
+
func TestCurveScalarMult(t *testing.T) {
curve := crypto.S256()
diff --git a/crypto/secp256k1/LICENSE b/crypto/secp256k1/LICENSE
new file mode 100644
index 0000000000..f9090e1423
--- /dev/null
+++ b/crypto/secp256k1/LICENSE
@@ -0,0 +1,31 @@
+Copyright (c) 2010 The Go Authors. All rights reserved.
+Copyright (c) 2011 ThePiachu. All rights reserved.
+Copyright (c) 2015 Jeffrey Wilcke. All rights reserved.
+Copyright (c) 2015 Felix Lange. All rights reserved.
+Copyright (c) 2015 Gustav Simonsson. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of the copyright holder. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/crypto/secp256k1/curve.go b/crypto/secp256k1/curve.go
index ecf7a238f0..9b26ab2928 100644
--- a/crypto/secp256k1/curve.go
+++ b/crypto/secp256k1/curve.go
@@ -1,5 +1,6 @@
// Copyright 2010 The Go Authors. All rights reserved.
// Copyright 2011 ThePiachu. All rights reserved.
+// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
@@ -34,16 +35,28 @@ package secp256k1
import (
"crypto/elliptic"
"math/big"
- "unsafe"
-
- "github.com/XinFinOrg/XDPoSChain/common/math"
)
-/*
-#include "libsecp256k1/include/secp256k1.h"
-extern int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, const unsigned char *point, const unsigned char *scalar);
-*/
-import "C"
+const (
+ // number of bits in a big.Word
+ wordBits = 32 << (uint64(^big.Word(0)) >> 63)
+ // number of bytes in a big.Word
+ wordBytes = wordBits / 8
+)
+
+// readBits encodes the absolute value of bigint as big-endian bytes. Callers
+// must ensure that buf has enough space. If buf is too short the result will
+// be incomplete.
+func readBits(bigint *big.Int, buf []byte) {
+ i := len(buf)
+ for _, d := range bigint.Bits() {
+ for j := 0; j < wordBytes && i > 0; j++ {
+ i--
+ buf[i] = byte(d)
+ d >>= 8
+ }
+ }
+}
// This code is from https://github.com/ThePiachu/GoBit and implements
// several Koblitz elliptic curves over prime fields.
@@ -77,7 +90,7 @@ func (BitCurve *BitCurve) Params() *elliptic.CurveParams {
}
}
-// IsOnBitCurve returns true if the given (x,y) lies on the BitCurve.
+// IsOnCurve returns true if the given (x,y) lies on the BitCurve.
func (BitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool {
// y² = x³ + b
y2 := new(big.Int).Mul(y, y) //y²
@@ -92,7 +105,6 @@ func (BitCurve *BitCurve) IsOnCurve(x, y *big.Int) bool {
return x3.Cmp(y2) == 0
}
-//TODO: double check if the function is okay
// 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) {
@@ -113,7 +125,18 @@ func (BitCurve *BitCurve) affineFromJacobian(x, y, z *big.Int) (xOut, yOut *big.
// Add returns the sum of (x1,y1) and (x2,y2)
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 {
+ return x2, y2
+ }
+ if x2.Sign() == 0 && y2.Sign() == 0 {
+ return x1, y1
+ }
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.addJacobian(x1, y1, z, x2, y2, z))
}
@@ -222,40 +245,6 @@ func (BitCurve *BitCurve) doubleJacobian(x, y, z *big.Int) (*big.Int, *big.Int,
return x3, y3, z3
}
-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 {
- panic("can't handle scalars > 256 bits")
- }
- // NOTE: potential timing issue
- padded := make([]byte, 32)
- copy(padded[32-len(scalar):], scalar)
- scalar = padded
-
- // Do the multiplication in C, updating point.
- point := make([]byte, 64)
- math.ReadBits(Bx, point[:32])
- math.ReadBits(By, point[32:])
- pointPtr := (*C.uchar)(unsafe.Pointer(&point[0]))
- scalarPtr := (*C.uchar)(unsafe.Pointer(&scalar[0]))
- res := C.secp256k1_ext_scalar_mul(context, pointPtr, scalarPtr)
-
- // 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
- }
- if res != 1 {
- return nil, nil
- }
- return x, y
-}
-
// 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) {
@@ -268,8 +257,8 @@ 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
- math.ReadBits(x, ret[1:1+byteLen])
- math.ReadBits(y, ret[1+byteLen:])
+ readBits(x, ret[1:1+byteLen])
+ readBits(y, ret[1+byteLen:])
return ret
}
@@ -293,12 +282,12 @@ var theCurve = new(BitCurve)
func init() {
// See SEC 2 section 2.7.1
// curve parameters taken from:
- // http://www.secg.org/collateral/sec2_final.pdf
- theCurve.P, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16)
- theCurve.N, _ = new(big.Int).SetString("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16)
- theCurve.B, _ = new(big.Int).SetString("0000000000000000000000000000000000000000000000000000000000000007", 16)
- theCurve.Gx, _ = new(big.Int).SetString("79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 16)
- theCurve.Gy, _ = new(big.Int).SetString("483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 16)
+ // http://www.secg.org/sec2-v2.pdf
+ theCurve.P, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 0)
+ theCurve.N, _ = new(big.Int).SetString("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 0)
+ theCurve.B, _ = new(big.Int).SetString("0x0000000000000000000000000000000000000000000000000000000000000007", 0)
+ theCurve.Gx, _ = new(big.Int).SetString("0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798", 0)
+ theCurve.Gy, _ = new(big.Int).SetString("0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8", 0)
theCurve.BitSize = 256
}
diff --git a/crypto/secp256k1/dummy.go b/crypto/secp256k1/dummy.go
new file mode 100644
index 0000000000..65a75080f6
--- /dev/null
+++ b/crypto/secp256k1/dummy.go
@@ -0,0 +1,21 @@
+//go:build dummy
+// +build dummy
+
+// This file is part of a workaround for `go mod vendor` which won't vendor
+// C files if there's no Go file in the same directory.
+// This would prevent the crypto/secp256k1/libsecp256k1/include/secp256k1.h file to be vendored.
+//
+// This Go file imports the c directory where there is another dummy.go file which
+// is the second part of this workaround.
+//
+// These two files combined make it so `go mod vendor` behaves correctly.
+//
+// See this issue for reference: https://github.com/golang/go/issues/26366
+
+package secp256k1
+
+import (
+ _ "github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/include"
+ _ "github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src"
+ _ "github.com/ethereum/go-ethereum/crypto/secp256k1/libsecp256k1/src/modules/recovery"
+)
diff --git a/crypto/secp256k1/ext.h b/crypto/secp256k1/ext.h
index 9b043c724e..e422fe4b49 100644
--- a/crypto/secp256k1/ext.h
+++ b/crypto/secp256k1/ext.h
@@ -1,18 +1,6 @@
-// Copyright 2015 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
+// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
// secp256k1_context_create_sign_verify creates a context for signing and signature verification.
static secp256k1_context* secp256k1_context_create_sign_verify() {
diff --git a/crypto/secp256k1/libsecp256k1/contrib/dummy.go b/crypto/secp256k1/libsecp256k1/contrib/dummy.go
new file mode 100644
index 0000000000..2c946210c5
--- /dev/null
+++ b/crypto/secp256k1/libsecp256k1/contrib/dummy.go
@@ -0,0 +1,8 @@
+//go:build dummy
+// +build dummy
+
+// Package c contains only a C file.
+//
+// This Go file is part of a workaround for `go mod vendor`.
+// Please see the file crypto/secp256k1/dummy.go for more information.
+package contrib
diff --git a/crypto/secp256k1/libsecp256k1/dummy.go b/crypto/secp256k1/libsecp256k1/dummy.go
new file mode 100644
index 0000000000..04bbe3d76e
--- /dev/null
+++ b/crypto/secp256k1/libsecp256k1/dummy.go
@@ -0,0 +1,8 @@
+//go:build dummy
+// +build dummy
+
+// Package c contains only a C file.
+//
+// This Go file is part of a workaround for `go mod vendor`.
+// Please see the file crypto/secp256k1/dummy.go for more information.
+package libsecp256k1
diff --git a/crypto/secp256k1/libsecp256k1/include/dummy.go b/crypto/secp256k1/libsecp256k1/include/dummy.go
new file mode 100644
index 0000000000..64c71b8451
--- /dev/null
+++ b/crypto/secp256k1/libsecp256k1/include/dummy.go
@@ -0,0 +1,8 @@
+//go:build dummy
+// +build dummy
+
+// Package c contains only a C file.
+//
+// This Go file is part of a workaround for `go mod vendor`.
+// Please see the file crypto/secp256k1/dummy.go for more information.
+package include
diff --git a/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s b/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s
index 5df561f2fc..5a9cc3ffcf 100644
--- a/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s
+++ b/crypto/secp256k1/libsecp256k1/src/asm/field_10x26_arm.s
@@ -11,7 +11,7 @@ Note:
- To avoid unnecessary loads and make use of available registers, two
'passes' have every time been interleaved, with the odd passes accumulating c' and d'
- which will be added to c and d respectively in the the even passes
+ which will be added to c and d respectively in the even passes
*/
@@ -23,7 +23,7 @@ Note:
.eabi_attribute 10, 0 @ Tag_FP_arch = none
.eabi_attribute 24, 1 @ Tag_ABI_align_needed = 8-byte
.eabi_attribute 25, 1 @ Tag_ABI_align_preserved = 8-byte, except leaf SP
- .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Agressive Speed
+ .eabi_attribute 30, 2 @ Tag_ABI_optimization_goals = Aggressive Speed
.eabi_attribute 34, 1 @ Tag_CPU_unaligned_access = v6
.text
diff --git a/crypto/secp256k1/libsecp256k1/src/dummy.go b/crypto/secp256k1/libsecp256k1/src/dummy.go
new file mode 100644
index 0000000000..2df270adc3
--- /dev/null
+++ b/crypto/secp256k1/libsecp256k1/src/dummy.go
@@ -0,0 +1,8 @@
+//go:build dummy
+// +build dummy
+
+// Package c contains only a C file.
+//
+// This Go file is part of a workaround for `go mod vendor`.
+// Please see the file crypto/secp256k1/dummy.go for more information.
+package src
diff --git a/crypto/secp256k1/libsecp256k1/src/modules/dummy.go b/crypto/secp256k1/libsecp256k1/src/modules/dummy.go
new file mode 100644
index 0000000000..99c538db51
--- /dev/null
+++ b/crypto/secp256k1/libsecp256k1/src/modules/dummy.go
@@ -0,0 +1,8 @@
+//go:build dummy
+// +build dummy
+
+// Package c contains only a C file.
+//
+// This Go file is part of a workaround for `go mod vendor`.
+// Please see the file crypto/secp256k1/dummy.go for more information.
+package module
diff --git a/crypto/secp256k1/libsecp256k1/src/modules/ecdh/dummy.go b/crypto/secp256k1/libsecp256k1/src/modules/ecdh/dummy.go
new file mode 100644
index 0000000000..48c2e0aa54
--- /dev/null
+++ b/crypto/secp256k1/libsecp256k1/src/modules/ecdh/dummy.go
@@ -0,0 +1,8 @@
+//go:build dummy
+// +build dummy
+
+// Package c contains only a C file.
+//
+// This Go file is part of a workaround for `go mod vendor`.
+// Please see the file crypto/secp256k1/dummy.go for more information.
+package ecdh
diff --git a/crypto/secp256k1/libsecp256k1/src/modules/recovery/dummy.go b/crypto/secp256k1/libsecp256k1/src/modules/recovery/dummy.go
new file mode 100644
index 0000000000..8efbd7abe7
--- /dev/null
+++ b/crypto/secp256k1/libsecp256k1/src/modules/recovery/dummy.go
@@ -0,0 +1,8 @@
+//go:build dummy
+// +build dummy
+
+// Package c contains only a C file.
+//
+// This Go file is part of a workaround for `go mod vendor`.
+// Please see the file crypto/secp256k1/dummy.go for more information.
+package recovery
diff --git a/crypto/secp256k1/libsecp256k1/src/num.h b/crypto/secp256k1/libsecp256k1/src/num.h
index 7bb9c5be8c..eff842200f 100644
--- a/crypto/secp256k1/libsecp256k1/src/num.h
+++ b/crypto/secp256k1/libsecp256k1/src/num.h
@@ -54,7 +54,7 @@ static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const se
even if r was negative. */
static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m);
-/** Right-shift the passed number by bits bits. */
+/** Right-shift the passed number by bits. */
static void secp256k1_num_shift(secp256k1_num *r, int bits);
/** Check whether a number is zero. */
diff --git a/crypto/secp256k1/libsecp256k1/src/secp256k1.c b/crypto/secp256k1/libsecp256k1/src/secp256k1.c
index fb8b882faa..7d637bfad1 100755
--- a/crypto/secp256k1/libsecp256k1/src/secp256k1.c
+++ b/crypto/secp256k1/libsecp256k1/src/secp256k1.c
@@ -26,7 +26,6 @@
} while(0)
static void default_illegal_callback_fn(const char* str, void* data) {
- (void)data;
fprintf(stderr, "[libsecp256k1] illegal argument: %s\n", str);
abort();
}
@@ -37,7 +36,6 @@ static const secp256k1_callback default_illegal_callback = {
};
static void default_error_callback_fn(const char* str, void* data) {
- (void)data;
fprintf(stderr, "[libsecp256k1] internal consistency check failed: %s\n", str);
abort();
}
diff --git a/crypto/secp256k1/panic_cb.go b/crypto/secp256k1/panic_cb.go
index e0e9034ee0..a30b04f51b 100644
--- a/crypto/secp256k1/panic_cb.go
+++ b/crypto/secp256k1/panic_cb.go
@@ -1,18 +1,9 @@
-// Copyright 2015 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
+// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+//go:build !gofuzz && cgo
+// +build !gofuzz,cgo
package secp256k1
diff --git a/crypto/secp256k1/scalar_mult_cgo.go b/crypto/secp256k1/scalar_mult_cgo.go
new file mode 100644
index 0000000000..8afa9d023b
--- /dev/null
+++ b/crypto/secp256k1/scalar_mult_cgo.go
@@ -0,0 +1,57 @@
+// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+//go:build !gofuzz && cgo
+// +build !gofuzz,cgo
+
+package secp256k1
+
+import (
+ "math/big"
+ "unsafe"
+)
+
+/*
+
+#include "libsecp256k1/include/secp256k1.h"
+
+extern int secp256k1_ext_scalar_mul(const secp256k1_context* ctx, const unsigned char *point, const unsigned char *scalar);
+
+*/
+import "C"
+
+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 {
+ panic("can't handle scalars > 256 bits")
+ }
+ // NOTE: potential timing issue
+ padded := make([]byte, 32)
+ copy(padded[32-len(scalar):], scalar)
+ scalar = padded
+
+ // Do the multiplication in C, updating point.
+ point := make([]byte, 64)
+ readBits(Bx, point[:32])
+ readBits(By, point[32:])
+
+ pointPtr := (*C.uchar)(unsafe.Pointer(&point[0]))
+ scalarPtr := (*C.uchar)(unsafe.Pointer(&scalar[0]))
+ res := C.secp256k1_ext_scalar_mul(context, pointPtr, scalarPtr)
+
+ // 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
+ }
+ if res != 1 {
+ return nil, nil
+ }
+ return x, y
+}
diff --git a/crypto/secp256k1/scalar_mult_nocgo.go b/crypto/secp256k1/scalar_mult_nocgo.go
new file mode 100644
index 0000000000..22f53ac6ae
--- /dev/null
+++ b/crypto/secp256k1/scalar_mult_nocgo.go
@@ -0,0 +1,14 @@
+// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+//go:build gofuzz || !cgo
+// +build gofuzz !cgo
+
+package secp256k1
+
+import "math/big"
+
+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")
+}
diff --git a/crypto/secp256k1/secp256.go b/crypto/secp256k1/secp256.go
index eefbb99ee4..61abc1eaf0 100644
--- a/crypto/secp256k1/secp256.go
+++ b/crypto/secp256k1/secp256.go
@@ -1,18 +1,9 @@
-// Copyright 2015 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
+// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+//go:build !gofuzz && cgo
+// +build !gofuzz,cgo
// Package secp256k1 wraps the bitcoin secp256k1 C library.
package secp256k1
@@ -20,12 +11,24 @@ package secp256k1
/*
#cgo CFLAGS: -I./libsecp256k1
#cgo CFLAGS: -I./libsecp256k1/src/
+
+#ifdef __SIZEOF_INT128__
+# define HAVE___INT128
+# define USE_FIELD_5X52
+# define USE_SCALAR_4X64
+#else
+# define USE_FIELD_10X26
+# define USE_SCALAR_8X32
+#endif
+
+#ifndef NDEBUG
+# define NDEBUG
+#endif
+
+#define USE_ENDOMORPHISM
#define USE_NUM_NONE
-#define USE_FIELD_10X26
#define USE_FIELD_INV_BUILTIN
-#define USE_SCALAR_8X32
#define USE_SCALAR_INV_BUILTIN
-#define NDEBUG
#include "./libsecp256k1/src/secp256k1.c"
#include "./libsecp256k1/src/modules/recovery/main_impl.h"
#include "ext.h"
@@ -98,7 +101,7 @@ func Sign(msg []byte, seckey []byte) ([]byte, error) {
return sig, nil
}
-// RecoverPubkey returns the the public key of the signer.
+// RecoverPubkey returns the public key of the signer.
// msg must be the 32-byte hash of the message to be signed.
// sig must be a 65-byte compact ECDSA signature containing the
// recovery id as the last element.
diff --git a/crypto/secp256k1/secp256_test.go b/crypto/secp256k1/secp256_test.go
index f8902607b9..74408d06d2 100644
--- a/crypto/secp256k1/secp256_test.go
+++ b/crypto/secp256k1/secp256_test.go
@@ -1,18 +1,9 @@
-// Copyright 2015 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
+// Copyright 2015 Jeffrey Wilcke, Felix Lange, Gustav Simonsson. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be found in
+// the LICENSE file.
+
+//go:build !gofuzz && cgo
+// +build !gofuzz,cgo
package secp256k1
@@ -22,10 +13,8 @@ import (
"crypto/elliptic"
"crypto/rand"
"encoding/hex"
+ "io"
"testing"
-
- "github.com/XinFinOrg/XDPoSChain/common/math"
- "github.com/XinFinOrg/XDPoSChain/crypto/randentropy"
)
const TestCount = 1000
@@ -36,11 +25,24 @@ func generateKeyPair() (pubkey, privkey []byte) {
panic(err)
}
pubkey = elliptic.Marshal(S256(), key.X, key.Y)
- return pubkey, math.PaddedBigBytes(key.D, 32)
+
+ privkey = make([]byte, 32)
+ blob := key.D.Bytes()
+ copy(privkey[32-len(blob):], blob)
+
+ return pubkey, privkey
+}
+
+func csprngEntropy(n int) []byte {
+ buf := make([]byte, n)
+ if _, err := io.ReadFull(rand.Reader, buf); err != nil {
+ panic("reading from crypto/rand failed: " + err.Error())
+ }
+ return buf
}
func randSig() []byte {
- sig := randentropy.GetEntropyCSPRNG(65)
+ sig := csprngEntropy(65)
sig[32] &= 0x70
sig[64] %= 4
return sig
@@ -49,7 +51,7 @@ func randSig() []byte {
// tests for malleability
// highest bit of signature ECDSA s value must be 0, in the 33th byte
func compactSigCheck(t *testing.T, sig []byte) {
- var b int = int(sig[32])
+ var b = int(sig[32])
if b < 0 {
t.Errorf("highest bit is negative: %d", b)
}
@@ -63,7 +65,7 @@ func compactSigCheck(t *testing.T, sig []byte) {
func TestSignatureValidity(t *testing.T) {
pubkey, seckey := generateKeyPair()
- msg := randentropy.GetEntropyCSPRNG(32)
+ msg := csprngEntropy(32)
sig, err := Sign(msg, seckey)
if err != nil {
t.Errorf("signature error: %s", err)
@@ -86,7 +88,7 @@ func TestSignatureValidity(t *testing.T) {
func TestInvalidRecoveryID(t *testing.T) {
_, seckey := generateKeyPair()
- msg := randentropy.GetEntropyCSPRNG(32)
+ msg := csprngEntropy(32)
sig, _ := Sign(msg, seckey)
sig[64] = 99
_, err := RecoverPubkey(msg, sig)
@@ -97,7 +99,7 @@ func TestInvalidRecoveryID(t *testing.T) {
func TestSignAndRecover(t *testing.T) {
pubkey1, seckey := generateKeyPair()
- msg := randentropy.GetEntropyCSPRNG(32)
+ msg := csprngEntropy(32)
sig, err := Sign(msg, seckey)
if err != nil {
t.Errorf("signature error: %s", err)
@@ -148,7 +150,7 @@ func TestRandomMessagesWithRandomKeys(t *testing.T) {
func signAndRecoverWithRandomMessages(t *testing.T, keys func() ([]byte, []byte)) {
for i := 0; i < TestCount; i++ {
pubkey1, seckey := keys()
- msg := randentropy.GetEntropyCSPRNG(32)
+ msg := csprngEntropy(32)
sig, err := Sign(msg, seckey)
if err != nil {
t.Fatalf("signature error: %s", err)
@@ -176,7 +178,7 @@ func signAndRecoverWithRandomMessages(t *testing.T, keys func() ([]byte, []byte)
func TestRecoveryOfRandomSignature(t *testing.T) {
pubkey1, _ := generateKeyPair()
- msg := randentropy.GetEntropyCSPRNG(32)
+ msg := csprngEntropy(32)
for i := 0; i < TestCount; i++ {
// recovery can sometimes work, but if so should always give wrong pubkey
@@ -189,11 +191,11 @@ func TestRecoveryOfRandomSignature(t *testing.T) {
func TestRandomMessagesAgainstValidSig(t *testing.T) {
pubkey1, seckey := generateKeyPair()
- msg := randentropy.GetEntropyCSPRNG(32)
+ msg := csprngEntropy(32)
sig, _ := Sign(msg, seckey)
for i := 0; i < TestCount; i++ {
- msg = randentropy.GetEntropyCSPRNG(32)
+ msg = csprngEntropy(32)
pubkey2, _ := RecoverPubkey(msg, sig)
// recovery can sometimes work, but if so should always give wrong pubkey
if bytes.Equal(pubkey1, pubkey2) {
@@ -219,7 +221,7 @@ func TestRecoverSanity(t *testing.T) {
func BenchmarkSign(b *testing.B) {
_, seckey := generateKeyPair()
- msg := randentropy.GetEntropyCSPRNG(32)
+ msg := csprngEntropy(32)
b.ResetTimer()
for i := 0; i < b.N; i++ {
@@ -228,7 +230,7 @@ func BenchmarkSign(b *testing.B) {
}
func BenchmarkRecover(b *testing.B) {
- msg := randentropy.GetEntropyCSPRNG(32)
+ msg := csprngEntropy(32)
_, seckey := generateKeyPair()
sig, _ := Sign(msg, seckey)
b.ResetTimer()