From 99d756f0ed80b48a1262211bd6a1c9422fd149ba Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 16 Nov 2020 21:22:35 +0100 Subject: [PATCH 01/13] cmd/geth: implement vulnerability check --- cmd/geth/main.go | 1 + cmd/geth/misccmd.go | 11 +++++ cmd/geth/version_check.go | 95 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 cmd/geth/version_check.go diff --git a/cmd/geth/main.go b/cmd/geth/main.go index 38e48534dcb1..723e7694f5a6 100644 --- a/cmd/geth/main.go +++ b/cmd/geth/main.go @@ -241,6 +241,7 @@ func init() { makecacheCommand, makedagCommand, versionCommand, + versionCheckCommand, licenseCommand, // See config.go dumpConfigCommand, diff --git a/cmd/geth/misccmd.go b/cmd/geth/misccmd.go index 0e7ee965133c..e870e4f01e75 100644 --- a/cmd/geth/misccmd.go +++ b/cmd/geth/misccmd.go @@ -65,6 +65,17 @@ Regular users do not need to execute it. Category: "MISCELLANEOUS COMMANDS", Description: ` The output of this command is supposed to be machine-readable. +`, + } + versionCheckCommand = cli.Command{ + Action: utils.MigrateFlags(versionCheck), + Name: "version-check", + Usage: "Checks (online) whether the current version suffers from any known security vulnerabilities", + ArgsUsage: "", + Category: "MISCELLANEOUS COMMANDS", + Description: ` +The version-check command fetches vulnerability-information from https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json, +and displays information about any security vulnerabilities that affect the currently executing version. `, } licenseCommand = cli.Command{ diff --git a/cmd/geth/version_check.go b/cmd/geth/version_check.go new file mode 100644 index 000000000000..8af13670dd42 --- /dev/null +++ b/cmd/geth/version_check.go @@ -0,0 +1,95 @@ +// Copyright 2020 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see . + +package main + +import ( + "encoding/json" + "fmt" + "github.com/ethereum/go-ethereum/log" + "github.com/ethereum/go-ethereum/params" + "gopkg.in/urfave/cli.v1" + "io/ioutil" + "net/http" + "regexp" + "runtime" +) + +const versionFeed = "https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json" + +type vulnJson struct { + Name string + Uid string + Summary string + Description string + Links []string + Introduced string + Fixed string + Published string + Severity string + Check string +} + +func versionCheck(ctx *cli.Context) error { + args := ctx.Args() + version := fmt.Sprintf("Geth/v%v/%v-%v/%v", + params.VersionWithCommit(gitCommit, gitDate), + runtime.GOOS, + runtime.GOARCH, + runtime.Version()) + if len(args) > 0 { + // Explicit version string given + version = args[0] + } + log.Info("Checking vulnerabilities", "version", version) + return checkCurrent(version) +} + +func checkCurrent(current string) error { + res, err := http.Get(versionFeed) + if err != nil { + return err + } + defer res.Body.Close() + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return err + } + var vulns []vulnJson + if err = json.Unmarshal(body, &vulns); err != nil { + return err + } + for _, vuln := range vulns { + r, err := regexp.Compile(vuln.Check) + if err != nil { + return err + } + if r.MatchString(current) { + fmt.Printf("## Vulnerable to %v (%v)\n\n", vuln.Uid, vuln.Name) + fmt.Printf("Severity: %v\n", vuln.Severity) + fmt.Printf("Summary : %v\n", vuln.Summary) + fmt.Printf("Fixed in: %v\n", vuln.Fixed) + if len(vuln.Links) > 0 { + fmt.Printf("References:\n") + for _, ref := range vuln.Links { + fmt.Printf("\t- %v\n", ref) + } + } + fmt.Println() + } + } + return nil +} From bc68c30a3e626074175fdd689b24e12957081814 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 17 Nov 2020 14:43:10 +0100 Subject: [PATCH 02/13] cmd/geth: use minisign to verify vulnerability feed --- cmd/geth/misccmd.go | 18 ++++- cmd/geth/testdata/vcheck/data.json | 61 +++++++++++++++ cmd/geth/testdata/vcheck/minisign.key | 2 + cmd/geth/testdata/vcheck/minisign.pub | 2 + .../sigs/vulnerabilities.json.minisig.1 | 4 + .../sigs/vulnerabilities.json.minisig.2 | 4 + .../sigs/vulnerabilities.json.minisig.3 | 4 + cmd/geth/version_check.go | 77 +++++++++++++------ go.sum | 3 + 9 files changed, 149 insertions(+), 26 deletions(-) create mode 100644 cmd/geth/testdata/vcheck/data.json create mode 100644 cmd/geth/testdata/vcheck/minisign.key create mode 100644 cmd/geth/testdata/vcheck/minisign.pub create mode 100644 cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.1 create mode 100644 cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.2 create mode 100644 cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.3 diff --git a/cmd/geth/misccmd.go b/cmd/geth/misccmd.go index e870e4f01e75..967df2ada09e 100644 --- a/cmd/geth/misccmd.go +++ b/cmd/geth/misccmd.go @@ -31,6 +31,18 @@ import ( ) var ( + VersionCheckUrlFlag = cli.StringFlag{ + Name: "check.url", + Usage: "URL to use when checking vulnerabilities", + Value: "https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json", + } + VersionCheckVersionFlag = cli.StringFlag{ + Name: "check.version", + Usage: "Version to check", + Value: fmt.Sprintf("Geth/v%v/%v-%v/%v", + params.VersionWithCommit(gitCommit, gitDate), + runtime.GOOS, runtime.GOARCH, runtime.Version()), + } makecacheCommand = cli.Command{ Action: utils.MigrateFlags(makecache), Name: "makecache", @@ -68,7 +80,11 @@ The output of this command is supposed to be machine-readable. `, } versionCheckCommand = cli.Command{ - Action: utils.MigrateFlags(versionCheck), + Action: utils.MigrateFlags(versionCheck), + Flags: []cli.Flag{ + VersionCheckUrlFlag, + VersionCheckVersionFlag, + }, Name: "version-check", Usage: "Checks (online) whether the current version suffers from any known security vulnerabilities", ArgsUsage: "", diff --git a/cmd/geth/testdata/vcheck/data.json b/cmd/geth/testdata/vcheck/data.json new file mode 100644 index 000000000000..e7ee2bf7e44c --- /dev/null +++ b/cmd/geth/testdata/vcheck/data.json @@ -0,0 +1,61 @@ +[ + { + "name": "CorruptedDAG", + "uid": "GETH-2020-01", + "summary": "Mining nodes will generate erroneous PoW on epochs > `385`.", + "description": "A mining flaw could cause miners to erroneously calculate PoW, due to an index overflow, if DAG size is exceeding the maximum 32 bit unsigned value.\n\nThis occurred on the ETC chain on 2020-11-06. This is likely to trigger for ETH mainnet around block `11550000`/epoch `385`, slated to occur early January 2021.\n\nThis issue is relevant only for miners, non-mining nodes are unaffected, since non-mining nodes use a smaller verification cache instead of a full DAG.", + "links": [ + "https://github.com/ethereum/go-ethereum/pull/21793", + "https://blog.ethereum.org/2020/11/12/geth_security_release/", + "https://github.com/ethereum/go-ethereum/commit/567d41d9363706b4b13ce0903804e8acf214af49" + ], + "introduced": "v1.6.0", + "fixed": "v1.9.24", + "published": "2020-11-12", + "severity": "Medium", + "check": "Geth\\/v1\\.(6|7|8)\\..*|Geth\\/v1\\.9\\.2(1|2|3)-.*" + }, + { + "name": "GoCrash", + "uid": "GETH-2020-02", + "summary": "A denial-of-service issue can be used to crash Geth nodes during block processing, due to an underlying bug in Go (CVE-2020-28362) versions < `1.15.5`, or `<1.14.12`", + "description": "The DoS issue can be used to crash all Geth nodes during block processing, the effects of which would be that a major part of the Ethereum network went offline.\n\nOutside of Go-Ethereum, the issue is most likely relevant for all forks of Geth (such as TurboGeth or ETC’s core-geth) which is built with versions of Go which contains the vulnerability.", + "links": [ + "https://blog.ethereum.org/2020/11/12/geth_security_release/", + "https://groups.google.com/g/golang-announce/c/NpBGTTmKzpM", + "https://github.com/golang/go/issues/42552" + ], + "fixed": "v1.9.24", + "published": "2020-11-12", + "severity": "Critical", + "check": "Geth.*\\/go1\\.(11(.*)|12(.*)|13(.*)|14|14\\.(\\d|10|11|)|15|15\\.[0-4])$" + }, + { + "name": "ShallowCopy", + "uid": "GETH-2020-03", + "summary": "A consensus flaw in Geth, related to `datacopy` precompile", + "description": "Geth erroneously performed a 'shallow' copy when the precompiled `datacopy` (at `0x00...04`) was invoked. An attacker could deploy a contract that uses the shallow copy to corrupt the contents of the `RETURNDATA`, thus causing a consensus failure.", + "links": [ + "https://blog.ethereum.org/2020/11/12/geth_security_release/" + ], + "introduced": "v1.9.7", + "fixed": "v1.9.17", + "published": "2020-11-12", + "severity": "Critical", + "check": "Geth\\/v1\\.9\\.(7|8|9|10|11|12|13|14|15|16).*$" + }, + { + "name": "GethCrash", + "uid": "GETH-2020-04", + "summary": "A denial-of-service issue can be used to crash Geth nodes during block processing", + "description": "Full details to be disclosed at a later date", + "links": [ + "https://blog.ethereum.org/2020/11/12/geth_security_release/" + ], + "introduced": "v1.9.16", + "fixed": "v1.9.18", + "published": "2020-11-12", + "severity": "Critical", + "check": "Geth\\/v1\\.9.(16|17).*$" + } +] diff --git a/cmd/geth/testdata/vcheck/minisign.key b/cmd/geth/testdata/vcheck/minisign.key new file mode 100644 index 000000000000..5c50715b2096 --- /dev/null +++ b/cmd/geth/testdata/vcheck/minisign.key @@ -0,0 +1,2 @@ +untrusted comment: minisign encrypted secret key +RWRTY0Iyz8kmPMKrqk6DCtlO9a33akKiaOQG1aLolqDxs52qvPoAAAACAAAAAAAAAEAAAAAArEiggdvyn6+WzTprirLtgiYQoU+ihz/HyGgjhuF+Pz2ddMduyCO+xjCHeq+vgVVW039fbsI8hW6LRGJZLBKV5/jdxCXAVVQE7qTQ6xpEdO0z8Z731/pV1hlspQXG2PNd16NMtwd9dWw= diff --git a/cmd/geth/testdata/vcheck/minisign.pub b/cmd/geth/testdata/vcheck/minisign.pub new file mode 100644 index 000000000000..183dce5f6b5d --- /dev/null +++ b/cmd/geth/testdata/vcheck/minisign.pub @@ -0,0 +1,2 @@ +untrusted comment: minisign public key 284E00B52C269624 +RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp diff --git a/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.1 b/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.1 new file mode 100644 index 000000000000..f9066d4fe0b1 --- /dev/null +++ b/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.1 @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= +trusted comment: timestamp:1605618622 file:vulnerabilities.json +osAPs4QPdDkmiWQxqeMIzYv/b+ZGxJ+19Sbrk1Cpq4t2gHBT+lqFtwL3OCzKWWyjGRTmHfsVGBYpzEdPRQ0/BQ== diff --git a/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.2 b/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.2 new file mode 100644 index 000000000000..a89a83d21a57 --- /dev/null +++ b/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.2 @@ -0,0 +1,4 @@ +untrusted comment: Here's a comment +RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= +trusted comment: Here's a trusted comment +3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ== diff --git a/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.3 b/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.3 new file mode 100644 index 000000000000..6fd33b19a3cd --- /dev/null +++ b/cmd/geth/testdata/vcheck/sigs/vulnerabilities.json.minisig.3 @@ -0,0 +1,4 @@ +untrusted comment: One more (untrusted) comment +RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= +trusted comment: Here's a trusted comment +3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ== diff --git a/cmd/geth/version_check.go b/cmd/geth/version_check.go index 8af13670dd42..a4de9bb81500 100644 --- a/cmd/geth/version_check.go +++ b/cmd/geth/version_check.go @@ -19,16 +19,17 @@ package main import ( "encoding/json" "fmt" - "github.com/ethereum/go-ethereum/log" - "github.com/ethereum/go-ethereum/params" - "gopkg.in/urfave/cli.v1" "io/ioutil" "net/http" "regexp" - "runtime" + + "github.com/ethereum/go-ethereum/log" + "github.com/jedisct1/go-minisign" + "gopkg.in/urfave/cli.v1" ) -const versionFeed = "https://geth.ethereum.org/docs/vulnerabilities/vulnerabilities.json" +// TODO(@holiman) replace this later on with an actual key (or keys) +const GethPubkey = "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp" type vulnJson struct { Name string @@ -44,32 +45,29 @@ type vulnJson struct { } func versionCheck(ctx *cli.Context) error { - args := ctx.Args() - version := fmt.Sprintf("Geth/v%v/%v-%v/%v", - params.VersionWithCommit(gitCommit, gitDate), - runtime.GOOS, - runtime.GOARCH, - runtime.Version()) - if len(args) > 0 { - // Explicit version string given - version = args[0] - } - log.Info("Checking vulnerabilities", "version", version) - return checkCurrent(version) + url := ctx.String(VersionCheckUrlFlag.Name) + version := ctx.String(VersionCheckVersionFlag.Name) + log.Info("Checking vulnerabilities", "version", version, "url", url) + return checkCurrent(url, version) } -func checkCurrent(current string) error { - res, err := http.Get(versionFeed) - if err != nil { - return err +func checkCurrent(url, current string) error { + var ( + data []byte + sig []byte + err error + ) + if data, err = fetch(url); err != nil { + return fmt.Errorf("could not retrieve data: %w", err) } - defer res.Body.Close() - body, err := ioutil.ReadAll(res.Body) - if err != nil { + if sig, err = fetch(fmt.Sprintf("%v.minisig", url)); err != nil { + return fmt.Errorf("could not retrieve signature: %w", err) + } + if err = verifySignature(GethPubkey, data, sig); err != nil { return err } var vulns []vulnJson - if err = json.Unmarshal(body, &vulns); err != nil { + if err = json.Unmarshal(data, &vulns); err != nil { return err } for _, vuln := range vulns { @@ -93,3 +91,32 @@ func checkCurrent(current string) error { } return nil } + +// fetch makes an HTTP request to the given url and returns the response body +func fetch(url string) ([]byte, error) { + res, err := http.Get(url) + if err != nil { + return nil, err + } + defer res.Body.Close() + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return nil, err + } + return body, nil +} + +// verifySignature checks that the sigData is a valid signature of the given +// data, for pubkey GethPubkey +func verifySignature(pubkey string, data, sigdata []byte) error { + pub, err := minisign.NewPublicKey(pubkey) + if err != nil { + return err + } + sig, err := minisign.DecodeSignature(string(sigdata)) + if err != nil { + return err + } + _, err = pub.Verify(data, sig) + return err +} diff --git a/go.sum b/go.sum index 10bec96411e9..dedae7bc7a20 100755 --- a/go.sum +++ b/go.sum @@ -123,6 +123,8 @@ github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883 h1:FSeK4fZCo github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 h1:6OvNmYgJyexcZ3pYbTI9jWx5tHo1Dee/tWbLMfPe2TA= github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e h1:UvSe12bq+Uj2hWd8aOlwPmoZ+CITRFrdit+sDGfAg8U= +github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e/go.mod h1:G1CVv03EnqU1wYL2dFwXxW2An0az9JTl/ZsqXQeBlkU= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af h1:pmfjZENx5imkbgOkpRUYLnmbU7UEFbjtDA2hxJ1ichM= github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21 h1:F/iKcka0K2LgnKy/fgSBf235AETtm1n1TvBzqu40LE0= @@ -214,6 +216,7 @@ github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208 h1:1cngl9mPEoITZG8s8 github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190909091759-094676da4a83/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= From 765eb3f8d584e9f4a48525ee07eba11455d56f5c Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 17 Nov 2020 14:48:03 +0100 Subject: [PATCH 03/13] cmd/geth: add the test too --- cmd/geth/version_check_test.go | 46 ++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 cmd/geth/version_check_test.go diff --git a/cmd/geth/version_check_test.go b/cmd/geth/version_check_test.go new file mode 100644 index 000000000000..8b00f93a174e --- /dev/null +++ b/cmd/geth/version_check_test.go @@ -0,0 +1,46 @@ +// Copyright 2020 The go-ethereum Authors +// This file is part of go-ethereum. +// +// go-ethereum is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// go-ethereum is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with go-ethereum. If not, see . + +package main + +import ( + "io/ioutil" + "path/filepath" + "testing" +) + +func TestVerification(t *testing.T) { + // For this test, the pubkey is in testdata/minisign.pub + // (the privkey is there aswell, if we want to expand this test. Password 'test' ) + pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp" + // Data to verify + data, err := ioutil.ReadFile("./testdata/vcheck/data.json") + // Signatures, with and without comments, both trusted and untrusted + files, err := ioutil.ReadDir("./testdata/vcheck/sigs/") + if err != nil { + t.Fatal(err) + } + for _, f := range files { + sig, err := ioutil.ReadFile(filepath.Join(".", "testdata", "vcheck", "sigs", f.Name())) + if err != nil { + t.Fatal(err) + } + err = verifySignature(pub, data, sig) + if err != nil { + t.Fatal(err) + } + } +} From 079e23e6a710abf63946d82f33b9b3ed23135bb0 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Wed, 18 Nov 2020 09:48:26 +0100 Subject: [PATCH 04/13] cmd/geth: more minisig/signify testing --- .../vulnerabilities.json.minisig.1 | 4 +++ .../vulnerabilities.json.minisig.2 | 4 +++ .../vulnerabilities.json.minisig.3 | 4 +++ .../vcheck/{minisign.key => minisign.sec} | 0 .../vcheck/signify-sigs/data.json.sig | 2 ++ cmd/geth/testdata/vcheck/signifykey.pub | 2 ++ cmd/geth/testdata/vcheck/signifykey.sec | 2 ++ cmd/geth/version_check_test.go | 27 ++++++++++++++----- go.mod | 1 + 9 files changed, 40 insertions(+), 6 deletions(-) create mode 100644 cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.1 create mode 100644 cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.2 create mode 100644 cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.3 rename cmd/geth/testdata/vcheck/{minisign.key => minisign.sec} (100%) create mode 100644 cmd/geth/testdata/vcheck/signify-sigs/data.json.sig create mode 100644 cmd/geth/testdata/vcheck/signifykey.pub create mode 100644 cmd/geth/testdata/vcheck/signifykey.sec diff --git a/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.1 b/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.1 new file mode 100644 index 000000000000..f9066d4fe0b1 --- /dev/null +++ b/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.1 @@ -0,0 +1,4 @@ +untrusted comment: signature from minisign secret key +RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= +trusted comment: timestamp:1605618622 file:vulnerabilities.json +osAPs4QPdDkmiWQxqeMIzYv/b+ZGxJ+19Sbrk1Cpq4t2gHBT+lqFtwL3OCzKWWyjGRTmHfsVGBYpzEdPRQ0/BQ== diff --git a/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.2 b/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.2 new file mode 100644 index 000000000000..a89a83d21a57 --- /dev/null +++ b/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.2 @@ -0,0 +1,4 @@ +untrusted comment: Here's a comment +RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= +trusted comment: Here's a trusted comment +3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ== diff --git a/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.3 b/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.3 new file mode 100644 index 000000000000..6fd33b19a3cd --- /dev/null +++ b/cmd/geth/testdata/vcheck/minisig-sigs/vulnerabilities.json.minisig.3 @@ -0,0 +1,4 @@ +untrusted comment: One more (untrusted) comment +RWQkliYstQBOKFQFQTjmCd6TPw07VZyWFSB3v4+1BM1kv8eHLE5FDy2OkPEqtdaL53xftlrHoJQie0uCcovdlSV8kpyxiLrxEQ0= +trusted comment: Here's a trusted comment +3CnkIuz9MEDa7uNyGZAbKZhuirwfiqm7E1uQHrd2SiO4Y8+Akw9vs052AyKw0s5nhbYHCZE2IMQdHNjKwxEGAQ== diff --git a/cmd/geth/testdata/vcheck/minisign.key b/cmd/geth/testdata/vcheck/minisign.sec similarity index 100% rename from cmd/geth/testdata/vcheck/minisign.key rename to cmd/geth/testdata/vcheck/minisign.sec diff --git a/cmd/geth/testdata/vcheck/signify-sigs/data.json.sig b/cmd/geth/testdata/vcheck/signify-sigs/data.json.sig new file mode 100644 index 000000000000..3d5fcacf9ae2 --- /dev/null +++ b/cmd/geth/testdata/vcheck/signify-sigs/data.json.sig @@ -0,0 +1,2 @@ +untrusted comment: verify with ./signifykey.pub +RWSKLNhZb0KdAbhRUhW2LQZXdnwttu2SYhM9EuC4mMgOJB85h7/YIPupf8/ldTs4N8e9Y/fhgdY40q5LQpt5IFC62fq0v8U1/w8= diff --git a/cmd/geth/testdata/vcheck/signifykey.pub b/cmd/geth/testdata/vcheck/signifykey.pub new file mode 100644 index 000000000000..328f973ab4dc --- /dev/null +++ b/cmd/geth/testdata/vcheck/signifykey.pub @@ -0,0 +1,2 @@ +untrusted comment: signify public key +RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/ diff --git a/cmd/geth/testdata/vcheck/signifykey.sec b/cmd/geth/testdata/vcheck/signifykey.sec new file mode 100644 index 000000000000..3279a2e58b55 --- /dev/null +++ b/cmd/geth/testdata/vcheck/signifykey.sec @@ -0,0 +1,2 @@ +untrusted comment: signify secret key +RWRCSwAAACpLQDLawSQCtI7eAVIvaiHzjTsTyJsfV5aKLNhZb0KdAWeICXJGa93/bHAcsY6jUh9I8RdEcDWEoGxmaXZC+IdVBPxDpkix9fBRGEUdKWHi3dOfqME0YRzErWI5AVg3cRw= diff --git a/cmd/geth/version_check_test.go b/cmd/geth/version_check_test.go index 8b00f93a174e..b0590d37354d 100644 --- a/cmd/geth/version_check_test.go +++ b/cmd/geth/version_check_test.go @@ -23,22 +23,37 @@ import ( ) func TestVerification(t *testing.T) { - // For this test, the pubkey is in testdata/minisign.pub - // (the privkey is there aswell, if we want to expand this test. Password 'test' ) - pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp" + // Signatures generated with `minisign` + t.Run("minisig", func(t *testing.T) { + // For this test, the pubkey is in testdata/minisign.pub + // (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' ) + pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp" + testVerification(t, pub, "./testdata/vcheck/minisig-sigs/") + }) + // Signatures generated with `signify-openbsd` + t.Run("signify-openbsd", func(t *testing.T) { + t.Skip("This currently fails, minisign expects 4 lines of data, signify provides only 2") + // For this test, the pubkey is in testdata/signifykey.pub + // (the privkey is `signifykey.sec`, if we want to expand this test. Password 'test' ) + pub := "RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/" + testVerification(t, pub, "./testdata/vcheck/signify-sigs/") + }) +} + +func testVerification(t *testing.T, pubkey, sigdir string) { // Data to verify data, err := ioutil.ReadFile("./testdata/vcheck/data.json") // Signatures, with and without comments, both trusted and untrusted - files, err := ioutil.ReadDir("./testdata/vcheck/sigs/") + files, err := ioutil.ReadDir(sigdir) if err != nil { t.Fatal(err) } for _, f := range files { - sig, err := ioutil.ReadFile(filepath.Join(".", "testdata", "vcheck", "sigs", f.Name())) + sig, err := ioutil.ReadFile(filepath.Join(sigdir, f.Name())) if err != nil { t.Fatal(err) } - err = verifySignature(pub, data, sig) + err = verifySignature(pubkey, data, sig) if err != nil { t.Fatal(err) } diff --git a/go.mod b/go.mod index ae1cf64aaf9c..9a35f6447ff4 100755 --- a/go.mod +++ b/go.mod @@ -36,6 +36,7 @@ require ( github.com/huin/goupnp v1.0.0 github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883 github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458 + github.com/jedisct1/go-minisign v0.0.0-20190909160543-45766022959e github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21 github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356 github.com/kr/pretty v0.1.0 // indirect From ae00c56da51a504adf4ae1ca8e003d21bc9e99c8 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 23 Nov 2020 10:34:06 +0100 Subject: [PATCH 05/13] cmd/geth: support multiple pubfiles for signing --- cmd/geth/version_check.go | 29 +++++++++++++++++++---------- cmd/geth/version_check_test.go | 2 +- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/cmd/geth/version_check.go b/cmd/geth/version_check.go index a4de9bb81500..f83ce730b6d5 100644 --- a/cmd/geth/version_check.go +++ b/cmd/geth/version_check.go @@ -18,6 +18,7 @@ package main import ( "encoding/json" + "errors" "fmt" "io/ioutil" "net/http" @@ -28,8 +29,11 @@ import ( "gopkg.in/urfave/cli.v1" ) -// TODO(@holiman) replace this later on with an actual key (or keys) -const GethPubkey = "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp" +// TODO(@holiman) replace this later on with actual keys +var gethPubKeys []string = []string{ + "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp", // Test-key, + "RWTq+byAzWOfZZ56S/WBPsDtl6TQu5Y3ud2HYuqi5yZqHpQ0ES8Lf5oU", // Test-key 2, +} type vulnJson struct { Name string @@ -63,7 +67,7 @@ func checkCurrent(url, current string) error { if sig, err = fetch(fmt.Sprintf("%v.minisig", url)); err != nil { return fmt.Errorf("could not retrieve signature: %w", err) } - if err = verifySignature(GethPubkey, data, sig); err != nil { + if err = verifySignature(gethPubKeys, data, sig); err != nil { return err } var vulns []vulnJson @@ -108,15 +112,20 @@ func fetch(url string) ([]byte, error) { // verifySignature checks that the sigData is a valid signature of the given // data, for pubkey GethPubkey -func verifySignature(pubkey string, data, sigdata []byte) error { - pub, err := minisign.NewPublicKey(pubkey) - if err != nil { - return err - } +func verifySignature(pubkeys []string, data, sigdata []byte) error { sig, err := minisign.DecodeSignature(string(sigdata)) if err != nil { return err } - _, err = pub.Verify(data, sig) - return err + for _, pubkey := range pubkeys { + pub, err := minisign.NewPublicKey(pubkey) + if err != nil { + // our pubkeys should be parseable + return err + } + if ok, err := pub.Verify(data, sig); ok && err == nil { + return nil + } + } + return errors.New("signature could not be verified") } diff --git a/cmd/geth/version_check_test.go b/cmd/geth/version_check_test.go index b0590d37354d..63d3c0c2a7da 100644 --- a/cmd/geth/version_check_test.go +++ b/cmd/geth/version_check_test.go @@ -53,7 +53,7 @@ func testVerification(t *testing.T, pubkey, sigdir string) { if err != nil { t.Fatal(err) } - err = verifySignature(pubkey, data, sig) + err = verifySignature([]string{pubkey}, data, sig) if err != nil { t.Fatal(err) } From 7a25129a87aa82b8f22980325179fc8e04df597f Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 23 Nov 2020 13:18:02 +0100 Subject: [PATCH 06/13] cmd/geth: add @holiman minisig pubkey --- cmd/geth/version_check.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmd/geth/version_check.go b/cmd/geth/version_check.go index f83ce730b6d5..a2e48683e1cd 100644 --- a/cmd/geth/version_check.go +++ b/cmd/geth/version_check.go @@ -29,10 +29,9 @@ import ( "gopkg.in/urfave/cli.v1" ) -// TODO(@holiman) replace this later on with actual keys +// TODO(@holiman) add more keys var gethPubKeys []string = []string{ - "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp", // Test-key, - "RWTq+byAzWOfZZ56S/WBPsDtl6TQu5Y3ud2HYuqi5yZqHpQ0ES8Lf5oU", // Test-key 2, + "RWQk7Lo5TQgd+wxBNZM+Zoy+7UhhMHaWKzqoes9tvSbFLJYZhNTbrIjx", //@holiman, minisign public key FB1D084D39BAEC24 } type vulnJson struct { From f546792543322f96995d77ed85c76e1a3cf267a9 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 23 Nov 2020 13:52:42 +0100 Subject: [PATCH 07/13] cmd/geth: polishes on vulnerability check --- cmd/geth/version_check.go | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/cmd/geth/version_check.go b/cmd/geth/version_check.go index a2e48683e1cd..fe8aaf6b9237 100644 --- a/cmd/geth/version_check.go +++ b/cmd/geth/version_check.go @@ -73,12 +73,14 @@ func checkCurrent(url, current string) error { if err = json.Unmarshal(data, &vulns); err != nil { return err } + allOk := true for _, vuln := range vulns { r, err := regexp.Compile(vuln.Check) if err != nil { return err } if r.MatchString(current) { + allOk = false fmt.Printf("## Vulnerable to %v (%v)\n\n", vuln.Uid, vuln.Name) fmt.Printf("Severity: %v\n", vuln.Severity) fmt.Printf("Summary : %v\n", vuln.Summary) @@ -92,6 +94,9 @@ func checkCurrent(url, current string) error { fmt.Println() } } + if allOk { + fmt.Println("No vulnerabilities found") + } return nil } @@ -116,15 +121,27 @@ func verifySignature(pubkeys []string, data, sigdata []byte) error { if err != nil { return err } + // find the used key + var key *minisign.PublicKey for _, pubkey := range pubkeys { pub, err := minisign.NewPublicKey(pubkey) if err != nil { // our pubkeys should be parseable return err } - if ok, err := pub.Verify(data, sig); ok && err == nil { - return nil + if pub.KeyId != sig.KeyId { + continue } + key = &pub + break + } + if key == nil { + log.Info("Signing key not trusted", "key", sig.KeyId, "error", err) + return errors.New("signature could not be verified") } - return errors.New("signature could not be verified") + if ok, err := key.Verify(data, sig); !ok || err != nil { + log.Info("Verification failed error", "key", fmt.Sprintf("%x", key.KeyId), "error", err) + return errors.New("signature could not be verified") + } + return nil } From 6bebea974fbc41d5bb9e495e831ef0afe3c3884f Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Mon, 23 Nov 2020 14:32:14 +0100 Subject: [PATCH 08/13] cmd/geth: fix ineffassign linter nit --- cmd/geth/version_check_test.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/geth/version_check_test.go b/cmd/geth/version_check_test.go index 63d3c0c2a7da..e2432418b92c 100644 --- a/cmd/geth/version_check_test.go +++ b/cmd/geth/version_check_test.go @@ -43,6 +43,9 @@ func TestVerification(t *testing.T) { func testVerification(t *testing.T, pubkey, sigdir string) { // Data to verify data, err := ioutil.ReadFile("./testdata/vcheck/data.json") + if err != nil { + t.Fatal(err) + } // Signatures, with and without comments, both trusted and untrusted files, err := ioutil.ReadDir(sigdir) if err != nil { From e2f70f01c01d278c77117a434fbae37b9d35aee2 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 24 Nov 2020 13:42:13 +0100 Subject: [PATCH 09/13] cmd/geth: add CVE to version check struct --- cmd/geth/version_check.go | 4 ++++ cmd/geth/version_check_test.go | 15 +++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/cmd/geth/version_check.go b/cmd/geth/version_check.go index fe8aaf6b9237..eae0d6598b55 100644 --- a/cmd/geth/version_check.go +++ b/cmd/geth/version_check.go @@ -45,6 +45,7 @@ type vulnJson struct { Published string Severity string Check string + CVE string } func versionCheck(ctx *cli.Context) error { @@ -85,6 +86,9 @@ func checkCurrent(url, current string) error { fmt.Printf("Severity: %v\n", vuln.Severity) fmt.Printf("Summary : %v\n", vuln.Summary) fmt.Printf("Fixed in: %v\n", vuln.Fixed) + if len(vuln.CVE) > 0 { + fmt.Printf("CVE: %v\n", vuln.CVE) + } if len(vuln.Links) > 0 { fmt.Printf("References:\n") for _, ref := range vuln.Links { diff --git a/cmd/geth/version_check_test.go b/cmd/geth/version_check_test.go index e2432418b92c..4afe8ddc83a9 100644 --- a/cmd/geth/version_check_test.go +++ b/cmd/geth/version_check_test.go @@ -17,6 +17,7 @@ package main import ( + "encoding/json" "io/ioutil" "path/filepath" "testing" @@ -62,3 +63,17 @@ func testVerification(t *testing.T, pubkey, sigdir string) { } } } + +func TestJson(t *testing.T) { + data, _ := ioutil.ReadFile("./testdata/vcheck/data2.json") + var vulns []vulnJson + if err := json.Unmarshal(data, &vulns); err != nil { + t.Fatal(err) + } + if len(vulns) == 0 { + t.Fatal("expected data, got none") + } + if have, want := vulns[0].CVE, "correct"; have != want { + t.Errorf("have %v, want %v", have, want) + } +} From a3220d75530bd538fe87c0a4e9355a524700e244 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Wed, 25 Nov 2020 09:50:26 +0100 Subject: [PATCH 10/13] cmd/geth/testdata: add missing testfile --- cmd/geth/testdata/vcheck/data2.json | 62 +++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 cmd/geth/testdata/vcheck/data2.json diff --git a/cmd/geth/testdata/vcheck/data2.json b/cmd/geth/testdata/vcheck/data2.json new file mode 100644 index 000000000000..75a31677a189 --- /dev/null +++ b/cmd/geth/testdata/vcheck/data2.json @@ -0,0 +1,62 @@ +[ + { + "name": "CorruptedDAG", + "uid": "GETH-2020-01", + "summary": "Mining nodes will generate erroneous PoW on epochs > `385`.", + "description": "A mining flaw could cause miners to erroneously calculate PoW, due to an index overflow, if DAG size is exceeding the maximum 32 bit unsigned value.\n\nThis occurred on the ETC chain on 2020-11-06. This is likely to trigger for ETH mainnet around block `11550000`/epoch `385`, slated to occur early January 2021.\n\nThis issue is relevant only for miners, non-mining nodes are unaffected, since non-mining nodes use a smaller verification cache instead of a full DAG.", + "links": [ + "https://github.com/ethereum/go-ethereum/pull/21793", + "https://blog.ethereum.org/2020/11/12/geth_security_release/", + "https://github.com/ethereum/go-ethereum/commit/567d41d9363706b4b13ce0903804e8acf214af49" + ], + "introduced": "v1.6.0", + "fixed": "v1.9.24", + "published": "2020-11-12", + "severity": "Medium", + "check": "Geth\\/v1\\.(6|7|8)\\..*|Geth\\/v1\\.9\\.2(1|2|3)-.*", + "CVE": "correct" + }, + { + "name": "GoCrash", + "uid": "GETH-2020-02", + "summary": "A denial-of-service issue can be used to crash Geth nodes during block processing, due to an underlying bug in Go (CVE-2020-28362) versions < `1.15.5`, or `<1.14.12`", + "description": "The DoS issue can be used to crash all Geth nodes during block processing, the effects of which would be that a major part of the Ethereum network went offline.\n\nOutside of Go-Ethereum, the issue is most likely relevant for all forks of Geth (such as TurboGeth or ETC’s core-geth) which is built with versions of Go which contains the vulnerability.", + "links": [ + "https://blog.ethereum.org/2020/11/12/geth_security_release/", + "https://groups.google.com/g/golang-announce/c/NpBGTTmKzpM", + "https://github.com/golang/go/issues/42552" + ], + "fixed": "v1.9.24", + "published": "2020-11-12", + "severity": "Critical", + "check": "Geth.*\\/go1\\.(11(.*)|12(.*)|13(.*)|14|14\\.(\\d|10|11|)|15|15\\.[0-4])$" + }, + { + "name": "ShallowCopy", + "uid": "GETH-2020-03", + "summary": "A consensus flaw in Geth, related to `datacopy` precompile", + "description": "Geth erroneously performed a 'shallow' copy when the precompiled `datacopy` (at `0x00...04`) was invoked. An attacker could deploy a contract that uses the shallow copy to corrupt the contents of the `RETURNDATA`, thus causing a consensus failure.", + "links": [ + "https://blog.ethereum.org/2020/11/12/geth_security_release/" + ], + "introduced": "v1.9.7", + "fixed": "v1.9.17", + "published": "2020-11-12", + "severity": "Critical", + "check": "Geth\\/v1\\.9\\.(7|8|9|10|11|12|13|14|15|16).*$" + }, + { + "name": "GethCrash", + "uid": "GETH-2020-04", + "summary": "A denial-of-service issue can be used to crash Geth nodes during block processing", + "description": "Full details to be disclosed at a later date", + "links": [ + "https://blog.ethereum.org/2020/11/12/geth_security_release/" + ], + "introduced": "v1.9.16", + "fixed": "v1.9.18", + "published": "2020-11-12", + "severity": "Critical", + "check": "Geth\\/v1\\.9.(16|17).*$" + } +] From f0ffd8332c4de8352bb4d4df6a0f0afe372fc484 Mon Sep 17 00:00:00 2001 From: Martin Holst Swende Date: Tue, 1 Dec 2020 11:26:15 +0100 Subject: [PATCH 11/13] cmd/geth: add more keys to versionchecker --- cmd/geth/version_check.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/cmd/geth/version_check.go b/cmd/geth/version_check.go index eae0d6598b55..0cdac86c5abb 100644 --- a/cmd/geth/version_check.go +++ b/cmd/geth/version_check.go @@ -29,9 +29,13 @@ import ( "gopkg.in/urfave/cli.v1" ) -// TODO(@holiman) add more keys var gethPubKeys []string = []string{ - "RWQk7Lo5TQgd+wxBNZM+Zoy+7UhhMHaWKzqoes9tvSbFLJYZhNTbrIjx", //@holiman, minisign public key FB1D084D39BAEC24 + //@holiman, minisign public key FB1D084D39BAEC24 + "RWQk7Lo5TQgd+wxBNZM+Zoy+7UhhMHaWKzqoes9tvSbFLJYZhNTbrIjx", + //minisign public key 138B1CA303E51687 + "RWSHFuUDoxyLEzjszuWZI1xStS66QTyXFFZG18uDfO26CuCsbckX1e9J", + //minisign public key FD9813B2D2098484 + "RWSEhAnSshOY/b+GmaiDkObbCWefsAoavjoLcPjBo1xn71yuOH5I+Lts", } type vulnJson struct { From 1d59c52255d10d9b7ab9a62c50999edde65d22f4 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 4 Dec 2020 12:57:14 +0100 Subject: [PATCH 12/13] cmd/geth: support file:// URLs in version check --- cmd/geth/version_check.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cmd/geth/version_check.go b/cmd/geth/version_check.go index 0cdac86c5abb..a4d235c3b562 100644 --- a/cmd/geth/version_check.go +++ b/cmd/geth/version_check.go @@ -23,6 +23,7 @@ import ( "io/ioutil" "net/http" "regexp" + "strings" "github.com/ethereum/go-ethereum/log" "github.com/jedisct1/go-minisign" @@ -110,6 +111,9 @@ func checkCurrent(url, current string) error { // fetch makes an HTTP request to the given url and returns the response body func fetch(url string) ([]byte, error) { + if filep := strings.TrimPrefix(url, "file://"); filep != url { + return ioutil.ReadFile(filep) + } res, err := http.Get(url) if err != nil { return nil, err From 51143237ea9e712c226bd9cd56342ec3dfc1b498 Mon Sep 17 00:00:00 2001 From: Felix Lange Date: Fri, 4 Dec 2020 12:57:37 +0100 Subject: [PATCH 13/13] cmd/geth: improve key ID printing when signature check fails --- cmd/geth/version_check.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cmd/geth/version_check.go b/cmd/geth/version_check.go index a4d235c3b562..2101a69e9886 100644 --- a/cmd/geth/version_check.go +++ b/cmd/geth/version_check.go @@ -148,12 +148,22 @@ func verifySignature(pubkeys []string, data, sigdata []byte) error { break } if key == nil { - log.Info("Signing key not trusted", "key", sig.KeyId, "error", err) + log.Info("Signing key not trusted", "keyid", keyID(sig.KeyId), "error", err) return errors.New("signature could not be verified") } if ok, err := key.Verify(data, sig); !ok || err != nil { - log.Info("Verification failed error", "key", fmt.Sprintf("%x", key.KeyId), "error", err) + log.Info("Verification failed error", "keyid", keyID(key.KeyId), "error", err) return errors.New("signature could not be verified") } return nil } + +// keyID turns a binary minisign key ID into a hex string. +// Note: key IDs are printed in reverse byte order. +func keyID(id [8]byte) string { + var rev [8]byte + for i := range id { + rev[len(rev)-1-i] = id[i] + } + return fmt.Sprintf("%X", rev) +}