func TestGenerateSharedSecret(t *testing.T) { c := secp256k1.S256() privKey1, err := secp256k1.GeneratePrivateKey(secp256k1.S256()) if err != nil { t.Errorf("private key generation error: %s", err) return } privKey2, err := secp256k1.GeneratePrivateKey(secp256k1.S256()) if err != nil { t.Errorf("private key generation error: %s", err) return } pk1x, pk1y := privKey1.Public() pk1 := secp256k1.NewPublicKey(c, pk1x, pk1y) pk2x, pk2y := privKey2.Public() pk2 := secp256k1.NewPublicKey(c, pk2x, pk2y) secret1 := secp256k1.GenerateSharedSecret(privKey1, pk2) secret2 := secp256k1.GenerateSharedSecret(privKey2, pk1) if !bytes.Equal(secret1, secret2) { t.Errorf("ECDH failed, secrets mismatch - first: %x, second: %x", secret1, secret2) } }
// Test 1: Encryption and decryption func TestCipheringBasic(t *testing.T) { c := secp256k1.S256() privkey, err := secp256k1.GeneratePrivateKey(secp256k1.S256()) if err != nil { t.Fatal("failed to generate private key") } in := []byte("Hey there dude. How are you doing? This is a test.") pk1x, pk1y := privkey.Public() pk1 := secp256k1.NewPublicKey(c, pk1x, pk1y) out, err := secp256k1.Encrypt(pk1, in) if err != nil { t.Fatal("failed to encrypt:", err) } dec, err := secp256k1.Decrypt(privkey, out) if err != nil { t.Fatal("failed to decrypt:", err) } if !bytes.Equal(in, dec) { t.Error("decrypted data doesn't match original") } }
// CombinePubkeys combines a slice of public keys into a single public key // by adding them together with point addition. func CombinePubkeys(curve *secp256k1.KoblitzCurve, pks []*secp256k1.PublicKey) *secp256k1.PublicKey { numPubKeys := len(pks) // Have to have at least two pubkeys. if numPubKeys < 1 { return nil } if numPubKeys == 1 { return pks[0] } if pks[0] == nil || pks[1] == nil { return nil } var pkSumX *big.Int var pkSumY *big.Int pkSumX, pkSumY = curve.Add(pks[0].GetX(), pks[0].GetY(), pks[1].GetX(), pks[1].GetY()) if numPubKeys > 2 { for i := 2; i < numPubKeys; i++ { pkSumX, pkSumY = curve.Add(pkSumX, pkSumY, pks[i].GetX(), pks[i].GetY()) } } if !curve.IsOnCurve(pkSumX, pkSumY) { return nil } return secp256k1.NewPublicKey(curve, pkSumX, pkSumY) }
func randSigList(curve *secp256k1.KoblitzCurve, i int) []*SignatureVerParams { r := rand.New(rand.NewSource(54321)) privKeyList := make([]*secp256k1.PrivateKey, i, i) for j := 0; j < i; j++ { for { bIn := new([32]byte) for k := 0; k < scalarSize; k++ { randByte := r.Intn(255) bIn[k] = uint8(randByte) } pks, _ := secp256k1.PrivKeyFromBytes(curve, bIn[:]) if pks == nil { continue } privKeyList[j] = pks r.Seed(int64(j) + 54321) break } } msgList := make([][]byte, i, i) for j := 0; j < i; j++ { m := make([]byte, 32, 32) for k := 0; k < scalarSize; k++ { randByte := r.Intn(255) m[k] = uint8(randByte) } msgList[j] = m r.Seed(int64(j) + 54321) } sigsList := make([]*Signature, i, i) for j := 0; j < i; j++ { r, s, err := Sign(curve, privKeyList[j], msgList[j]) if err != nil { panic("sign failure") } sig := &Signature{r, s} sigsList[j] = sig } sigStructList := make([]*SignatureVerParams, i, i) for j := 0; j < i; j++ { ss := new(SignatureVerParams) pkx, pky := privKeyList[j].Public() ss.pubkey = secp256k1.NewPublicKey(curve, pkx, pky) ss.msg = msgList[j] ss.sig = sigsList[j] sigStructList[j] = ss } return sigStructList }
func testSignAndVerify(t *testing.T, c *secp256k1.KoblitzCurve, tag string) { priv, _ := secp256k1.GeneratePrivateKey(c) pubx, puby := priv.Public() pub := secp256k1.NewPublicKey(c, pubx, puby) hashed := []byte("testing") sig, err := priv.Sign(hashed) if err != nil { t.Errorf("%s: error signing: %s", tag, err) return } if !sig.Verify(hashed, pub) { t.Errorf("%s: Verify failed", tag) } hashed[0] ^= 0xff if sig.Verify(hashed, pub) { t.Errorf("%s: Verify always works!", tag) } }
// generateNoncePair deterministically generate a nonce pair for use in // partial signing of a message. Returns a public key (nonce to disseminate) // and a private nonce to keep as a secret for the signer. func generateNoncePair(curve *secp256k1.KoblitzCurve, msg []byte, priv []byte, nonceFunction func([]byte, []byte, []byte, []byte) []byte, extra []byte, version []byte) ([]byte, *secp256k1.PublicKey, error) { k := nonceFunction(priv, msg, extra, version) bigK := new(big.Int).SetBytes(k) // k scalar sanity checks. if bigK.Cmp(bigZero) == 0 { str := fmt.Sprintf("k scalar is zero") return nil, nil, schnorrError(ErrBadNonce, str) } if bigK.Cmp(curve.N) >= 0 { str := fmt.Sprintf("k scalar is >= curve.N") return nil, nil, schnorrError(ErrBadNonce, str) } bigK.SetInt64(0) pubx, puby := curve.ScalarBaseMult(k) pubnonce := secp256k1.NewPublicKey(curve, pubx, puby) return k, pubnonce, nil }
// newSecSchnorrDSA instatiates a function DSA subsystem over the secp256k1 // curve. A caveat for the functions below is that they're all routed through // interfaces, and nil returns from the library itself for interfaces must // ALWAYS be checked by checking the return value by attempted dereference // (== nil). func newSecSchnorrDSA() DSA { var secp DSA = &secSchnorrDSA{ // Constants getP: func() *big.Int { return secp256k1Curve.P }, getN: func() *big.Int { return secp256k1Curve.N }, // EC Math add: func(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { return secp256k1Curve.Add(x1, y1, x2, y2) }, isOnCurve: func(x, y *big.Int) bool { return secp256k1Curve.IsOnCurve(x, y) }, scalarMult: func(x, y *big.Int, k []byte) (*big.Int, *big.Int) { return secp256k1Curve.ScalarMult(x, y, k) }, scalarBaseMult: func(k []byte) (*big.Int, *big.Int) { return secp256k1Curve.ScalarBaseMult(k) }, // Private keys newPrivateKey: func(d *big.Int) PrivateKey { pk := secp256k1.NewPrivateKey(secp256k1Curve, d) if pk != nil { return PrivateKey(pk) } return nil }, privKeyFromBytes: func(pk []byte) (PrivateKey, PublicKey) { priv, pub := secp256k1.PrivKeyFromBytes(secp256k1Curve, pk) if priv == nil { return nil, nil } if pub == nil { return nil, nil } tpriv := PrivateKey(priv) tpub := PublicKey(pub) return tpriv, tpub }, privKeyFromScalar: func(pk []byte) (PrivateKey, PublicKey) { priv, pub := secp256k1.PrivKeyFromScalar(secp256k1Curve, pk) if priv == nil { return nil, nil } if pub == nil { return nil, nil } tpriv := PrivateKey(priv) tpub := PublicKey(pub) return tpriv, tpub }, privKeyBytesLen: func() int { return secp256k1.PrivKeyBytesLen }, // Public keys // Note that Schnorr only allows 33 byte public keys, however // as they are secp256k1 you still have access to the other // serialization types. newPublicKey: func(x *big.Int, y *big.Int) PublicKey { pk := secp256k1.NewPublicKey(secp256k1Curve, x, y) tpk := PublicKey(pk) return tpk }, parsePubKey: func(pubKeyStr []byte) (PublicKey, error) { pk, err := schnorr.ParsePubKey(secp256k1Curve, pubKeyStr) if err != nil { return nil, err } tpk := PublicKey(pk) return tpk, err }, pubKeyBytesLen: func() int { return schnorr.PubKeyBytesLen }, pubKeyBytesLenUncompressed: func() int { return schnorr.PubKeyBytesLen }, pubKeyBytesLenCompressed: func() int { return schnorr.PubKeyBytesLen }, pubKeyBytesLenHybrid: func() int { return schnorr.PubKeyBytesLen }, // Signatures newSignature: func(r *big.Int, s *big.Int) Signature { sig := schnorr.NewSignature(r, s) ts := Signature(sig) return ts }, parseDERSignature: func(sigStr []byte) (Signature, error) { sig, err := schnorr.ParseSignature(sigStr) ts := Signature(sig) return ts, err }, parseSignature: func(sigStr []byte) (Signature, error) { sig, err := schnorr.ParseSignature(sigStr) ts := Signature(sig) return ts, err }, recoverCompact: func(signature, hash []byte) (PublicKey, bool, error) { pk, bl, err := schnorr.RecoverPubkey(secp256k1Curve, signature, hash) tpk := PublicKey(pk) return tpk, bl, err }, // ECDSA generateKey: func(rand io.Reader) ([]byte, *big.Int, *big.Int, error) { return secp256k1.GenerateKey(secp256k1Curve, rand) }, sign: func(priv PrivateKey, hash []byte) (r, s *big.Int, err error) { spriv := secp256k1.NewPrivateKey(secp256k1Curve, priv.GetD()) return schnorr.Sign(secp256k1Curve, spriv, hash) }, verify: func(pub PublicKey, hash []byte, r, s *big.Int) bool { spub := secp256k1.NewPublicKey(secp256k1Curve, pub.GetX(), pub.GetY()) return schnorr.Verify(secp256k1Curve, spub, hash, r, s) }, // Symmetric cipher encryption generateSharedSecret: func(privkey []byte, x, y *big.Int) []byte { sprivkey, _ := secp256k1.PrivKeyFromBytes(secp256k1Curve, privkey) if sprivkey == nil { return nil } spubkey := secp256k1.NewPublicKey(secp256k1Curve, x, y) return secp256k1.GenerateSharedSecret(sprivkey, spubkey) }, encrypt: func(x, y *big.Int, in []byte) ([]byte, error) { spubkey := secp256k1.NewPublicKey(secp256k1Curve, x, y) return secp256k1.Encrypt(spubkey, in) }, decrypt: func(privkey []byte, in []byte) ([]byte, error) { sprivkey, _ := secp256k1.PrivKeyFromBytes(secp256k1Curve, privkey) if sprivkey == nil { return nil, fmt.Errorf("failure deserializing privkey") } return secp256k1.Decrypt(sprivkey, in) }, } return secp.(DSA) }
// schnorrRecover recovers a public key using a signature, hash function, // and message. It also attempts to verify the signature against the // regenerated public key. func schnorrRecover(curve *secp256k1.KoblitzCurve, sig, msg []byte, hashFunc func([]byte) []byte) (*secp256k1.PublicKey, bool, error) { if len(msg) != scalarSize { str := fmt.Sprintf("wrong size for message (got %v, want %v)", len(msg), scalarSize) return nil, false, schnorrError(ErrBadInputSize, str) } if len(sig) != SignatureSize { str := fmt.Sprintf("wrong size for signature (got %v, want %v)", len(sig), SignatureSize) return nil, false, schnorrError(ErrBadInputSize, str) } sigR := sig[:32] sigS := sig[32:] sigRCopy := make([]byte, scalarSize, scalarSize) copy(sigRCopy, sigR) toHash := append(sigRCopy, msg...) h := hashFunc(toHash) hBig := new(big.Int).SetBytes(h) // If the hash ends up larger than the order of the curve, abort. // Same thing for hash == 0 (as unlikely as that is...). if hBig.Cmp(curve.N) >= 0 { str := fmt.Sprintf("hash of (R || m) too big") return nil, false, schnorrError(ErrSchnorrHashValue, str) } if hBig.Cmp(bigZero) == 0 { str := fmt.Sprintf("hash of (R || m) is zero value") return nil, false, schnorrError(ErrSchnorrHashValue, str) } // Convert s to big int. sBig := EncodedBytesToBigInt(copyBytes(sigS)) // We also can't have s greater than the order of the curve. if sBig.Cmp(curve.N) >= 0 { str := fmt.Sprintf("s value is too big") return nil, false, schnorrError(ErrInputValue, str) } // r can't be larger than the curve prime. rBig := EncodedBytesToBigInt(copyBytes(sigR)) if rBig.Cmp(curve.P) == 1 { str := fmt.Sprintf("given R was greater than curve prime") return nil, false, schnorrError(ErrBadSigRNotOnCurve, str) } // Decompress the Y value. We know that the first bit must // be even. Use the PublicKey struct to make it easier. compressedPoint := make([]byte, PubKeyBytesLen, PubKeyBytesLen) compressedPoint[0] = pubkeyCompressed copy(compressedPoint[1:], sigR) rPoint, err := secp256k1.ParsePubKey(compressedPoint, curve) if err != nil { str := fmt.Sprintf("bad r point") return nil, false, schnorrError(ErrRegenerateRPoint, str) } // Get the inverse of the hash. hInv := new(big.Int).ModInverse(hBig, curve.N) hInv.Mod(hInv, curve.N) // Negate s. sBig.Sub(curve.N, sBig) sBig.Mod(sBig, curve.N) // s' = -s * inverse(h). sBig.Mul(sBig, hInv) sBig.Mod(sBig, curve.N) // Q = h^(-1)R + s'G lx, ly := curve.ScalarMult(rPoint.GetX(), rPoint.GetY(), hInv.Bytes()) rx, ry := curve.ScalarBaseMult(sBig.Bytes()) pkx, pky := curve.Add(lx, ly, rx, ry) // Check if the public key is on the curve. if !curve.IsOnCurve(pkx, pky) { str := fmt.Sprintf("pubkey not on curve") return nil, false, schnorrError(ErrPubKeyOffCurve, str) } pubkey := secp256k1.NewPublicKey(curve, pkx, pky) // Verify this signature. Slow, lots of double checks, could be more // cheaply implemented as // hQ + sG - R == 0 // which this function checks. // This will sometimes pass even for corrupted signatures, but // this shouldn't be a concern because whoever is using the // results should be checking the returned public key against // some known one anyway. In the case of these Schnorr signatures, // relatively high numbers of corrupted signatures (50-70%) // seem to produce valid pubkeys and valid signatures. _, err = schnorrVerify(curve, sig, pubkey, msg, hashFunc) if err != nil { str := fmt.Sprintf("pubkey/sig pair could not be validated") return nil, false, schnorrError(ErrRegenSig, str) } return pubkey, true, nil }
// newSecp256k1DSA instatiates a function DSA subsystem over the secp256k1 // curve. A caveat for the functions below is that they're all routed through // interfaces, and nil returns from the library itself for interfaces must // ALWAYS be checked by checking the return value by attempted dereference // (== nil). func newSecp256k1DSA() DSA { var secp DSA = &secp256k1DSA{ // Constants getP: func() *big.Int { return secp256k1Curve.P }, getN: func() *big.Int { return secp256k1Curve.N }, // EC Math add: func(x1, y1, x2, y2 *big.Int) (*big.Int, *big.Int) { return secp256k1Curve.Add(x1, y1, x2, y2) }, isOnCurve: func(x, y *big.Int) bool { return secp256k1Curve.IsOnCurve(x, y) }, scalarMult: func(x, y *big.Int, k []byte) (*big.Int, *big.Int) { return secp256k1Curve.ScalarMult(x, y, k) }, scalarBaseMult: func(k []byte) (*big.Int, *big.Int) { return secp256k1Curve.ScalarBaseMult(k) }, // Private keys newPrivateKey: func(d *big.Int) PrivateKey { if d == nil { return nil } pk := secp256k1.NewPrivateKey(secp256k1Curve, d) if pk != nil { return PrivateKey(pk) } return nil }, privKeyFromBytes: func(pk []byte) (PrivateKey, PublicKey) { priv, pub := secp256k1.PrivKeyFromBytes(secp256k1Curve, pk) if priv == nil { return nil, nil } if pub == nil { return nil, nil } tpriv := PrivateKey(priv) tpub := PublicKey(pub) return tpriv, tpub }, privKeyFromScalar: func(pk []byte) (PrivateKey, PublicKey) { priv, pub := secp256k1.PrivKeyFromScalar(secp256k1Curve, pk) if priv == nil { return nil, nil } if pub == nil { return nil, nil } tpriv := PrivateKey(priv) tpub := PublicKey(pub) return tpriv, tpub }, privKeyBytesLen: func() int { return secp256k1.PrivKeyBytesLen }, // Public keys newPublicKey: func(x *big.Int, y *big.Int) PublicKey { pk := secp256k1.NewPublicKey(secp256k1Curve, x, y) tpk := PublicKey(pk) return tpk }, parsePubKey: func(pubKeyStr []byte) (PublicKey, error) { pk, err := secp256k1.ParsePubKey(pubKeyStr, secp256k1Curve) if err != nil { return nil, err } tpk := PublicKey(pk) return tpk, err }, pubKeyBytesLen: func() int { return secp256k1.PubKeyBytesLenCompressed }, pubKeyBytesLenUncompressed: func() int { return secp256k1.PubKeyBytesLenUncompressed }, pubKeyBytesLenCompressed: func() int { return secp256k1.PubKeyBytesLenCompressed }, pubKeyBytesLenHybrid: func() int { return secp256k1.PubKeyBytesLenHybrid }, // Signatures newSignature: func(r *big.Int, s *big.Int) Signature { sig := secp256k1.NewSignature(r, s) ts := Signature(sig) return ts }, parseDERSignature: func(sigStr []byte) (Signature, error) { sig, err := secp256k1.ParseDERSignature(sigStr, secp256k1Curve) if err != nil { return nil, err } ts := Signature(sig) return ts, err }, parseSignature: func(sigStr []byte) (Signature, error) { sig, err := secp256k1.ParseSignature(sigStr, secp256k1Curve) if err != nil { return nil, err } ts := Signature(sig) return ts, err }, recoverCompact: func(signature, hash []byte) (PublicKey, bool, error) { pk, bl, err := secp256k1.RecoverCompact(secp256k1Curve, signature, hash) tpk := PublicKey(pk) return tpk, bl, err }, // ECDSA generateKey: func(rand io.Reader) ([]byte, *big.Int, *big.Int, error) { return secp256k1.GenerateKey(secp256k1Curve, rand) }, sign: func(priv PrivateKey, hash []byte) (r, s *big.Int, err error) { if priv.GetType() != ECTypeSecp256k1 { return nil, nil, errors.New("wrong type") } spriv, ok := priv.(*secp256k1.PrivateKey) if !ok { return nil, nil, errors.New("wrong type") } sig, err := spriv.Sign(hash) if sig != nil { r = sig.GetR() s = sig.GetS() } return }, verify: func(pub PublicKey, hash []byte, r, s *big.Int) bool { spub := secp256k1.NewPublicKey(secp256k1Curve, pub.GetX(), pub.GetY()) ssig := secp256k1.NewSignature(r, s) return ssig.Verify(hash, spub) }, // Symmetric cipher encryption generateSharedSecret: func(privkey []byte, x, y *big.Int) []byte { sprivkey, _ := secp256k1.PrivKeyFromBytes(secp256k1Curve, privkey) if sprivkey == nil { return nil } spubkey := secp256k1.NewPublicKey(secp256k1Curve, x, y) return secp256k1.GenerateSharedSecret(sprivkey, spubkey) }, encrypt: func(x, y *big.Int, in []byte) ([]byte, error) { spubkey := secp256k1.NewPublicKey(secp256k1Curve, x, y) return secp256k1.Encrypt(spubkey, in) }, decrypt: func(privkey []byte, in []byte) ([]byte, error) { sprivkey, _ := secp256k1.PrivKeyFromBytes(secp256k1Curve, privkey) if sprivkey == nil { return nil, fmt.Errorf("failure deserializing privkey") } return secp256k1.Decrypt(sprivkey, in) }, } return secp.(DSA) }