From f6a30e074d2254e9fcbbc29357a692e799dbfc51 Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 10 Feb 2022 17:40:48 -0800 Subject: [PATCH 1/3] build: update to btcec/v2 and btcd/btcutil In this commit we update our deps to use the new `btcec/v2` APIs as well as point to the new `btcd/btcutil` repo. Along the way, we get a ~8% speed up in packet construction, and a ~9% speed up in packet processing due to the more optimized EC routines that `btcec/v2` uses. Benchmark run with the new changes: ``` goos: darwin goarch: amd64 pkg: github.com/lightningnetwork/lightning-onion cpu: VirtualApple @ 2.50GHz BenchmarkPathPacketConstruction-8 366 3260221 ns/op 174541 B/op 1411 allocs/op BenchmarkProcessPacket-8 4926 247395 ns/op 21059 B/op 68 allocs/op PASS ``` Benchmark run with the old code: ``` goos: darwin goarch: amd64 pkg: github.com/lightningnetwork/lightning-onion cpu: VirtualApple @ 2.50GHz BenchmarkPathPacketConstruction-8 332 3522599 ns/op 170336 B/op 1410 allocs/op BenchmarkProcessPacket-8 4425 270806 ns/op 22166 B/op 99 allocs/op PASS ``` --- bench_test.go | 6 ++-- cmd/main.go | 8 ++--- crypto.go | 47 +++++++++++++++++++++--------- go.mod | 9 +++--- go.sum | 71 ++++++++++++++++++++++++++++++++++++++------- hornet.go | 2 +- obfuscation.go | 6 ++-- obfuscation_test.go | 12 ++++---- packetfiller.go | 2 +- path.go | 4 +-- sphinx.go | 24 +++++++-------- sphinx_test.go | 24 ++++++--------- 12 files changed, 139 insertions(+), 76 deletions(-) diff --git a/bench_test.go b/bench_test.go index 40aa252..457e6c5 100644 --- a/bench_test.go +++ b/bench_test.go @@ -4,7 +4,7 @@ import ( "bytes" "testing" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" ) var ( @@ -22,7 +22,7 @@ func BenchmarkPathPacketConstruction(b *testing.B) { ) for i := 0; i < NumMaxHops; i++ { - privKey, err := btcec.NewPrivateKey(btcec.S256()) + privKey, err := btcec.NewPrivateKey() if err != nil { b.Fatalf("unable to generate key: %v", privKey) } @@ -44,7 +44,7 @@ func BenchmarkPathPacketConstruction(b *testing.B) { } } - d, _ := btcec.PrivKeyFromBytes(btcec.S256(), bytes.Repeat([]byte{'A'}, 32)) + d, _ := btcec.PrivKeyFromBytes(bytes.Repeat([]byte{'A'}, 32)) b.ReportAllocs() diff --git a/cmd/main.go b/cmd/main.go index 3b43868..5266555 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -10,7 +10,7 @@ import ( "os" "strings" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" sphinx "github.com/lightningnetwork/lightning-onion" ) @@ -44,7 +44,7 @@ func parseOnionSpec(spec OnionSpec) (*sphinx.PaymentPath, *btcec.PrivateKey, err binSessionKey = bytes.Repeat([]byte{'A'}, 32) } - sessionKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), binSessionKey) + sessionKey, _ := btcec.PrivKeyFromBytes(binSessionKey) for i, hop := range spec.Hops { binKey, err := hex.DecodeString(hop.PublicKey) @@ -52,7 +52,7 @@ func parseOnionSpec(spec OnionSpec) (*sphinx.PaymentPath, *btcec.PrivateKey, err log.Fatalf("%s is not a valid hex pubkey %s", hop.PublicKey, err) } - pubkey, err := btcec.ParsePubKey(binKey, btcec.S256()) + pubkey, err := btcec.ParsePubKey(binKey) if err != nil { log.Fatalf("%s is not a valid hex pubkey %s", hop.PublicKey, err) } @@ -132,7 +132,7 @@ func main() { log.Fatalf("Error decoding message: %s", err) } - privkey, _ := btcec.PrivKeyFromBytes(btcec.S256(), binKey) + privkey, _ := btcec.PrivKeyFromBytes(binKey) privKeyECDH := &sphinx.PrivKeyECDH{PrivKey: privkey} replayLog := sphinx.NewMemoryReplayLog() s := sphinx.NewRouter( diff --git a/crypto.go b/crypto.go index 9988a75..939f9ec 100644 --- a/crypto.go +++ b/crypto.go @@ -8,7 +8,8 @@ import ( "fmt" "github.com/aead/chacha20" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" + secp "github.com/decred/dcrd/dcrec/secp256k1/v4" ) const ( @@ -65,10 +66,16 @@ func (p *PrivKeyECDH) PubKey() *btcec.PublicKey { // // NOTE: This is part of the SingleKeyECDH interface. func (p *PrivKeyECDH) ECDH(pub *btcec.PublicKey) ([32]byte, error) { - s := &btcec.PublicKey{} - s.X, s.Y = btcec.S256().ScalarMult(pub.X, pub.Y, p.PrivKey.D.Bytes()) + var pubJ btcec.JacobianPoint + pub.AsJacobian(&pubJ) - return sha256.Sum256(s.SerializeCompressed()), nil + var ecdhPoint btcec.JacobianPoint + btcec.ScalarMultNonConst(&p.PrivKey.Key, &pubJ, &ecdhPoint) + + ecdhPoint.ToAffine() + ecdhPubKey := btcec.NewPublicKey(&ecdhPoint.X, &ecdhPoint.Y) + + return sha256.Sum256(ecdhPubKey.SerializeCompressed()), nil } // DecryptedError contains the decrypted error message and its sender. @@ -153,7 +160,7 @@ func generateCipherStream(key [keyLen]byte, numBytes uint) []byte { // sharedSecret for this hop. The blinding factor is computed as the // sha-256(pubkey || sharedSecret). func computeBlindingFactor(hopPubKey *btcec.PublicKey, - hopSharedSecret []byte) Hash256 { + hopSharedSecret []byte) btcec.ModNScalar { sha := sha256.New() sha.Write(hopPubKey.SerializeCompressed()) @@ -161,21 +168,35 @@ func computeBlindingFactor(hopPubKey *btcec.PublicKey, var hash Hash256 copy(hash[:], sha.Sum(nil)) - return hash + + var blindingBytes btcec.ModNScalar + blindingBytes.SetByteSlice(hash[:]) + + return blindingBytes } // blindGroupElement blinds the group element P by performing scalar // multiplication of the group element by blindingFactor: blindingFactor * P. -func blindGroupElement(hopPubKey *btcec.PublicKey, blindingFactor []byte) *btcec.PublicKey { - newX, newY := btcec.S256().ScalarMult(hopPubKey.X, hopPubKey.Y, blindingFactor[:]) - return &btcec.PublicKey{btcec.S256(), newX, newY} +func blindGroupElement(hopPubKey *btcec.PublicKey, blindingFactor btcec.ModNScalar) *btcec.PublicKey { + var hopPubKeyJ btcec.JacobianPoint + hopPubKey.AsJacobian(&hopPubKeyJ) + + var blindedPoint btcec.JacobianPoint + btcec.ScalarMultNonConst( + &blindingFactor, &hopPubKeyJ, &blindedPoint, + ) + blindedPoint.ToAffine() + + return btcec.NewPublicKey(&blindedPoint.X, &blindedPoint.Y) } // blindBaseElement blinds the groups's generator G by performing scalar base // multiplication using the blindingFactor: blindingFactor * G. -func blindBaseElement(blindingFactor []byte) *btcec.PublicKey { - newX, newY := btcec.S256().ScalarBaseMult(blindingFactor) - return &btcec.PublicKey{btcec.S256(), newX, newY} +func blindBaseElement(blindingFactor btcec.ModNScalar) *btcec.PublicKey { + // TODO(roasbeef): remove after btcec version bump to add alias for + // this method + priv := secp.NewPrivateKey(&blindingFactor) + return priv.PubKey() } // sharedSecretGenerator is an interface that abstracts away exactly *how* the @@ -193,7 +214,7 @@ func (r *Router) generateSharedSecret(dhKey *btcec.PublicKey) (Hash256, error) { var sharedSecret Hash256 // Ensure that the public key is on our curve. - if !btcec.S256().IsOnCurve(dhKey.X, dhKey.Y) { + if !dhKey.IsOnCurve() { return sharedSecret, ErrInvalidOnionKey } diff --git a/go.mod b/go.mod index 4d19c54..d274362 100644 --- a/go.mod +++ b/go.mod @@ -2,12 +2,13 @@ module github.com/lightningnetwork/lightning-onion require ( github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da - github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8 + github.com/btcsuite/btcd v0.22.0-beta.0.20220207191057-4dc4ff7963b4 + github.com/btcsuite/btcd/btcec/v2 v2.1.0 + github.com/btcsuite/btcd/btcutil v1.1.0 github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f - github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d github.com/davecgh/go-spew v1.1.1 - golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 - golang.org/x/sys v0.0.0-20190209173611-3b5209105503 // indirect + github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 + golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 ) go 1.13 diff --git a/go.sum b/go.sum index ca83343..fe83050 100644 --- a/go.sum +++ b/go.sum @@ -1,42 +1,93 @@ github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmHS9iAKVt9AyzRSqNU1qabPih5BY= github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA= -github.com/aead/siphash v1.0.1 h1:FwHfE/T45KPKYuuSAKyyvE+oPWcaQ+CUmFW0bPlM+kg= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= -github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8 h1:mOg8/RgDSHTQ1R0IR+LMDuW4TDShPv+JzYHuR4GLoNA= -github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= +github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= +github.com/btcsuite/btcd v0.22.0-beta.0.20220111032746-97732e52810c/go.mod h1:tjmYdS6MLJ5/s0Fj4DbLgSbDHbEqLJrtnHecBFkdz5M= +github.com/btcsuite/btcd v0.22.0-beta.0.20220207191057-4dc4ff7963b4 h1:CEGr/598C/0LZQUoioaT6sdGGcJgu4+ck0PDeJ/QkKs= +github.com/btcsuite/btcd v0.22.0-beta.0.20220207191057-4dc4ff7963b4/go.mod h1:7alexyj/lHlOtr2PJK7L/+HDJZpcGDn/pAU98r7DY08= +github.com/btcsuite/btcd/btcec/v2 v2.1.0 h1:Whmbo9yShKKG+WrUfYGFfgj77vYBiwhwBSJnM66TMKI= +github.com/btcsuite/btcd/btcec/v2 v2.1.0/go.mod h1:2VzYrv4Gm4apmbVVsSq5bqf1Ec8v56E48Vt0Y/umPgA= +github.com/btcsuite/btcd/btcutil v1.0.0/go.mod h1:Uoxwv0pqYWhD//tfTiipkxNfdhG9UrLwaeswfjfdF0A= +github.com/btcsuite/btcd/btcutil v1.1.0 h1:MO4klnGY+EWJdoWF12Wkuf4AWDBPMpZNeN/jRLrklUU= +github.com/btcsuite/btcd/btcutil v1.1.0/go.mod h1:5OapHB7A2hBBWLm48mmw4MOHNJCcUBTwmWH/0Jn8VHE= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= -github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d h1:yJzD/yFppdVCf6ApMkVy8cUxV0XrxdP9rVf6D87/Mng= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= -github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd h1:R/opQEbFEy9JGkIguV40SvRY1uliPX8ifOvi6ICsFCw= github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg= github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY= +github.com/btcsuite/goleveldb v1.0.0/go.mod h1:QiK9vBlgftBg6rWQIj6wFzbPfRjiykIEhBH4obrXJ/I= github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= -github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792 h1:R8vQdOQdZ9Y3SkEwmHoWBmX1DNXhXZqlTpq6s4tyJGc= +github.com/btcsuite/snappy-go v1.0.0/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc= github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY= github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs= github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/decred/dcrd/crypto/blake256 v1.0.0/go.mod h1:sQl2p6Y26YV+ZOcSTP6thNdn47hh8kt6rqSlvmrXFAc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 h1:YLtO71vCjJRCBcrPMtQ9nqBsqpA1m5sE92cU+pd5Mcc= +github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeCxkaw7y45JueMRL4DIyJDKs= +github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= +github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= +github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= +github.com/onsi/ginkgo v1.14.0/go.mod h1:iSB4RoI2tjJc9BBv4NKIKWKya62Rps+oPG/Lv9klQyY= +github.com/onsi/gomega v1.4.1/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67 h1:ng3VDlRp5/DHpSWl02R4rM9I+8M2rhmsuLwAMmkLQWE= -golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/net v0.0.0-20180719180050-a680a1efc54d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= +golang.org/x/net v0.0.0-20200813134508-3edf25e44fcc/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190209173611-3b5209105503 h1:5SvYFrOM3W8Mexn9/oA44Ji7vhXAZQ9hiP+1Q/DMrWg= -golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed h1:J22ig1FUekjjkmZUM7pTKixYm8DvrYsvrBZdunYeIuQ= +golang.org/x/sys v0.0.0-20200814200057-3d37ad5750ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/hornet.go b/hornet.go index 7b65ea0..b1c07c3 100644 --- a/hornet.go +++ b/hornet.go @@ -1,7 +1,7 @@ package sphinx import ( - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "golang.org/x/crypto/ripemd160" ) diff --git a/obfuscation.go b/obfuscation.go index 06a0b9e..b8df7cc 100644 --- a/obfuscation.go +++ b/obfuscation.go @@ -3,7 +3,7 @@ package sphinx import ( "io" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" ) // OnionErrorEncrypter is a struct that's used to implement onion error @@ -62,7 +62,7 @@ func (c *Circuit) Decode(r io.Reader) error { return err } - c.SessionKey, _ = btcec.PrivKeyFromBytes(btcec.S256(), sessionKeyData) + c.SessionKey, _ = btcec.PrivKeyFromBytes(sessionKeyData) var pathLength [1]byte if _, err := r.Read(pathLength[:]); err != nil { return err @@ -75,7 +75,7 @@ func (c *Circuit) Decode(r io.Reader) error { return err } - pubKey, err := btcec.ParsePubKey(pubKeyData[:], btcec.S256()) + pubKey, err := btcec.ParsePubKey(pubKeyData[:]) if err != nil { return err } diff --git a/obfuscation_test.go b/obfuscation_test.go index c4ebf6e..dc476c8 100644 --- a/obfuscation_test.go +++ b/obfuscation_test.go @@ -7,7 +7,7 @@ import ( "reflect" "testing" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" ) // TestOnionFailure checks the ability of sender of payment to decode the @@ -16,14 +16,13 @@ func TestOnionFailure(t *testing.T) { // Create numHops random sphinx paymentPath. paymentPath := make([]*btcec.PublicKey, 5) for i := 0; i < len(paymentPath); i++ { - privKey, err := btcec.NewPrivateKey(btcec.S256()) + privKey, err := btcec.NewPrivateKey() if err != nil { t.Fatalf("unable to generate random key for sphinx node: %v", err) } paymentPath[i] = privKey.PubKey() } - sessionKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), - bytes.Repeat([]byte{'A'}, 32)) + sessionKey, _ := btcec.PrivKeyFromBytes(bytes.Repeat([]byte{'A'}, 32)) // Reduce the error path on one node, in order to check that we are // able to receive the error not only from last hop. @@ -152,7 +151,7 @@ func getSpecPubKeys() ([]*btcec.PublicKey, error) { return nil, err } - key, err := btcec.ParsePubKey(bKey, btcec.S256()) + key, err := btcec.ParsePubKey(bKey) if err != nil { return nil, err } @@ -168,7 +167,7 @@ func getSpecSessionKey() (*btcec.PrivateKey, error) { return nil, err } - privKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), bKey) + privKey, _ := btcec.PrivKeyFromBytes(bKey) return privKey, nil } @@ -202,7 +201,6 @@ func TestOnionFailureSpecVector(t *testing.T) { t.Fatalf("Unexpected error while generating secrets: %v", err) } for i, test := range onionErrorData { - // Decode the shared secret and check that it matchs with // specification. expectedSharedSecret, err := hex.DecodeString(test.sharedSecret) diff --git a/packetfiller.go b/packetfiller.go index 4fbbfb3..79c1441 100644 --- a/packetfiller.go +++ b/packetfiller.go @@ -4,7 +4,7 @@ import ( "crypto/rand" "github.com/aead/chacha20" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" ) // PacketFiller is a function type to be specified by the caller to provide a diff --git a/path.go b/path.go index 8a2e298..f46ba01 100644 --- a/path.go +++ b/path.go @@ -7,7 +7,7 @@ import ( "fmt" "io" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/wire" ) @@ -343,7 +343,7 @@ type OnionHop struct { // IsEmpty returns true if the hop isn't populated. func (o OnionHop) IsEmpty() bool { - return o.NodePub.X == nil || o.NodePub.Y == nil + return o.NodePub.X().BitLen() == 0 || o.NodePub.Y().BitLen() == 0 } // NodeKeys returns a slice pointing to node keys that this route comprises of. diff --git a/sphinx.go b/sphinx.go index 9b7a97a..36e9a81 100644 --- a/sphinx.go +++ b/sphinx.go @@ -6,12 +6,11 @@ import ( "crypto/sha256" "fmt" "io" - "math/big" "sync" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" + "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" - "github.com/btcsuite/btcutil" ) const ( @@ -151,29 +150,28 @@ func generateSharedSecrets(paymentPath []*btcec.PublicKey, // c_0 = x. At the beginning of each iteration, the previous blinding // factor is aggregated into the modular product, and used as the scalar // value in deriving the hop ephemeral keys and shared secrets. - var cachedBlindingFactor big.Int - cachedBlindingFactor.SetBytes(sessionKey.D.Bytes()) + var cachedBlindingFactor btcec.ModNScalar + cachedBlindingFactor.Set(&sessionKey.Key) // Now recursively compute the cached blinding factor, ephemeral ECDH // pub keys, and shared secret for each hop. - var nextBlindingFactor big.Int + var nextBlindingFactor btcec.ModNScalar for i := 1; i <= numHops-1; i++ { // Update the cached blinding factor with b_{i-1}. - nextBlindingFactor.SetBytes(lastBlindingFactor[:]) - cachedBlindingFactor.Mul(&cachedBlindingFactor, &nextBlindingFactor) - cachedBlindingFactor.Mod(&cachedBlindingFactor, btcec.S256().Params().N) + nextBlindingFactor.Set(&lastBlindingFactor) + cachedBlindingFactor.Mul(&nextBlindingFactor) // a_i = g ^ c_i // = g^( x * b_0 * ... * b_{i-1} ) // = X^( b_0 * ... * b_{i-1} ) // X_our_session_pub_key x all prev blinding factors - lastEphemeralPubKey = blindBaseElement(cachedBlindingFactor.Bytes()) + lastEphemeralPubKey = blindBaseElement(cachedBlindingFactor) // e_i = Y_i ^ c_i // = ( Y_i ^ x )^( b_0 * ... * b_{i-1} ) // (Y_their_pub_key x x_our_priv) x all prev blinding factors hopBlindedPubKey := blindGroupElement( - paymentPath[i], cachedBlindingFactor.Bytes(), + paymentPath[i], cachedBlindingFactor, ) // s_i = sha256( e_i ) @@ -403,7 +401,7 @@ func (f *OnionPacket) Decode(r io.Reader) error { if _, err := io.ReadFull(r, ephemeral[:]); err != nil { return err } - f.EphemeralKey, err = btcec.ParsePubKey(ephemeral[:], btcec.S256()) + f.EphemeralKey, err = btcec.ParsePubKey(ephemeral[:]) if err != nil { return ErrInvalidOnionKey } @@ -614,7 +612,7 @@ func unwrapPacket(onionPkt *OnionPacket, sharedSecret *Hash256, // Randomize the DH group element for the next hop using the // deterministic blinding factor. blindingFactor := computeBlindingFactor(dhKey, sharedSecret[:]) - nextDHKey := blindGroupElement(dhKey, blindingFactor[:]) + nextDHKey := blindGroupElement(dhKey, blindingFactor) // With the MAC checked, and the payload decrypted, we can now parse // out the payload so we can derive the specified forwarding diff --git a/sphinx_test.go b/sphinx_test.go index 9afcb3f..3425e76 100644 --- a/sphinx_test.go +++ b/sphinx_test.go @@ -9,7 +9,7 @@ import ( "reflect" "testing" - "github.com/btcsuite/btcd/btcec" + "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/chaincfg" "github.com/davecgh/go-spew/spew" ) @@ -43,7 +43,7 @@ func newTestRoute(numHops int) ([]*Router, *PaymentPath, *[]HopData, *OnionPacke // Create numHops random sphinx nodes. for i := 0; i < len(nodes); i++ { - privKey, err := btcec.NewPrivateKey(btcec.S256()) + privKey, err := btcec.NewPrivateKey() if err != nil { return nil, nil, nil, nil, fmt.Errorf("Unable to "+ "generate random key for sphinx node: %v", err) @@ -81,9 +81,7 @@ func newTestRoute(numHops int) ([]*Router, *PaymentPath, *[]HopData, *OnionPacke // Generate a forwarding message to route to the final node via the // generated intermediate nodes above. Destination should be Hash160, // adding padding so parsing still works. - sessionKey, _ := btcec.PrivKeyFromBytes( - btcec.S256(), bytes.Repeat([]byte{'A'}, 32), - ) + sessionKey, _ := btcec.PrivKeyFromBytes(bytes.Repeat([]byte{'A'}, 32)) fwdMsg, err := NewOnionPacket( &route, sessionKey, nil, DeterministicPacketFiller, ) @@ -117,7 +115,7 @@ func TestBolt4Packet(t *testing.T) { t.Fatalf("unable to decode BOLT 4 hex pubkey #%d: %v", i, err) } - pubKey, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256()) + pubKey, err := btcec.ParsePubKey(pubKeyBytes) if err != nil { t.Fatalf("unable to parse BOLT 4 pubkey #%d: %v", i, err) } @@ -134,8 +132,6 @@ func TestBolt4Packet(t *testing.T) { t.Fatalf("unable to make hop payload: %v", err) } - pubKey.Curve = nil - route[i] = OnionHop{ NodePub: *pubKey, HopPayload: hopPayload, @@ -148,7 +144,7 @@ func TestBolt4Packet(t *testing.T) { "%v", err) } - sessionKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), bolt4SessionKey) + sessionKey, _ := btcec.PrivKeyFromBytes(bolt4SessionKey) pkt, err := NewOnionPacket( &route, sessionKey, bolt4AssocData, DeterministicPacketFiller, ) @@ -487,7 +483,7 @@ func newEOBRoute(numHops uint32, // First, we'll assemble a set of routers that will consume all the // hops we create in this path. for i := 0; i < len(nodes); i++ { - privKey, err := btcec.NewPrivateKey(btcec.S256()) + privKey, err := btcec.NewPrivateKey() if err != nil { return nil, nil, fmt.Errorf("Unable to generate "+ "random key for sphinx node: %v", err) @@ -514,9 +510,7 @@ func newEOBRoute(numHops uint32, // Generate a forwarding message to route to the final node via the // generated intermediate nodes above. Destination should be Hash160, // adding padding so parsing still works. - sessionKey, _ := btcec.PrivKeyFromBytes( - btcec.S256(), bytes.Repeat([]byte{'A'}, 32), - ) + sessionKey, _ := btcec.PrivKeyFromBytes(bytes.Repeat([]byte{'A'}, 32)) fwdMsg, err := NewOnionPacket( &route, sessionKey, nil, DeterministicPacketFiller, ) @@ -828,7 +822,7 @@ func TestVariablePayloadOnion(t *testing.T) { if err != nil { t.Fatalf("unable to decode pubkey: %v", err) } - pubKey, err := btcec.ParsePubKey(pubKeyBytes, btcec.S256()) + pubKey, err := btcec.ParsePubKey(pubKeyBytes) if err != nil { t.Fatalf("unable to parse BOLT 4 pubkey #%d: %v", i, err) } @@ -875,7 +869,7 @@ func TestVariablePayloadOnion(t *testing.T) { } // With all the required data assembled, we'll craft a new packet. - sessionKey, _ := btcec.PrivKeyFromBytes(btcec.S256(), sessionKeyBytes) + sessionKey, _ := btcec.PrivKeyFromBytes(sessionKeyBytes) pkt, err := NewOnionPacket( &route, sessionKey, associatedData, DeterministicPacketFiller, ) From 56a62e1ff779259b8ff08733dfaffec14565921e Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 10 Feb 2022 17:55:15 -0800 Subject: [PATCH 2/3] bench: use 20 hops for the benchmark Turns out in practice, the 27 hop limit is actually _too large_, so we fall back to the old 20 hop limit for now. We'll want to circle back and emperically derive the _true_ hop limit. --- bench_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bench_test.go b/bench_test.go index 457e6c5..ef9e8ba 100644 --- a/bench_test.go +++ b/bench_test.go @@ -21,7 +21,7 @@ func BenchmarkPathPacketConstruction(b *testing.B) { route PaymentPath ) - for i := 0; i < NumMaxHops; i++ { + for i := 0; i < 20; i++ { privKey, err := btcec.NewPrivateKey() if err != nil { b.Fatalf("unable to generate key: %v", privKey) From bb84a1ccb0c5294687bfc9caed2acd626d76de2a Mon Sep 17 00:00:00 2001 From: Olaoluwa Osuntokun Date: Thu, 10 Feb 2022 18:16:28 -0800 Subject: [PATCH 3/3] build: bump Go version to 1.17.x --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6a302ae..b42af85 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,7 +7,7 @@ cache: - $GOPATH/src/github.com/golang go: - - "1.13.x" + - "1.17.x" sudo: required