diff --git a/dcrec/edwards/ciphering.go b/dcrec/edwards/ciphering.go index 87d4a07c..69b39fc8 100644 --- a/dcrec/edwards/ciphering.go +++ b/dcrec/edwards/ciphering.go @@ -64,8 +64,8 @@ func GenerateSharedSecret(privkey *PrivateKey, pubkey *PublicKey) []byte { // The primary aim is to ensure byte compatibility with Pyelliptic. // Additionally, refer to section 5.8.1 of ANSI X9.63 for rationale on this // format. -func Encrypt(curve *TwistedEdwardsCurve, pubkey *PublicKey, in []byte) ([]byte, error) { - ephemeral, err := GeneratePrivateKey(curve) +func Encrypt(pubkey *PublicKey, in []byte) ([]byte, error) { + ephemeral, err := GeneratePrivateKey() if err != nil { return nil, err } @@ -83,7 +83,7 @@ func Encrypt(curve *TwistedEdwardsCurve, pubkey *PublicKey, in []byte) ([]byte, } // start writing public key ePubX, ePubY := ephemeral.Public() - pbk := NewPublicKey(curve, ePubX, ePubY) + pbk := NewPublicKey(ePubX, ePubY) pb := pbk.Serialize() offset := aes.BlockSize @@ -111,7 +111,7 @@ func Encrypt(curve *TwistedEdwardsCurve, pubkey *PublicKey, in []byte) ([]byte, } // Decrypt decrypts data that was encrypted using the Encrypt function. -func Decrypt(curve *TwistedEdwardsCurve, priv *PrivateKey, in []byte) ([]byte, error) { +func Decrypt(priv *PrivateKey, in []byte) ([]byte, error) { // IV + Curve params/X/Y + 1 block + HMAC-256 if len(in) < aes.BlockSize+36+aes.BlockSize+sha256.Size { return nil, errInputTooShort @@ -139,7 +139,7 @@ func Decrypt(curve *TwistedEdwardsCurve, priv *PrivateKey, in []byte) ([]byte, e copy(pb[0:32], yBytes) // check if (X, Y) lies on the curve and create a Pubkey if it does - pubkey, err := ParsePubKey(curve, pb) + pubkey, err := ParsePubKey(pb) if err != nil { return nil, err } diff --git a/dcrec/edwards/ciphering_test.go b/dcrec/edwards/ciphering_test.go index 6aefde78..6383d5d5 100644 --- a/dcrec/edwards/ciphering_test.go +++ b/dcrec/edwards/ciphering_test.go @@ -13,23 +13,21 @@ import ( ) func TestGenerateSharedSecret(t *testing.T) { - c := new(TwistedEdwardsCurve) - c.InitParam25519() - privKey1, err := GeneratePrivateKey(c) + privKey1, err := GeneratePrivateKey() if err != nil { t.Errorf("private key generation error: %s", err) return } - privKey2, err := GeneratePrivateKey(c) + privKey2, err := GeneratePrivateKey() if err != nil { t.Errorf("private key generation error: %s", err) return } pk1x, pk1y := privKey1.Public() - pk1 := NewPublicKey(c, pk1x, pk1y) + pk1 := NewPublicKey(pk1x, pk1y) pk2x, pk2y := privKey2.Public() - pk2 := NewPublicKey(c, pk2x, pk2y) + pk2 := NewPublicKey(pk2x, pk2y) secret1 := GenerateSharedSecret(privKey1, pk2) secret2 := GenerateSharedSecret(privKey2, pk1) @@ -41,9 +39,7 @@ func TestGenerateSharedSecret(t *testing.T) { // Test 1: Encryption and decryption func TestCipheringBasic(t *testing.T) { - c := new(TwistedEdwardsCurve) - c.InitParam25519() - privkey, err := GeneratePrivateKey(c) + privkey, err := GeneratePrivateKey() if err != nil { t.Fatal("failed to generate private key") } @@ -51,13 +47,13 @@ func TestCipheringBasic(t *testing.T) { in := []byte("Hey there dude. How are you doing? This is a test.") pk1x, pk1y := privkey.Public() - pk1 := NewPublicKey(c, pk1x, pk1y) - out, err := Encrypt(c, pk1, in) + pk1 := NewPublicKey(pk1x, pk1y) + out, err := Encrypt(pk1, in) if err != nil { t.Fatal("failed to encrypt:", err) } - dec, err := Decrypt(c, privkey, out) + dec, err := Decrypt(privkey, out) if err != nil { t.Fatal("failed to decrypt:", err) } @@ -68,8 +64,7 @@ func TestCipheringBasic(t *testing.T) { } func TestCiphering(t *testing.T) { - c := new(TwistedEdwardsCurve) - c.InitParam25519() + c := Edwards() pb, _ := hex.DecodeString("fe38240982f313ae5afb3e904fb8215fb11af1200592b" + "fca26c96c4738e4bf8f") @@ -77,12 +72,12 @@ func TestCiphering(t *testing.T) { pbBig.Mod(pbBig, c.N) pb = pbBig.Bytes() pb = copyBytes(pb)[:] - privkey, pubkey, err := PrivKeyFromScalar(c, pb) + privkey, pubkey, err := PrivKeyFromScalar(pb) if err != nil { t.Error(err) } in := []byte("This is just a test.") - localOut, err := Encrypt(c, pubkey, in) + localOut, err := Encrypt(pubkey, in) if err != nil { t.Error(err) } @@ -92,12 +87,12 @@ func TestCiphering(t *testing.T) { "04f86635c50baca78d11189d4dc02c2f32c4c11e9d50b04eb2d3ff4b9f95e7f2e90e" + "0f4a8d64a2a4149c27d21f88f2dedc200f4b609936c0d67ca98") - _, err = Decrypt(c, privkey, out) + _, err = Decrypt(privkey, out) if err != nil { t.Fatal("failed to decrypt:", err) } - dec, err := Decrypt(c, privkey, localOut) + dec, err := Decrypt(privkey, localOut) if err != nil { t.Fatal("failed to decrypt:", err) } @@ -108,10 +103,7 @@ func TestCiphering(t *testing.T) { } func TestCipheringErrors(t *testing.T) { - c := new(TwistedEdwardsCurve) - c.InitParam25519() - - privkey, err := GeneratePrivateKey(c) + privkey, err := GeneratePrivateKey() if err != nil { t.Fatal("failed to generate private key") } @@ -172,7 +164,7 @@ func TestCipheringErrors(t *testing.T) { } for i, test := range tests1 { - _, err = Decrypt(c, privkey, test.ciphertext) + _, err = Decrypt(privkey, test.ciphertext) if err == nil { t.Errorf("Decrypt #%d did not get error", i) } diff --git a/dcrec/edwards/ecdsa.go b/dcrec/edwards/ecdsa.go index 6d7280e8..5d1e4a66 100644 --- a/dcrec/edwards/ecdsa.go +++ b/dcrec/edwards/ecdsa.go @@ -47,10 +47,7 @@ func GenerateKey(rand io.Reader) (priv []byte, x, y *big.Int, err error) { } priv = privArray[:] - curve := new(TwistedEdwardsCurve) - curve.InitParam25519() - - x, y, err = curve.EncodedBytesToBigIntPoint(pub) + x, y, err = Edwards().EncodedBytesToBigIntPoint(pub) if err != nil { return nil, nil, nil, err } @@ -87,10 +84,10 @@ func SignFromSecretNoReader(priv *PrivateKey, hash []byte) (r, s *big.Int, err e // nonceRFC6979 is a local instatiation of deterministic nonce generation // by the standards of RFC6979. -func nonceRFC6979(curve *TwistedEdwardsCurve, privkey []byte, hash []byte, extra []byte, version []byte) []byte { +func nonceRFC6979(privkey []byte, hash []byte, extra []byte, version []byte) []byte { pkD := new(big.Int).SetBytes(privkey) defer pkD.SetInt64(0) - bigK := NonceRFC6979(curve, pkD, hash, extra, version) + bigK := NonceRFC6979(pkD, hash, extra, version) defer bigK.SetInt64(0) k := BigIntToEncodedBytesNoReverse(bigK) return k[:] @@ -99,7 +96,8 @@ func nonceRFC6979(curve *TwistedEdwardsCurve, privkey []byte, hash []byte, extra // NonceRFC6979 generates an ECDSA nonce (`k`) deterministically according to // RFC 6979. It takes a 32-byte hash as an input and returns 32-byte nonce to // be used in ECDSA algorithm. -func NonceRFC6979(curve *TwistedEdwardsCurve, privkey *big.Int, hash []byte, extra []byte, version []byte) *big.Int { +func NonceRFC6979(privkey *big.Int, hash []byte, extra []byte, version []byte) *big.Int { + curve := Edwards() q := curve.Params().N x := privkey alg := sha256.New @@ -107,7 +105,7 @@ func NonceRFC6979(curve *TwistedEdwardsCurve, privkey *big.Int, hash []byte, ext qlen := q.BitLen() holen := alg().Size() rolen := (qlen + 7) >> 3 - bx := append(int2octets(x, rolen), bits2octets(hash, curve, rolen)...) + bx := append(int2octets(x, rolen), bits2octets(hash, rolen)...) if len(extra) == 32 { bx = append(bx, extra...) } @@ -209,7 +207,8 @@ func int2octets(v *big.Int, rolen int) []byte { } // https://tools.ietf.org/html/rfc6979#section-2.3.4 -func bits2octets(in []byte, curve *TwistedEdwardsCurve, rolen int) []byte { +func bits2octets(in []byte, rolen int) []byte { + curve := Edwards() z1 := hashToInt(in, curve) z2 := new(big.Int).Sub(z1, curve.Params().N) if z2.Sign() < 0 { @@ -222,7 +221,7 @@ func bits2octets(in []byte, curve *TwistedEdwardsCurve, rolen int) []byte { // It uses RFC6979 to generate a deterministic nonce. Considered experimental. // r = kG, where k is the RFC6979 nonce // s = r + hash512(k || A || M) * a -func SignFromScalar(curve *TwistedEdwardsCurve, priv *PrivateKey, nonce []byte, hash []byte) (r, s *big.Int, err error) { +func SignFromScalar(priv *PrivateKey, nonce []byte, hash []byte) (r, s *big.Int, err error) { publicKey := new([PubKeyBytesLen]byte) var A edwards25519.ExtendedGroupElement privateScalar := copyBytes(priv.Serialize()) @@ -259,7 +258,7 @@ func SignFromScalar(curve *TwistedEdwardsCurve, priv *PrivateKey, nonce []byte, signature := new([64]byte) copy(signature[:], encodedR[:]) copy(signature[32:], localS[:]) - sigEd, err := ParseSignature(curve, signature[:]) + sigEd, err := ParseSignature(signature[:]) if err != nil { return nil, nil, err } @@ -275,7 +274,7 @@ func SignFromScalar(curve *TwistedEdwardsCurve, priv *PrivateKey, nonce []byte, // the public nonce point with n-1 keys added. // r = K_Sum // s = r + hash512(k || A || M) * a -func SignThreshold(curve *TwistedEdwardsCurve, priv *PrivateKey, groupPub *PublicKey, hash []byte, privNonce *PrivateKey, +func SignThreshold(priv *PrivateKey, groupPub *PublicKey, hash []byte, privNonce *PrivateKey, pubNonceSum *PublicKey) (r, s *big.Int, err error) { if priv == nil || hash == nil || privNonce == nil || pubNonceSum == nil { @@ -314,7 +313,7 @@ func SignThreshold(curve *TwistedEdwardsCurve, priv *PrivateKey, groupPub *Publi signature := new([64]byte) copy(signature[:], encodedGroupR[:]) copy(signature[32:], localS[:]) - sigEd, err := ParseSignature(curve, signature[:]) + sigEd, err := ParseSignature(signature[:]) if err != nil { return nil, nil, err } @@ -324,7 +323,7 @@ func SignThreshold(curve *TwistedEdwardsCurve, priv *PrivateKey, groupPub *Publi // Sign is the generalized and exported version of Ed25519 signing, that // handles both standard private secrets and non-standard scalars. -func Sign(curve *TwistedEdwardsCurve, priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { +func Sign(priv *PrivateKey, hash []byte) (r, s *big.Int, err error) { if priv == nil { return nil, nil, fmt.Errorf("private key is nil") } @@ -335,8 +334,8 @@ func Sign(curve *TwistedEdwardsCurve, priv *PrivateKey, hash []byte) (r, s *big. if priv.secret == nil { privLE := copyBytes(priv.Serialize()) reverse(privLE) - nonce := nonceRFC6979(curve, privLE[:], hash, nil, nil) - return SignFromScalar(curve, priv, nonce, hash) + nonce := nonceRFC6979(privLE[:], hash, nil, nil) + return SignFromScalar(priv, nonce, hash) } return SignFromSecretNoReader(priv, hash) diff --git a/dcrec/edwards/ecdsa_test.go b/dcrec/edwards/ecdsa_test.go index d519a046..e1adbddb 100644 --- a/dcrec/edwards/ecdsa_test.go +++ b/dcrec/edwards/ecdsa_test.go @@ -18,9 +18,6 @@ import ( ) func TestGolden(t *testing.T) { - curve := new(TwistedEdwardsCurve) - curve.InitParam25519() - // sign.input.gz is a selection of test cases from // http://ed25519.cr.yp.to/python/sign.input testDataZ, err := os.Open("testdata/sign.input.gz") @@ -74,8 +71,8 @@ func TestGolden(t *testing.T) { copy(priv[32:], pubKeyBytes) // Deserialize privkey and test functions. - privkeyS1, pubkeyS1 := PrivKeyFromSecret(curve, priv[:32]) - privkeyS2, pubkeyS2 := PrivKeyFromBytes(curve, priv[:]) + privkeyS1, pubkeyS1 := PrivKeyFromSecret(priv[:32]) + privkeyS2, pubkeyS2 := PrivKeyFromBytes(priv[:]) pkS1 := privkeyS1.SerializeSecret() pkS2 := privkeyS2.SerializeSecret() pubkS1 := pubkeyS1.Serialize() @@ -111,7 +108,7 @@ func TestGolden(t *testing.T) { } // Deserialize pubkey and test functions. - pubkeyP, err := ParsePubKey(curve, pubKeyBytes) + pubkeyP, err := ParsePubKey(pubKeyBytes) if err != nil { t.Fatalf("ParsePubKey: %v", err) } @@ -133,7 +130,7 @@ func TestGolden(t *testing.T) { } // Deserialize signature and test functions. - internalSig, err := ParseSignature(curve, sig) + internalSig, err := ParseSignature(sig) if err != nil { t.Fatalf("ParseSignature failed: %v", err) } @@ -143,7 +140,7 @@ func TestGolden(t *testing.T) { t.Fatalf("expected %v, got %v", true, cmp) } - sig2r, sig2s, err := Sign(curve, privkeyS2, msg) + sig2r, sig2s, err := Sign(privkeyS2, msg) if err != nil { t.Fatalf("Sign failed: %v", err) } @@ -162,9 +159,10 @@ func TestGolden(t *testing.T) { } } -func randPrivScalarKeyList(curve *TwistedEdwardsCurve, i int) []*PrivateKey { +func randPrivScalarKeyList(i int) []*PrivateKey { r := rand.New(rand.NewSource(54321)) + curve := Edwards() privKeyList := make([]*PrivateKey, i) for j := 0; j < i; j++ { for { @@ -179,7 +177,7 @@ func randPrivScalarKeyList(curve *TwistedEdwardsCurve, i int) []*PrivateKey { bIn = copyBytes(bInBig.Bytes()) bIn[31] &= 248 - pks, _, err := PrivKeyFromScalar(curve, bIn[:]) + pks, _, err := PrivKeyFromScalar(bIn[:]) if err != nil { r.Seed(int64(j) + r.Int63n(12345)) continue @@ -203,8 +201,6 @@ func randPrivScalarKeyList(curve *TwistedEdwardsCurve, i int) []*PrivateKey { func TestNonStandardSignatures(t *testing.T) { tRand := rand.New(rand.NewSource(54321)) - curve := new(TwistedEdwardsCurve) - curve.InitParam25519() msg := []byte{ 0xbe, 0x13, 0xae, 0xf4, 0xe8, 0xa2, 0x00, 0xb6, @@ -216,22 +212,22 @@ func TestNonStandardSignatures(t *testing.T) { 0x98, 0x2b, 0xd9, 0xfb, } - pks := randPrivScalarKeyList(curve, 50) + pks := randPrivScalarKeyList(50) for _, pk := range pks { - r, s, err := Sign(curve, pk, msg) + r, s, err := Sign(pk, msg) if err != nil { t.Fatalf("unexpected error %s", err) } pubX, pubY := pk.Public() - pub := NewPublicKey(curve, pubX, pubY) + pub := NewPublicKey(pubX, pubY) ok := Verify(pub, msg, r, s) if !ok { t.Fatalf("expected %v, got %v", true, ok) } // Test serializing/deserializing. - privKeyDupTest, _, err := PrivKeyFromScalar(curve, + privKeyDupTest, _, err := PrivKeyFromScalar( copyBytes(pk.ecPk.D.Bytes())[:]) if err != nil { @@ -243,7 +239,7 @@ func TestNonStandardSignatures(t *testing.T) { t.Fatalf("expected %v, got %v", true, cmp) } - privKeyDupTest2, _, err := PrivKeyFromScalar(curve, pk.Serialize()) + privKeyDupTest2, _, err := PrivKeyFromScalar(pk.Serialize()) if err != nil { t.Fatalf("unexpected error %s", err) } @@ -261,7 +257,7 @@ func TestNonStandardSignatures(t *testing.T) { bitPos := tRand.Intn(7) sigBad[pos] ^= 1 << uint8(bitPos) - bSig, err := ParseSignature(curve, sigBad) + bSig, err := ParseSignature(sigBad) if err != nil { // Signature failed to parse, continue. continue @@ -282,7 +278,7 @@ func TestNonStandardSignatures(t *testing.T) { bitPos = tRand.Intn(7) } pkBad[pos] ^= 1 << uint8(bitPos) - bPub, err := ParsePubKey(curve, pkBad) + bPub, err := ParsePubKey(pkBad) if err == nil && bPub != nil { ok = Verify(bPub, msg, r, s) if ok { @@ -292,7 +288,7 @@ func TestNonStandardSignatures(t *testing.T) { } } -func randPrivKeyList(curve *TwistedEdwardsCurve, i int) []*PrivateKey { +func randPrivKeyList(i int) []*PrivateKey { r := rand.New(rand.NewSource(54321)) privKeyList := make([]*PrivateKey, i) @@ -304,7 +300,7 @@ func randPrivKeyList(curve *TwistedEdwardsCurve, i int) []*PrivateKey { bIn[k] = uint8(randByte) } - pks, _ := PrivKeyFromSecret(curve, bIn[:]) + pks, _ := PrivKeyFromSecret(bIn[:]) if pks == nil { continue } @@ -324,9 +320,6 @@ func randPrivKeyList(curve *TwistedEdwardsCurve, i int) []*PrivateKey { } func benchmarkSigning(b *testing.B) { - curve := new(TwistedEdwardsCurve) - curve.InitParam25519() - r := rand.New(rand.NewSource(54321)) msg := []byte{ 0xbe, 0x13, 0xae, 0xf4, @@ -340,11 +333,11 @@ func benchmarkSigning(b *testing.B) { } numKeys := 1024 - privKeyList := randPrivKeyList(curve, numKeys) + privKeyList := randPrivKeyList(numKeys) for n := 0; n < b.N; n++ { randIndex := r.Intn(numKeys - 1) - _, _, err := Sign(curve, privKeyList[randIndex], msg) + _, _, err := Sign(privKeyList[randIndex], msg) if err != nil { panic("sign failure") } @@ -354,9 +347,6 @@ func benchmarkSigning(b *testing.B) { func BenchmarkSigning(b *testing.B) { benchmarkSigning(b) } func benchmarkSigningNonStandard(b *testing.B) { - curve := new(TwistedEdwardsCurve) - curve.InitParam25519() - r := rand.New(rand.NewSource(54321)) msg := []byte{ 0xbe, 0x13, 0xae, 0xf4, @@ -370,11 +360,11 @@ func benchmarkSigningNonStandard(b *testing.B) { } numKeys := 250 - privKeyList := randPrivScalarKeyList(curve, numKeys) + privKeyList := randPrivScalarKeyList(numKeys) for n := 0; n < b.N; n++ { randIndex := r.Intn(numKeys - 1) - _, _, err := Sign(curve, privKeyList[randIndex], msg) + _, _, err := Sign(privKeyList[randIndex], msg) if err != nil { panic("sign failure") } @@ -389,7 +379,7 @@ type SignatureVerParams struct { sig *Signature } -func randSigList(curve *TwistedEdwardsCurve, i int) []*SignatureVerParams { +func randSigList(i int) []*SignatureVerParams { r := rand.New(rand.NewSource(54321)) privKeyList := make([]*PrivateKey, i) @@ -401,7 +391,7 @@ func randSigList(curve *TwistedEdwardsCurve, i int) []*SignatureVerParams { bIn[k] = uint8(randByte) } - pks, _ := PrivKeyFromSecret(curve, bIn[:]) + pks, _ := PrivKeyFromSecret(bIn[:]) if pks == nil { continue } @@ -424,7 +414,7 @@ func randSigList(curve *TwistedEdwardsCurve, i int) []*SignatureVerParams { sigsList := make([]*Signature, i) for j := 0; j < i; j++ { - r, s, err := Sign(curve, privKeyList[j], msgList[j]) + r, s, err := Sign(privKeyList[j], msgList[j]) if err != nil { panic("sign failure") } @@ -436,7 +426,7 @@ func randSigList(curve *TwistedEdwardsCurve, i int) []*SignatureVerParams { for j := 0; j < i; j++ { ss := new(SignatureVerParams) pkx, pky := privKeyList[j].Public() - ss.pubkey = NewPublicKey(curve, pkx, pky) + ss.pubkey = NewPublicKey(pkx, pky) ss.msg = msgList[j] ss.sig = sigsList[j] sigStructList[j] = ss @@ -446,12 +436,10 @@ func randSigList(curve *TwistedEdwardsCurve, i int) []*SignatureVerParams { } func benchmarkVerification(b *testing.B) { - curve := new(TwistedEdwardsCurve) - curve.InitParam25519() r := rand.New(rand.NewSource(54321)) numSigs := 1024 - sigList := randSigList(curve, numSigs) + sigList := randSigList(numSigs) for n := 0; n < b.N; n++ { randIndex := r.Intn(numSigs - 1) diff --git a/dcrec/edwards/privkey.go b/dcrec/edwards/privkey.go index 4f74ce69..2e87f924 100644 --- a/dcrec/edwards/privkey.go +++ b/dcrec/edwards/privkey.go @@ -32,16 +32,16 @@ type PrivateKey struct { // NewPrivateKey instantiates a new private key from a scalar encoded as a // big integer. -func NewPrivateKey(curve *TwistedEdwardsCurve, d *big.Int) *PrivateKey { +func NewPrivateKey(d *big.Int) *PrivateKey { dArray := BigIntToEncodedBytes(d) - priv, _ := PrivKeyFromSecret(curve, dArray[:]) + priv, _ := PrivKeyFromSecret(dArray[:]) return priv } // GeneratePrivateKey is a wrapper for ecdsa.GenerateKey that returns a // PrivateKey instead of the normal ecdsa.PrivateKey. -func GeneratePrivateKey(curve *TwistedEdwardsCurve) (*PrivateKey, error) { - key, err := ecdsa.GenerateKey(curve, rand.Reader) +func GeneratePrivateKey() (*PrivateKey, error) { + key, err := ecdsa.GenerateKey(Edwards(), rand.Reader) if err != nil { return nil, err } @@ -70,7 +70,7 @@ func computeScalar(privateKey *[PrivKeyBytesLen]byte) *[PrivScalarSize]byte { // PrivKeyFromBytes returns a private and public key for `curve' based on the // private key passed as an argument as a byte slice. -func PrivKeyFromBytes(curve *TwistedEdwardsCurve, pkBytes []byte) (*PrivateKey, *PublicKey) { +func PrivKeyFromBytes(pkBytes []byte) (*PrivateKey, *PublicKey) { if len(pkBytes) != PrivKeyBytesLen { return nil, nil } @@ -82,7 +82,7 @@ func PrivKeyFromBytes(curve *TwistedEdwardsCurve, pkBytes []byte) (*PrivateKey, // So, make sure we only grab the actual scalar we care about. privKeyBytes := pk[0:32] pubKeyBytes := pk[32:64] - pubKey, err := ParsePubKey(curve, pubKeyBytes) + pubKey, err := ParsePubKey(pubKeyBytes) if err != nil { return nil, nil } @@ -100,7 +100,7 @@ func PrivKeyFromBytes(curve *TwistedEdwardsCurve, pkBytes []byte) (*PrivateKey, // PrivKeyFromSecret returns a private and public key for `curve' based on the // 32-byte private key secret passed as an argument as a byte slice. -func PrivKeyFromSecret(curve *TwistedEdwardsCurve, s []byte) (*PrivateKey, *PublicKey) { +func PrivKeyFromSecret(s []byte) (*PrivateKey, *PublicKey) { if len(s) != PrivKeyBytesLen/2 { return nil, nil } @@ -113,13 +113,13 @@ func PrivKeyFromSecret(curve *TwistedEdwardsCurve, s []byte) (*PrivateKey, *Publ return nil, nil } - return PrivKeyFromBytes(curve, pk[:]) + return PrivKeyFromBytes(pk[:]) } // PrivKeyFromScalar returns a private and public key for `curve' based on the // 32-byte private scalar passed as an argument as a byte slice (encoded big // endian int). -func PrivKeyFromScalar(curve *TwistedEdwardsCurve, p []byte) (*PrivateKey, *PublicKey, error) { +func PrivKeyFromScalar(p []byte) (*PrivateKey, *PublicKey, error) { if len(p) != PrivScalarSize { return nil, nil, fmt.Errorf("bad private scalar size") } @@ -129,6 +129,7 @@ func PrivKeyFromScalar(curve *TwistedEdwardsCurve, p []byte) (*PrivateKey, *Publ pk.ecPk.D = new(big.Int).SetBytes(p) // The scalar must be in the subgroup. + curve := Edwards() if pk.ecPk.D.Cmp(curve.N) > 0 { return nil, nil, fmt.Errorf("not on subgroup (>N)") } diff --git a/dcrec/edwards/pubkey.go b/dcrec/edwards/pubkey.go index ff1a6f00..63a918c7 100644 --- a/dcrec/edwards/pubkey.go +++ b/dcrec/edwards/pubkey.go @@ -22,17 +22,18 @@ const ( type PublicKey ecdsa.PublicKey // NewPublicKey instantiates a new public key. -func NewPublicKey(curve *TwistedEdwardsCurve, x *big.Int, y *big.Int) *PublicKey { - return &PublicKey{curve, x, y} +func NewPublicKey(x *big.Int, y *big.Int) *PublicKey { + return &PublicKey{Edwards(), x, y} } // ParsePubKey parses a public key for an edwards curve from a bytestring into a // ecdsa.Publickey, verifying that it is valid. -func ParsePubKey(curve *TwistedEdwardsCurve, pubKeyStr []byte) (key *PublicKey, err error) { +func ParsePubKey(pubKeyStr []byte) (key *PublicKey, err error) { if len(pubKeyStr) == 0 { return nil, errors.New("pubkey string is empty") } + curve := Edwards() pubkey := PublicKey{} pubkey.Curve = curve x, y, err := curve.EncodedBytesToBigIntPoint(copyBytes(pubKeyStr)) diff --git a/dcrec/edwards/signature.go b/dcrec/edwards/signature.go index c60e7e4a..882261c9 100644 --- a/dcrec/edwards/signature.go +++ b/dcrec/edwards/signature.go @@ -40,7 +40,7 @@ func (sig Signature) Serialize() []byte { } // parseSig is the default method of parsing a serialized Ed25519 signature. -func parseSig(curve *TwistedEdwardsCurve, sigStr []byte, der bool) (*Signature, error) { +func parseSig(sigStr []byte, der bool) (*Signature, error) { if der { return nil, fmt.Errorf("DER signatures not allowed in ed25519") } @@ -50,6 +50,7 @@ func parseSig(curve *TwistedEdwardsCurve, sigStr []byte, der bool) (*Signature, len(sigStr), SignatureSize) } + curve := Edwards() rBytes := copyBytes(sigStr[0:32]) r := EncodedBytesToBigInt(rBytes) // r is a point on the curve as well. Evaluate it and make sure it's @@ -72,14 +73,14 @@ func parseSig(curve *TwistedEdwardsCurve, sigStr []byte, der bool) (*Signature, // ParseSignature parses a signature in BER format for the curve type `curve' // into a Signature type, perfoming some basic sanity checks. -func ParseSignature(curve *TwistedEdwardsCurve, sigStr []byte) (*Signature, error) { - return parseSig(curve, sigStr, false) +func ParseSignature(sigStr []byte) (*Signature, error) { + return parseSig(sigStr, false) } // ParseDERSignature offers a legacy function for plugging into Decred, which // is based off btcec. -func ParseDERSignature(curve *TwistedEdwardsCurve, sigStr []byte) (*Signature, error) { - return parseSig(curve, sigStr, false) +func ParseDERSignature(sigStr []byte) (*Signature, error) { + return parseSig(sigStr, false) } // RecoverCompact uses a signature and a hash to recover is private diff --git a/dcrec/edwards/threshold.go b/dcrec/edwards/threshold.go index 0c06cf39..327200c2 100644 --- a/dcrec/edwards/threshold.go +++ b/dcrec/edwards/threshold.go @@ -15,7 +15,7 @@ var Sha512VersionStringRFC6979 = []byte("Edwards+SHA512 ") // CombinePubkeys combines a slice of public keys into a single public key // by adding them together with point addition. -func CombinePubkeys(curve *TwistedEdwardsCurve, pks []*PublicKey) *PublicKey { +func CombinePubkeys(pks []*PublicKey) *PublicKey { numPubKeys := len(pks) // Have to have at least two pubkeys. @@ -32,6 +32,7 @@ func CombinePubkeys(curve *TwistedEdwardsCurve, pks []*PublicKey) *PublicKey { return nil } + curve := Edwards() var pkSumX *big.Int var pkSumY *big.Int @@ -49,16 +50,18 @@ func CombinePubkeys(curve *TwistedEdwardsCurve, pks []*PublicKey) *PublicKey { return nil } - return NewPublicKey(curve, pkSumX, pkSumY) + return NewPublicKey(pkSumX, pkSumY) } // generateNoncePair deterministically generate a nonce pair for use in // partial signing of a message. Returns a public key (nonce to dissemanate) // and a private nonce to keep as a secret for the signer. -func generateNoncePair(curve *TwistedEdwardsCurve, msg []byte, priv []byte, - nonceFunction func(*TwistedEdwardsCurve, []byte, []byte, []byte, +func generateNoncePair(msg []byte, priv []byte, + nonceFunction func([]byte, []byte, []byte, []byte) []byte, extra []byte, version []byte) ([]byte, *PublicKey, error) { - k := nonceFunction(curve, priv, msg, extra, version) + + curve := Edwards() + k := nonceFunction(priv, msg, extra, version) bigK := new(big.Int).SetBytes(k) bigK.Mod(bigK, curve.N) @@ -72,31 +75,30 @@ func generateNoncePair(curve *TwistedEdwardsCurve, msg []byte, priv []byte, bigK.SetInt64(0) pubx, puby := curve.ScalarBaseMult(k) - pubnonce := NewPublicKey(curve, pubx, puby) + pubnonce := NewPublicKey(pubx, puby) return k, pubnonce, nil } // GenerateNoncePair is the generalized and exported version of generateNoncePair. -func GenerateNoncePair(curve *TwistedEdwardsCurve, msg []byte, - privkey *PrivateKey, extra []byte, +func GenerateNoncePair(msg []byte, privkey *PrivateKey, extra []byte, version []byte) (*PrivateKey, *PublicKey, error) { - priv, pubNonce, err := generateNoncePair(curve, msg, privkey.Serialize(), + priv, pubNonce, err := generateNoncePair(msg, privkey.Serialize(), nonceRFC6979, extra, version) if err != nil { return nil, nil, err } - privNonce := NewPrivateKey(curve, + privNonce := NewPrivateKey( EncodedBytesToBigIntNoReverse(copyBytes(priv))) return privNonce, pubNonce, nil } // schnorrPartialSign creates a partial Schnorr signature which may be combined // with other Schnorr signatures to create a valid signature for a group pubkey. -func schnorrPartialSign(curve *TwistedEdwardsCurve, msg []byte, priv []byte, +func schnorrPartialSign(msg []byte, priv []byte, groupPublicKey []byte, privNonce []byte, pubNonceSum []byte) (*big.Int, *big.Int, error) { @@ -128,6 +130,7 @@ func schnorrPartialSign(curve *TwistedEdwardsCurve, msg []byte, priv []byte, return nil, nil, fmt.Errorf("%v", str) } + curve := Edwards() privBig := new(big.Int).SetBytes(priv) if privBig.Cmp(zero) == 0 { str := fmt.Sprintf("priv scalar is zero") @@ -170,34 +173,34 @@ func schnorrPartialSign(curve *TwistedEdwardsCurve, msg []byte, priv []byte, return nil, nil, fmt.Errorf("%v", str) } - privDecoded, _, _ := PrivKeyFromScalar(curve, priv) - groupPubKeyDecoded, _ := ParsePubKey(curve, groupPublicKey) - privNonceDecoded, _, _ := PrivKeyFromScalar(curve, privNonce) - pubNonceSumDecoded, _ := ParsePubKey(curve, pubNonceSum) + privDecoded, _, _ := PrivKeyFromScalar(priv) + groupPubKeyDecoded, _ := ParsePubKey(groupPublicKey) + privNonceDecoded, _, _ := PrivKeyFromScalar(privNonce) + pubNonceSumDecoded, _ := ParsePubKey(pubNonceSum) - return SignThreshold(curve, privDecoded, groupPubKeyDecoded, msg, + return SignThreshold(privDecoded, groupPubKeyDecoded, msg, privNonceDecoded, pubNonceSumDecoded) } // SchnorrPartialSign is the generalized and exported version of // schnorrPartialSign. -func SchnorrPartialSign(curve *TwistedEdwardsCurve, msg []byte, - priv *PrivateKey, groupPub *PublicKey, privNonce *PrivateKey, - pubSum *PublicKey) (*big.Int, *big.Int, error) { +func SchnorrPartialSign(msg []byte, priv *PrivateKey, groupPub *PublicKey, + privNonce *PrivateKey, pubSum *PublicKey) (*big.Int, *big.Int, error) { privBytes := priv.Serialize() defer zeroSlice(privBytes) privNonceBytes := privNonce.Serialize() defer zeroSlice(privNonceBytes) - return schnorrPartialSign(curve, msg, privBytes, groupPub.Serialize(), + return schnorrPartialSign(msg, privBytes, groupPub.Serialize(), privNonceBytes, pubSum.Serialize()) } // schnorrCombineSigs combines a list of partial Schnorr signatures s values // into a complete signature s for some group public key. This is achieved // by simply adding the s values of the partial signatures as scalars. -func schnorrCombineSigs(curve *TwistedEdwardsCurve, sigss [][]byte) (*big.Int, error) { +func schnorrCombineSigs(sigss [][]byte) (*big.Int, error) { + curve := Edwards() combinedSigS := new(big.Int).SetInt64(0) for i, sigs := range sigss { sigsBI := EncodedBytesToBigInt(copyBytes(sigs)) @@ -224,8 +227,7 @@ func schnorrCombineSigs(curve *TwistedEdwardsCurve, sigss [][]byte) (*big.Int, e // SchnorrCombineSigs is the generalized and exported version of // generateNoncePair. -func SchnorrCombineSigs(curve *TwistedEdwardsCurve, - sigs []*Signature) (*Signature, error) { +func SchnorrCombineSigs(sigs []*Signature) (*Signature, error) { sigss := make([][]byte, len(sigs)) for i, sig := range sigs { if sig == nil { @@ -243,7 +245,7 @@ func SchnorrCombineSigs(curve *TwistedEdwardsCurve, sigss[i] = BigIntToEncodedBytes(sig.GetS())[:] } - combinedSigS, err := schnorrCombineSigs(curve, sigss) + combinedSigS, err := schnorrCombineSigs(sigss) if err != nil { return nil, err } diff --git a/dcrec/edwards/threshold_test.go b/dcrec/edwards/threshold_test.go index af3219fa..cfdb0890 100644 --- a/dcrec/edwards/threshold_test.go +++ b/dcrec/edwards/threshold_test.go @@ -18,12 +18,9 @@ func TestSchnorrThreshold(t *testing.T) { numTests := 5 numSignatories := maxSignatories * numTests - curve := new(TwistedEdwardsCurve) - curve.InitParam25519() - msg, _ := hex.DecodeString( "d04b98f48e8f8bcc15c6ae5ac050801cd6dcfd428fb5f9e65c4e16e7807340fa") - privkeys := randPrivScalarKeyList(curve, numSignatories) + privkeys := randPrivScalarKeyList(numSignatories) for i := 0; i < numTests; i++ { numKeysForTest := tRand.Intn(maxSignatories-2) + 2 @@ -35,7 +32,7 @@ func TestSchnorrThreshold(t *testing.T) { pubKeysToUse := make([]*PublicKey, numKeysForTest) for j := 0; j < numKeysForTest; j++ { - _, pubkey, _ := PrivKeyFromScalar(curve, + _, pubkey, _ := PrivKeyFromScalar( keysToUse[j].Serialize()) pubKeysToUse[j] = pubkey } @@ -44,19 +41,20 @@ func TestSchnorrThreshold(t *testing.T) { allPubkeys := make([]*PublicKey, numKeysForTest) copy(allPubkeys, pubKeysToUse) - allPksSum := CombinePubkeys(curve, allPubkeys) + allPksSum := CombinePubkeys(allPubkeys) + curve := Edwards() privNoncesToUse := make([]*PrivateKey, numKeysForTest) pubNoncesToUse := make([]*PublicKey, numKeysForTest) for j := 0; j < numKeysForTest; j++ { - nonce := nonceRFC6979(curve, keysToUse[j].Serialize(), msg, nil, + nonce := nonceRFC6979(keysToUse[j].Serialize(), msg, nil, Sha512VersionStringRFC6979) nonceBig := new(big.Int).SetBytes(nonce) nonceBig.Mod(nonceBig, curve.N) nonce = copyBytes(nonceBig.Bytes())[:] nonce[31] &= 248 - privNonce, pubNonce, err := PrivKeyFromScalar(curve, + privNonce, pubNonce, err := PrivKeyFromScalar( nonce[:]) cmp := privNonce != nil if !cmp { @@ -79,13 +77,13 @@ func TestSchnorrThreshold(t *testing.T) { partialSignatures := make([]*Signature, numKeysForTest) // Partial signature generation. - publicNonceSum := CombinePubkeys(curve, pubNoncesToUse) + publicNonceSum := CombinePubkeys(pubNoncesToUse) cmp := publicNonceSum != nil if !cmp { t.Fatalf("expected %v, got %v", true, cmp) } for j := range keysToUse { - r, s, err := schnorrPartialSign(curve, msg, keysToUse[j].Serialize(), + r, s, err := schnorrPartialSign(msg, keysToUse[j].Serialize(), allPksSum.Serialize(), privNoncesToUse[j].Serialize(), publicNonceSum.Serialize()) if err != nil { @@ -97,7 +95,7 @@ func TestSchnorrThreshold(t *testing.T) { } // Combine signatures. - combinedSignature, err := SchnorrCombineSigs(curve, partialSignatures) + combinedSignature, err := SchnorrCombineSigs(partialSignatures) if err != nil { t.Fatalf("unexpected error %s, ", err) } @@ -117,17 +115,17 @@ func TestSchnorrThreshold(t *testing.T) { combinedNonceD.Mod(combinedNonceD, curve.N) } - combinedPrivkey, _, err := PrivKeyFromScalar(curve, + combinedPrivkey, _, err := PrivKeyFromScalar( copyBytes(combinedPrivkeysD.Bytes())[:]) if err != nil { t.Fatalf("unexpected error %s, ", err) } - combinedNonce, _, err := PrivKeyFromScalar(curve, + combinedNonce, _, err := PrivKeyFromScalar( copyBytes(combinedNonceD.Bytes())[:]) if err != nil { t.Fatalf("unexpected error %s, ", err) } - cSigR, cSigS, err := SignFromScalar(curve, combinedPrivkey, + cSigR, cSigS, err := SignFromScalar(combinedPrivkey, combinedNonce.Serialize(), msg) sumSig := NewSignature(cSigR, cSigS) cmp = bytes.Equal(sumSig.Serialize(), combinedSignature.Serialize()) @@ -194,9 +192,9 @@ func TestSchnorrThreshold(t *testing.T) { localPubNonces[itr] = pubNonce itr++ } - publicNonceSum := CombinePubkeys(curve, localPubNonces) + publicNonceSum := CombinePubkeys(localPubNonces) - sigR, sigS, _ := schnorrPartialSign(curve, msg, + sigR, sigS, _ := schnorrPartialSign(msg, keysToUse[j].Serialize(), allPksSum.Serialize(), privNoncesToUse[j].Serialize(), publicNonceSum.Serialize()) @@ -206,7 +204,7 @@ func TestSchnorrThreshold(t *testing.T) { } // Combine signatures. - combinedSignature, _ = SchnorrCombineSigs(curve, partialSignatures) + combinedSignature, _ = SchnorrCombineSigs(partialSignatures) // Nothing that makes it here should be valid. if allPksSum != nil && combinedSignature != nil {