diff --git a/.gitignore b/.gitignore index 012fba02e..a5a732f46 100644 --- a/.gitignore +++ b/.gitignore @@ -22,3 +22,6 @@ keystore *.out *.test benchmark/process/run-to-height +ela +ela-cli +ela-dns diff --git a/LICENSE b/LICENSE index faa34b089..42f42e137 100644 --- a/LICENSE +++ b/LICENSE @@ -38,3 +38,8 @@ Ecies Copyright (c) 2012 The Go Authors. All rights reserved. https://github.com/obscuren/ecies BSD3 License + +Schnorr + Copyright (c) 2019 Hbakhtiyor. All rights reserved. + https://github.com/hbakhtiyor/schnorr + MIT-like License \ No newline at end of file diff --git a/blockchain/validation.go b/blockchain/validation.go index 23fbd7d17..f34f23302 100644 --- a/blockchain/validation.go +++ b/blockchain/validation.go @@ -6,13 +6,10 @@ package blockchain import ( - "crypto/elliptic" "crypto/sha256" "errors" - "math/big" "sort" - //"github.com/btcsuite/btcd/btcec" "github.com/elastos/Elastos.ELA/common" "github.com/elastos/Elastos.ELA/core/contract" . "github.com/elastos/Elastos.ELA/core/contract/program" @@ -20,22 +17,6 @@ import ( "github.com/elastos/Elastos.ELA/crypto" ) -var ( - // Curve is a KoblitzCurve which implements secp256k1. - - Curve = elliptic.P256() - // One holds a big integer of 1 - One = new(big.Int).SetInt64(1) - // Two holds a big integer of 2 - Two = new(big.Int).SetInt64(2) - // Three holds a big integer of 3 - Three = new(big.Int).SetInt64(3) - // Four holds a big integer of 4 - Four = new(big.Int).SetInt64(4) - // N2 holds a big integer of N-2 - N2 = new(big.Int).Sub(Curve.Params().N, Two) -) - func RunPrograms(data []byte, programHashes []common.Uint168, programs []*Program) error { if len(programHashes) != len(programs) { return errors.New("the number of data hashes is different with number of programs") @@ -151,169 +132,7 @@ func checkSchnorrSignatures(program Program, data []byte) (bool, error) { signature := [64]byte{} copy(signature[:], program.Parameter[:64]) - return verify(publicKey, data, signature) -} - -func verify(publicKey [33]byte, message []byte, signature [64]byte) (bool, error) { - Px, Py := Unmarshal(Curve, publicKey[:]) - - if Px == nil || Py == nil || !Curve.IsOnCurve(Px, Py) { - return false, errors.New("signature verification failed") - } - r := new(big.Int).SetBytes(signature[:32]) - if r.Cmp(Curve.Params().P) >= 0 { - return false, errors.New("r is larger than or equal to field size") - } - s := new(big.Int).SetBytes(signature[32:]) - if s.Cmp(Curve.Params().P) >= 0 { - - return false, errors.New("s is larger than or equal to curve order") - } - - e := getE(Px, Py, intToByte(r), message) - sGx, sGy := Curve.ScalarBaseMult(intToByte(s)) - ePx, ePy := Curve.ScalarMult(Px, Py, intToByte(e)) - ePy.Sub(Curve.Params().P, ePy) - Rx, Ry := Curve.Add(sGx, sGy, ePx, ePy) - - if Rx.Sign() == 0 && Ry.Sign() == 0 { - return false, errors.New("signature verification failed") - } - if big.Jacobi(Ry, Curve.Params().P) != 1 { - return false, errors.New("signature Ry verification failed") - } - if Rx.Cmp(r) != 0 { - return false, errors.New("signature Rx verification failed") - } - return true, nil -} - -func getK(Ry, k0 *big.Int) *big.Int { - if big.Jacobi(Ry, Curve.Params().P) == 1 { - return k0 - } - return k0.Sub(Curve.Params().N, k0) -} - -func getE(Px, Py *big.Int, rX []byte, m []byte) *big.Int { - r := append(rX, Marshal(Curve, Px, Py)...) - r = append(r, m[:]...) - h := sha256.Sum256(r) - i := new(big.Int).SetBytes(h[:]) - return i.Mod(i, Curve.Params().P) -} - -func intToByte(i *big.Int) []byte { - b1, b2 := [32]byte{}, i.Bytes() - copy(b1[32-len(b2):], b2) - return b1[:] -} - -func Marshal(curve elliptic.Curve, x, y *big.Int) []byte { - byteLen := (curve.Params().BitSize + 7) >> 3 - - ret := make([]byte, 1+byteLen) - ret[0] = 2 - - xBytes := x.Bytes() - copy(ret[1+byteLen-len(xBytes):], xBytes) - ret[0] += byte(y.Bit(0)) - return ret -} - -func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) { - byteLen := (curve.Params().BitSize + 7) >> 3 - if (data[0] &^ 1) != 2 { - return - } - if len(data) != 1+byteLen { - return - } - paramA := big.NewInt(crypto.P256PARAMA) - x0 := new(big.Int).SetBytes(data[1 : 1+byteLen]) - P := curve.Params().P - - ax := new(big.Int) - ax.Add(ax, paramA) - ax.Mul(ax, x0) - - ySq := new(big.Int) - ySq.Exp(x0, Three, P) - ySq.Add(ySq, ax) - ySq.Add(ySq, curve.Params().B) - ySq.Mod(ySq, P) - - y0 := new(big.Int) - P1 := new(big.Int).Add(P, One) - d := new(big.Int).Mod(P1, Four) - P1.Sub(P1, d) - P1.Div(P1, Four) - y0.Exp(ySq, P1, P) - - if new(big.Int).Exp(y0, Two, P).Cmp(ySq) != 0 { - return - } - if y0.Bit(0) != uint(data[0]&1) { - y0.Sub(P, y0) - } - x, y = x0, y0 - return -} - -// AggregateSignatures aggregates multiple signatures of different private keys over -// the same message into a single 64 byte signature. -func AggregateSignatures(privateKeys []*big.Int, message []byte) ([64]byte, error) { - sig := [64]byte{} - if privateKeys == nil || len(privateKeys) == 0 { - return sig, errors.New("privateKeys must be an array with one or more elements") - } - - k0s := []*big.Int{} - Px, Py := new(big.Int), new(big.Int) - Rx, Ry := new(big.Int), new(big.Int) - for _, privateKey := range privateKeys { - if privateKey.Cmp(One) < 0 || privateKey.Cmp(new(big.Int).Sub(Curve.Params().N, One)) > 0 { - return sig, errors.New("the private key must be an integer in the range 1..n-1") - } - - d := intToByte(privateKey) - k0i, err := deterministicGetK0(d, message) - if err != nil { - return sig, err - } - - RiX, RiY := Curve.ScalarBaseMult(intToByte(k0i)) - PiX, PiY := Curve.ScalarBaseMult(d) - - k0s = append(k0s, k0i) - - Rx, Ry = Curve.Add(Rx, Ry, RiX, RiY) - Px, Py = Curve.Add(Px, Py, PiX, PiY) - } - - rX := intToByte(Rx) - e := getE(Px, Py, rX, message[:]) - s := new(big.Int).SetInt64(0) - - for i, k0 := range k0s { - k := getK(Ry, k0) - k.Add(k, new(big.Int).Mul(e, privateKeys[i])) - s.Add(s, k) - } - - copy(sig[:32], rX) - copy(sig[32:], intToByte(s.Mod(s, Curve.Params().N))) - return sig, nil -} -func deterministicGetK0(d []byte, message []byte) (*big.Int, error) { - h := sha256.Sum256(append(d, message[:]...)) - i := new(big.Int).SetBytes(h[:]) - k0 := i.Mod(i, Curve.Params().N) - if k0.Sign() == 0 { - return nil, errors.New("k0 is zero") - } - - return k0, nil + return crypto.SchnorrVerify(publicKey, data, signature) } func checkCrossChainSignatures(program Program, data []byte) error { diff --git a/blockchain/validation_test.go b/blockchain/validation_test.go index 54f4defba..14b0b2422 100644 --- a/blockchain/validation_test.go +++ b/blockchain/validation_test.go @@ -277,15 +277,15 @@ func TestSchnorrRunProgramsOrigin(t *testing.T) { m = decodeMessage(test.m, t) } - Px, Py := Curve.ScalarBaseMult(privKey.Bytes()) + Px, Py := crypto.Curve.ScalarBaseMult(privKey.Bytes()) Pxs = append(Pxs, Px) Pys = append(Pys, Py) } t.Run("Can sign and verify two aggregated signatures over same message", func(t *testing.T) { - Px, Py := Curve.Add(Pxs[0], Pys[0], Pxs[1], Pys[1]) + Px, Py := crypto.Curve.Add(Pxs[0], Pys[0], Pxs[1], Pys[1]) //this is the sum pk elliptic. - copy(pk[:], Marshal(Curve, Px, Py)) + copy(pk[:], crypto.Marshal(crypto.Curve, Px, Py)) publicKey1, _ := crypto.DecodePoint(pk[:]) fmt.Println(publicKey1) @@ -297,7 +297,7 @@ func TestSchnorrRunProgramsOrigin(t *testing.T) { tx = buildTx() data := getData(tx) - sig, err := AggregateSignatures(pks[:2], data[:]) + sig, err := crypto.AggregateSignatures(pks[:2], data[:]) if err != nil { t.Fatalf("Unexpected error from AggregateSignatures(%x, %x): %v", pks[:2], m, err) } @@ -390,19 +390,19 @@ func TestAggregateSignatures(t *testing.T) { m = decodeMessage(test.m, t) } - Px, Py := Curve.ScalarBaseMult(privKey.Bytes()) + Px, Py := crypto.Curve.ScalarBaseMult(privKey.Bytes()) Pxs = append(Pxs, Px) Pys = append(Pys, Py) } t.Run("Can sign and verify two aggregated signatures over same message", func(t *testing.T) { - sig, err := AggregateSignatures(pks[:2], m[:]) + sig, err := crypto.AggregateSignatures(pks[:2], m[:]) if err != nil { t.Fatalf("Unexpected error from AggregateSignatures(%x, %x): %v", pks[:2], m, err) } - Px, Py := Curve.Add(Pxs[0], Pys[0], Pxs[1], Pys[1]) - copy(pk[:], Marshal(Curve, Px, Py)) + Px, Py := crypto.Curve.Add(Pxs[0], Pys[0], Pxs[1], Pys[1]) + copy(pk[:], crypto.Marshal(crypto.Curve, Px, Py)) observedSum := hex.EncodeToString(pk[:]) expected := "03c0cba209687e8f213f9b00ba0202d98ef17d189bd0d4c5decd7382b7a63bc64e" @@ -412,7 +412,7 @@ func TestAggregateSignatures(t *testing.T) { t.Fatalf("Sum of public keys, %s, want %s", observedSum, expected) } - observed, err := verify(pk, m[:], sig) + observed, err := crypto.SchnorrVerify(pk, m[:], sig) if err != nil { t.Fatalf("Unexpected error from Verify(%x, %x, %x): %v", pk, m, sig, err) } @@ -424,13 +424,13 @@ func TestAggregateSignatures(t *testing.T) { }) t.Run("Can sign and verify two more aggregated signatures over same message", func(t *testing.T) { - sig, err := AggregateSignatures(pks[1:3], m[:]) + sig, err := crypto.AggregateSignatures(pks[1:3], m[:]) if err != nil { t.Fatalf("Unexpected error from AggregateSignatures(%x, %x): %v", pks[1:3], m, err) } - Px, Py := Curve.Add(Pxs[1], Pys[1], Pxs[2], Pys[2]) - copy(pk[:], Marshal(Curve, Px, Py)) + Px, Py := crypto.Curve.Add(Pxs[1], Pys[1], Pxs[2], Pys[2]) + copy(pk[:], crypto.Marshal(crypto.Curve, Px, Py)) observedSum := hex.EncodeToString(pk[:]) expected := "038c47ce8f4f20fd041a25ef78e872448340b1dc28f6539d4fe0126018f1b8e0ea" @@ -440,7 +440,7 @@ func TestAggregateSignatures(t *testing.T) { t.Fatalf("Sum of public keys, %s, want %s", observedSum, expected) } - observed, err := verify(pk, m[:], sig) + observed, err := crypto.SchnorrVerify(pk, m[:], sig) if err != nil { t.Fatalf("Unexpected error from Verify(%x, %x, %x): %v", pk, m, sig, err) } @@ -452,14 +452,14 @@ func TestAggregateSignatures(t *testing.T) { }) t.Run("Can sign and verify three aggregated signatures over same message", func(t *testing.T) { - sig, err := AggregateSignatures(pks[:3], m[:]) + sig, err := crypto.AggregateSignatures(pks[:3], m[:]) if err != nil { t.Fatalf("Unexpected error from AggregateSignatures(%x, %x): %v", pks[:3], m, err) } - Px, Py := Curve.Add(Pxs[0], Pys[0], Pxs[1], Pys[1]) - Px, Py = Curve.Add(Px, Py, Pxs[2], Pys[2]) - copy(pk[:], Marshal(Curve, Px, Py)) + Px, Py := crypto.Curve.Add(Pxs[0], Pys[0], Pxs[1], Pys[1]) + Px, Py = crypto.Curve.Add(Px, Py, Pxs[2], Pys[2]) + copy(pk[:], crypto.Marshal(crypto.Curve, Px, Py)) observedSum := hex.EncodeToString(pk[:]) expected := "02adde346abd5b690dae4ebbb74e59ea0e41cdc00c8a5b05b0057678e5e98f9f2e" @@ -469,7 +469,7 @@ func TestAggregateSignatures(t *testing.T) { t.Fatalf("Sum of public keys, %s, want %s", observedSum, expected) } - observed, err := verify(pk, m[:], sig) + observed, err := crypto.SchnorrVerify(pk, m[:], sig) if err != nil { t.Fatalf("Unexpected error from Verify(%x, %x, %x): %v", pk, m, sig, err) } @@ -486,7 +486,7 @@ func TestAggregateSignatures(t *testing.T) { m := decodeMessage("243F6A8885A308D313198A2E03707344A4093822299F31D0082EFA98EC4E6C89", t) pks := []*big.Int{privKey1, privKey2} - aggregatedSignature, err := AggregateSignatures(pks, m[:]) + aggregatedSignature, err := crypto.AggregateSignatures(pks, m[:]) expected := "436f519c7c3a32b794a0252d1af33c34f4a14e4e54282d004983a41b0b12270773057726f0bdd41917998a55ab1d0f5ca1ea01d50b1a6731060351e78b9a7e00" observed := hex.EncodeToString(aggregatedSignature[:]) @@ -502,11 +502,11 @@ func TestAggregateSignatures(t *testing.T) { pubKey1 := decodePublicKey("031c7ce0c8d4812b12a9a8988697f45351d83cba72ea9e16f227445599666ea415", t) pubKey2 := decodePublicKey("03460cfbe83d295c072c547e831ce224dd903f888a183a35d2888b7ab3a8666054", t) - P1x, P1y := Unmarshal(Curve, pubKey1[:]) - P2x, P2y := Unmarshal(Curve, pubKey2[:]) - Px, Py := Curve.Add(P1x, P1y, P2x, P2y) + P1x, P1y := crypto.Unmarshal(crypto.Curve, pubKey1[:]) + P2x, P2y := crypto.Unmarshal(crypto.Curve, pubKey2[:]) + Px, Py := crypto.Curve.Add(P1x, P1y, P2x, P2y) - copy(pk[:], Marshal(Curve, Px, Py)) + copy(pk[:], crypto.Marshal(crypto.Curve, Px, Py)) observed = hex.EncodeToString(pk[:]) expected = "03486ca0cb4360d2b8c4be796772f77815932e18d3fe29ca81b5b30c41a1f3272e" @@ -516,7 +516,7 @@ func TestAggregateSignatures(t *testing.T) { t.Fatalf("Sum of public keys, %s, want %s", observed, expected) } - result, err := verify(pk, m[:], aggregatedSignature) + result, err := crypto.SchnorrVerify(pk, m[:], aggregatedSignature) if err != nil { t.Fatalf("Unexpected error from Verify(%x, %x, %x): %v", pk, m, aggregatedSignature, err) } @@ -548,7 +548,7 @@ func TestSchnorrRunPrograms(t *testing.T) { act = newSchnorrMultiAccount(aggregateNum, t) acts = append(acts, act) hashes = append(hashes, *act.ProgramHash()) - sig, err := AggregateSignatures(act.privateKeys[:aggregateNum], data[:]) + sig, err := crypto.AggregateSignatures(act.privateKeys[:aggregateNum], data[:]) if err != nil { fmt.Println("AggregateSignatures fail") } @@ -712,15 +712,15 @@ func newSchnorrMultiAccount(num int, t *testing.T) *schnorAccount { ma.accounts = append(ma.accounts, newAccount) privKey := new(big.Int).SetBytes(newAccount.private) ma.privateKeys = append(ma.privateKeys, privKey) - Px, Py := Curve.ScalarBaseMult(newAccount.private) + Px, Py := crypto.Curve.ScalarBaseMult(newAccount.private) Pxs = append(Pxs, Px) Pys = append(Pys, Py) } - Px, Py := Curve.Add(Pxs[0], Pys[0], Pxs[1], Pys[1]) + Px, Py := crypto.Curve.Add(Pxs[0], Pys[0], Pxs[1], Pys[1]) for i := 2; i < num; i++ { - Px, Py = Curve.Add(Px, Py, Pxs[i], Pys[i]) + Px, Py = crypto.Curve.Add(Px, Py, Pxs[i], Pys[i]) } - copy(ma.sumPublicKey[:], Marshal(Curve, Px, Py)) + copy(ma.sumPublicKey[:], crypto.Marshal(crypto.Curve, Px, Py)) publicKey, _ := crypto.DecodePoint(ma.sumPublicKey[:]) var err error diff --git a/crypto/schnorr.go b/crypto/schnorr.go new file mode 100644 index 000000000..13f7669a6 --- /dev/null +++ b/crypto/schnorr.go @@ -0,0 +1,196 @@ +// Copyright (c) 2017-2020 The Elastos Foundation +// Use of this source code is governed by an MIT +// license that can be found in the LICENSE file. +// + +package crypto + +import ( + "crypto/elliptic" + "crypto/sha256" + "errors" + "math/big" +) + +var ( + // Curve is a KoblitzCurve which implements secp256r1. + Curve = DefaultCurve + // One holds a big integer of 1 + One = new(big.Int).SetInt64(1) + // Two holds a big integer of 2 + Two = new(big.Int).SetInt64(2) + // Three holds a big integer of 3 + Three = new(big.Int).SetInt64(3) + // Four holds a big integer of 4 + Four = new(big.Int).SetInt64(4) + // The order of the base point + N = DefaultParams.N + // The order of the underlying field + P = DefaultParams.P + // The constant of the curve equation + B = DefaultParams.B + // The size of the underlying field + BitSize = DefaultParams.BitSize +) + +func SchnorrVerify(publicKey [33]byte, message []byte, signature [64]byte) (bool, error) { + Px, Py := Unmarshal(Curve, publicKey[:]) + + if Px == nil || Py == nil || !Curve.IsOnCurve(Px, Py) { + return false, errors.New("signature verification failed") + } + r := new(big.Int).SetBytes(signature[:32]) + if r.Cmp(P) >= 0 { + return false, errors.New("r is larger than or equal to field size") + } + s := new(big.Int).SetBytes(signature[32:]) + if s.Cmp(P) >= 0 { + + return false, errors.New("s is larger than or equal to curve order") + } + + e := getE(Px, Py, intToByte(r), message) + sGx, sGy := Curve.ScalarBaseMult(intToByte(s)) + ePx, ePy := Curve.ScalarMult(Px, Py, intToByte(e)) + ePy.Sub(P, ePy) + Rx, Ry := Curve.Add(sGx, sGy, ePx, ePy) + + if Rx.Sign() == 0 && Ry.Sign() == 0 { + return false, errors.New("signature verification failed") + } + if big.Jacobi(Ry, P) != 1 { + return false, errors.New("signature Ry verification failed") + } + if Rx.Cmp(r) != 0 { + return false, errors.New("signature Rx verification failed") + } + return true, nil +} + +func getK(Ry, k0 *big.Int) *big.Int { + if big.Jacobi(Ry, P) == 1 { + return k0 + } + return k0.Sub(N, k0) +} + +func getE(Px, Py *big.Int, rX []byte, m []byte) *big.Int { + r := append(rX, Marshal(Curve, Px, Py)...) + r = append(r, m[:]...) + h := sha256.Sum256(r) + i := new(big.Int).SetBytes(h[:]) + return i.Mod(i, P) +} + +func intToByte(i *big.Int) []byte { + b1, b2 := [32]byte{}, i.Bytes() + copy(b1[32-len(b2):], b2) + return b1[:] +} + +func Marshal(curve elliptic.Curve, x, y *big.Int) []byte { + byteLen := (BitSize + 7) >> 3 + + ret := make([]byte, 1+byteLen) + ret[0] = 2 + + xBytes := x.Bytes() + copy(ret[1+byteLen-len(xBytes):], xBytes) + ret[0] += byte(y.Bit(0)) + return ret +} + +func Unmarshal(curve elliptic.Curve, data []byte) (x, y *big.Int) { + byteLen := (BitSize + 7) >> 3 + if (data[0] &^ 1) != 2 { + return + } + if len(data) != 1+byteLen { + return + } + paramA := big.NewInt(-3) + x0 := new(big.Int).SetBytes(data[1 : 1+byteLen]) + + ax := new(big.Int) + ax.Add(ax, paramA) + ax.Mul(ax, x0) + + ySq := new(big.Int) + ySq.Exp(x0, Three, P) + ySq.Add(ySq, ax) + ySq.Add(ySq, B) + ySq.Mod(ySq, P) + + y0 := new(big.Int) + P1 := new(big.Int).Add(P, One) + d := new(big.Int).Mod(P1, Four) + P1.Sub(P1, d) + P1.Div(P1, Four) + y0.Exp(ySq, P1, P) + + if new(big.Int).Exp(y0, Two, P).Cmp(ySq) != 0 { + return + } + if y0.Bit(0) != uint(data[0]&1) { + y0.Sub(P, y0) + } + x, y = x0, y0 + return +} + +// AggregateSignatures aggregates multiple signatures of different private keys over +// the same message into a single 64 byte signature. +func AggregateSignatures(privateKeys []*big.Int, message []byte) ([64]byte, error) { + sig := [64]byte{} + if privateKeys == nil || len(privateKeys) == 0 { + return sig, errors.New("privateKeys must be an array with one or more elements") + } + + k0s := []*big.Int{} + Px, Py := new(big.Int), new(big.Int) + Rx, Ry := new(big.Int), new(big.Int) + for _, privateKey := range privateKeys { + if privateKey.Cmp(One) < 0 || privateKey.Cmp(new(big.Int).Sub(N, One)) > 0 { + return sig, errors.New("the private key must be an integer in the range 1..n-1") + } + + d := intToByte(privateKey) + k0i, err := deterministicGetK0(d, message) + if err != nil { + return sig, err + } + + RiX, RiY := Curve.ScalarBaseMult(intToByte(k0i)) + PiX, PiY := Curve.ScalarBaseMult(d) + + k0s = append(k0s, k0i) + + Rx, Ry = Curve.Add(Rx, Ry, RiX, RiY) + Px, Py = Curve.Add(Px, Py, PiX, PiY) + } + + rX := intToByte(Rx) + e := getE(Px, Py, rX, message[:]) + s := new(big.Int).SetInt64(0) + + for i, k0 := range k0s { + k := getK(Ry, k0) + k.Add(k, new(big.Int).Mul(e, privateKeys[i])) + s.Add(s, k) + } + + copy(sig[:32], rX) + copy(sig[32:], intToByte(s.Mod(s, N))) + return sig, nil +} + +func deterministicGetK0(d []byte, message []byte) (*big.Int, error) { + h := sha256.Sum256(append(d, message[:]...)) + i := new(big.Int).SetBytes(h[:]) + k0 := i.Mod(i, N) + if k0.Sign() == 0 { + return nil, errors.New("k0 is zero") + } + + return k0, nil +}