diff --git a/.travis.yml b/.travis.yml
index fd31e3d506b4..d37458792a42 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -67,22 +67,22 @@ jobs:
script:
# Build for the primary platforms that Trusty can manage
- go run build/ci.go install -dlgo
- - go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
+ - go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go install -dlgo -arch 386
- - go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
+ - go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
# Switch over GCC to cross compilation (breaks 386, hence why do it here only)
- sudo -E apt-get -yq --no-install-suggests --no-install-recommends --force-yes install gcc-arm-linux-gnueabi libc6-dev-armel-cross gcc-arm-linux-gnueabihf libc6-dev-armhf-cross gcc-aarch64-linux-gnu libc6-dev-arm64-cross
- sudo ln -s /usr/include/asm-generic /usr/include/asm
- GOARM=5 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc
- - GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
+ - GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
- GOARM=6 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabi-gcc
- - GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
+ - GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
- GOARM=7 go run build/ci.go install -dlgo -arch arm -cc arm-linux-gnueabihf-gcc
- - GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
+ - GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go install -dlgo -arch arm64 -cc aarch64-linux-gnu-gcc
- - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
+ - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
# This builder does the Linux Azure MIPS xgo uploads
- stage: build
@@ -100,19 +100,19 @@ jobs:
script:
- go run build/ci.go xgo --alltools -- --targets=linux/mips --ldflags '-extldflags "-static"' -v
- for bin in build/bin/*-linux-mips; do mv -f "${bin}" "${bin/-linux-mips/}"; done
- - go run build/ci.go archive -arch mips -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
+ - go run build/ci.go archive -arch mips -type tar -signer LINUX_SIGNING_KEY -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go xgo --alltools -- --targets=linux/mipsle --ldflags '-extldflags "-static"' -v
- for bin in build/bin/*-linux-mipsle; do mv -f "${bin}" "${bin/-linux-mipsle/}"; done
- - go run build/ci.go archive -arch mipsle -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
+ - go run build/ci.go archive -arch mipsle -type tar -signer LINUX_SIGNING_KEY -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go xgo --alltools -- --targets=linux/mips64 --ldflags '-extldflags "-static"' -v
- for bin in build/bin/*-linux-mips64; do mv -f "${bin}" "${bin/-linux-mips64/}"; done
- - go run build/ci.go archive -arch mips64 -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
+ - go run build/ci.go archive -arch mips64 -type tar -signer LINUX_SIGNING_KEY signify LINUX_SIGNIFY_KEY -upload gethstore/builds
- go run build/ci.go xgo --alltools -- --targets=linux/mips64le --ldflags '-extldflags "-static"' -v
- for bin in build/bin/*-linux-mips64le; do mv -f "${bin}" "${bin/-linux-mips64le/}"; done
- - go run build/ci.go archive -arch mips64le -type tar -signer LINUX_SIGNING_KEY -upload gethstore/builds
+ - go run build/ci.go archive -arch mips64le -type tar -signer LINUX_SIGNING_KEY -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
# This builder does the Android Maven and Azure uploads
- stage: build
@@ -151,7 +151,7 @@ jobs:
- mkdir -p $GOPATH/src/github.com/ethereum
- ln -s `pwd` $GOPATH/src/github.com/ethereum/go-ethereum
- - go run build/ci.go aar -signer ANDROID_SIGNING_KEY -deploy https://oss.sonatype.org -upload gethstore/builds
+ - go run build/ci.go aar -signer ANDROID_SIGNING_KEY -signify ANDROID_SIGNIFY_KEY -deploy https://oss.sonatype.org -upload gethstore/builds
# This builder does the OSX Azure, iOS CocoaPods and iOS Azure uploads
- stage: build
@@ -167,7 +167,7 @@ jobs:
submodules: false # avoid cloning ethereum/tests
script:
- go run build/ci.go install -dlgo
- - go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -upload gethstore/builds
+ - go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify OSX_SIGNIFY_KEY -upload gethstore/builds
# Build the iOS framework and upload it to CocoaPods and Azure
- gem uninstall cocoapods -a -x
@@ -182,7 +182,7 @@ jobs:
# Workaround for https://github.com/golang/go/issues/23749
- export CGO_CFLAGS_ALLOW='-fmodules|-fblocks|-fobjc-arc'
- - go run build/ci.go xcode -signer IOS_SIGNING_KEY -deploy trunk -upload gethstore/builds
+ - go run build/ci.go xcode -signer IOS_SIGNING_KEY -signify IOS_SIGNIFY_KEY -deploy trunk -upload gethstore/builds
# These builders run the tests
- stage: build
diff --git a/build/ci.go b/build/ci.go
index 0cffb903aadb..951b21f9108a 100644
--- a/build/ci.go
+++ b/build/ci.go
@@ -26,7 +26,7 @@ Available commands are:
install [ -arch architecture ] [ -cc compiler ] [ packages... ] -- builds packages and executables
test [ -coverage ] [ packages... ] -- runs the tests
lint -- runs certain pre-selected linters
- archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -upload dest ] -- archives build artifacts
+ archive [ -arch architecture ] [ -type zip|tar ] [ -signer key-envvar ] [ -signify key-envvar ] [ -upload dest ] -- archives build artifacts
importkeys -- imports signing keys from env
debsrc [ -signer key-id ] [ -upload dest ] -- creates a debian source package
nsis -- creates a Windows NSIS installer
@@ -58,6 +58,7 @@ import (
"time"
"github.com/cespare/cp"
+ signifyPkg "github.com/ethereum/go-ethereum/crypto/signify"
"github.com/ethereum/go-ethereum/internal/build"
"github.com/ethereum/go-ethereum/params"
)
@@ -396,11 +397,12 @@ func downloadLinter(cachedir string) string {
// Release Packaging
func doArchive(cmdline []string) {
var (
- arch = flag.String("arch", runtime.GOARCH, "Architecture cross packaging")
- atype = flag.String("type", "zip", "Type of archive to write (zip|tar)")
- signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`)
- upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
- ext string
+ arch = flag.String("arch", runtime.GOARCH, "Architecture cross packaging")
+ atype = flag.String("type", "zip", "Type of archive to write (zip|tar)")
+ signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. LINUX_SIGNING_KEY)`)
+ signify = flag.String("signify", "", `Environment variable holding the signify key (e.g. LINUX_SIGNIFY_KEY)`)
+ upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
+ ext string
)
flag.CommandLine.Parse(cmdline)
switch *atype {
@@ -427,7 +429,7 @@ func doArchive(cmdline []string) {
log.Fatal(err)
}
for _, archive := range []string{geth, alltools} {
- if err := archiveUpload(archive, *upload, *signer); err != nil {
+ if err := archiveUpload(archive, *upload, *signer, *signify); err != nil {
log.Fatal(err)
}
}
@@ -447,7 +449,7 @@ func archiveBasename(arch string, archiveVersion string) string {
return platform + "-" + archiveVersion
}
-func archiveUpload(archive string, blobstore string, signer string) error {
+func archiveUpload(archive string, blobstore string, signer string, signify string) error {
// If signing was requested, generate the signature files
if signer != "" {
key := getenvBase64(signer)
@@ -455,6 +457,12 @@ func archiveUpload(archive string, blobstore string, signer string) error {
return err
}
}
+ if signify != "" {
+ key := getenvBase64(string(signify))
+ if err := signifyPkg.SignifySignFile(archive, archive+".sig", string(key), "verify with geth.pub", fmt.Sprintf("%d", time.Now().UTC().Unix())); err != nil {
+ return err
+ }
+ }
// If uploading to Azure was requested, push the archive possibly with its signature
if blobstore != "" {
auth := build.AzureBlobstoreConfig{
@@ -470,6 +478,11 @@ func archiveUpload(archive string, blobstore string, signer string) error {
return err
}
}
+ if signify != "" {
+ if err := build.AzureBlobstoreUpload(archive+".sig", filepath.Base(archive+".sig"), auth); err != nil {
+ return err
+ }
+ }
}
return nil
}
@@ -806,6 +819,7 @@ func doWindowsInstaller(cmdline []string) {
var (
arch = flag.String("arch", runtime.GOARCH, "Architecture for cross build packaging")
signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. WINDOWS_SIGNING_KEY)`)
+ signify = flag.String("signify key", "", `Environment variable holding the signify signing key (e.g. WINDOWS_SIGNIFY_KEY)`)
upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
workdir = flag.String("workdir", "", `Output directory for packages (uses temp dir if unset)`)
)
@@ -867,7 +881,7 @@ func doWindowsInstaller(cmdline []string) {
filepath.Join(*workdir, "geth.nsi"),
)
// Sign and publish installer.
- if err := archiveUpload(installer, *upload, *signer); err != nil {
+ if err := archiveUpload(installer, *upload, *signer, *signify); err != nil {
log.Fatal(err)
}
}
@@ -876,10 +890,11 @@ func doWindowsInstaller(cmdline []string) {
func doAndroidArchive(cmdline []string) {
var (
- local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
- signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. ANDROID_SIGNING_KEY)`)
- deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "https://oss.sonatype.org")`)
- upload = flag.String("upload", "", `Destination to upload the archive (usually "gethstore/builds")`)
+ local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
+ signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. ANDROID_SIGNING_KEY)`)
+ signify = flag.String("signify", "", `Environment variable holding the signify signing key (e.g. ANDROID_SIGNIFY_KEY)`)
+ deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "https://oss.sonatype.org")`)
+ upload = flag.String("upload", "", `Destination to upload the archive (usually "gethstore/builds")`)
)
flag.CommandLine.Parse(cmdline)
env := build.Env()
@@ -908,7 +923,7 @@ func doAndroidArchive(cmdline []string) {
archive := "geth-" + archiveBasename("android", params.ArchiveVersion(env.Commit)) + ".aar"
os.Rename("geth.aar", archive)
- if err := archiveUpload(archive, *upload, *signer); err != nil {
+ if err := archiveUpload(archive, *upload, *signer, *signify); err != nil {
log.Fatal(err)
}
// Sign and upload all the artifacts to Maven Central
@@ -1001,10 +1016,11 @@ func newMavenMetadata(env build.Environment) mavenMetadata {
func doXCodeFramework(cmdline []string) {
var (
- local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
- signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. IOS_SIGNING_KEY)`)
- deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "trunk")`)
- upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
+ local = flag.Bool("local", false, `Flag whether we're only doing a local build (skip Maven artifacts)`)
+ signer = flag.String("signer", "", `Environment variable holding the signing key (e.g. IOS_SIGNING_KEY)`)
+ signify = flag.String("signify", "", `Environment variable holding the signify signing key (e.g. IOS_SIGNIFY_KEY)`)
+ deploy = flag.String("deploy", "", `Destination to deploy the archive (usually "trunk")`)
+ upload = flag.String("upload", "", `Destination to upload the archives (usually "gethstore/builds")`)
)
flag.CommandLine.Parse(cmdline)
env := build.Env()
@@ -1032,7 +1048,7 @@ func doXCodeFramework(cmdline []string) {
maybeSkipArchive(env)
// Sign and upload the framework to Azure
- if err := archiveUpload(archive+".tar.gz", *upload, *signer); err != nil {
+ if err := archiveUpload(archive+".tar.gz", *upload, *signer, *signify); err != nil {
log.Fatal(err)
}
// Prepare and upload a PodSpec to CocoaPods
diff --git a/crypto/signify/signify.go b/crypto/signify/signify.go
new file mode 100644
index 000000000000..e86c4f09b0bd
--- /dev/null
+++ b/crypto/signify/signify.go
@@ -0,0 +1,118 @@
+// Copyright 2020 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// signFile reads the contents of an input file and signs it (in armored format)
+// with the key provided, placing the signature into the output file.
+
+package signify
+
+import (
+ "encoding/base64"
+ "errors"
+ "fmt"
+ "io/ioutil"
+ "os"
+ "strings"
+ "time"
+
+ "crypto/ed25519"
+)
+
+var (
+ errInvalidKeyHeader = errors.New("Incorrect key header")
+ errInvalidKeyLength = errors.New("invalid, key length != 104")
+)
+
+func parsePrivateKey(key string) (ed25519.PrivateKey, []byte, []byte, error) {
+ keydata, err := base64.StdEncoding.DecodeString(key)
+ if err != nil {
+ return nil, nil, nil, err
+ }
+
+ if len(keydata) != 104 {
+ return nil, nil, nil, errInvalidKeyLength
+ }
+
+ if string(keydata[:2]) != "Ed" {
+ return nil, nil, nil, errInvalidKeyHeader
+ }
+
+ return ed25519.PrivateKey(keydata[40:]), keydata[:2], keydata[32:40], nil
+}
+
+func commentHasManyLines(comment string) bool {
+ firstLFIndex := strings.IndexByte(comment, 10)
+ return (firstLFIndex >= 0 && firstLFIndex < len(comment)-1)
+}
+
+// SignifySignFile creates a signature of the input file.
+func SignifySignFile(input string, output string, key string, unTrustedComment string, trustedComment string) error {
+ in, err := os.Open(input)
+ if err != nil {
+ return err
+ }
+ defer in.Close()
+
+ out, err := os.Create(output)
+ if err != nil {
+ return err
+ }
+ defer out.Close()
+
+ skey, header, keyNum, err := parsePrivateKey(key)
+ if err != nil {
+ return err
+ }
+
+ filedata, err := ioutil.ReadAll(in)
+ if err != nil {
+ return err
+ }
+
+ rawSig := ed25519.Sign(skey, filedata)
+
+ var sigdata []byte
+ sigdata = append(sigdata, header...)
+ sigdata = append(sigdata, keyNum...)
+ sigdata = append(sigdata, rawSig...)
+
+ // Check that the trusted comment fits in one line
+ if commentHasManyLines(unTrustedComment) {
+ return errors.New("untrusted comment must fit on a single line")
+ }
+
+ if unTrustedComment == "" {
+ unTrustedComment = "verify with " + input + ".pub"
+ }
+ out.WriteString(fmt.Sprintf("untrusted comment: %s\n%s\n", unTrustedComment, base64.StdEncoding.EncodeToString(sigdata)))
+
+ // Add the trusted comment if unavailable
+ if trustedComment == "" {
+ trustedComment = fmt.Sprintf("timestamp:%d", time.Now().Unix())
+ }
+
+ // Check that the trusted comment fits in one line
+ if commentHasManyLines(trustedComment) {
+ return errors.New("trusted comment must fit on a single line")
+ }
+
+ var sigAndComment []byte
+ sigAndComment = append(sigAndComment, rawSig...)
+ sigAndComment = append(sigAndComment, []byte(trustedComment)...)
+ out.WriteString(fmt.Sprintf("trusted comment: %s\n%s\n", trustedComment, base64.StdEncoding.EncodeToString(ed25519.Sign(skey, sigAndComment))))
+
+ return nil
+}
diff --git a/crypto/signify/signify_fuzz.go b/crypto/signify/signify_fuzz.go
new file mode 100644
index 000000000000..d1bcf356a4db
--- /dev/null
+++ b/crypto/signify/signify_fuzz.go
@@ -0,0 +1,148 @@
+// Copyright 2020 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// +build gofuzz
+
+package signify
+
+import (
+ "bufio"
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "os/exec"
+ "runtime"
+
+ fuzz "github.com/google/gofuzz"
+ "github.com/jedisct1/go-minisign"
+)
+
+func Fuzz(data []byte) int {
+ if len(data) < 32 {
+ return -1
+ }
+ tmpFile, err := ioutil.TempFile("", "")
+ if err != nil {
+ panic(err)
+ }
+ defer os.Remove(tmpFile.Name())
+ defer tmpFile.Close()
+
+ testSecKey, testPubKey := createKeyPair()
+ // Create message
+ tmpFile.Write(data)
+ if err = tmpFile.Close(); err != nil {
+ panic(err)
+ }
+ // Fuzz comments
+ var untrustedComment string
+ var trustedComment string
+ f := fuzz.NewFromGoFuzz(data)
+ f.Fuzz(&untrustedComment)
+ f.Fuzz(&trustedComment)
+ fmt.Printf("untrusted: %v\n", untrustedComment)
+ fmt.Printf("trusted: %v\n", trustedComment)
+
+ err = SignifySignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, untrustedComment, trustedComment)
+ if err != nil {
+ panic(err)
+ }
+ defer os.Remove(tmpFile.Name() + ".sig")
+
+ signify := "signify"
+ path := os.Getenv("SIGNIFY")
+ if path != "" {
+ signify = path
+ }
+
+ _, err := exec.LookPath(signify)
+ if err != nil {
+ panic(err)
+ }
+
+ // Write the public key into the file to pass it as
+ // an argument to signify-openbsd
+ pubKeyFile, err := ioutil.TempFile("", "")
+ if err != nil {
+ panic(err)
+ }
+ defer os.Remove(pubKeyFile.Name())
+ defer pubKeyFile.Close()
+ pubKeyFile.WriteString("untrusted comment: signify public key\n")
+ pubKeyFile.WriteString(testPubKey)
+ pubKeyFile.WriteString("\n")
+
+ cmd := exec.Command(signify, "-V", "-p", pubKeyFile.Name(), "-x", tmpFile.Name()+".sig", "-m", tmpFile.Name())
+ if output, err := cmd.CombinedOutput(); err != nil {
+ panic(fmt.Sprintf("could not verify the file: %v, output: \n%s", err, output))
+ }
+
+ // Verify the signature using a golang library
+ sig, err := minisign.NewSignatureFromFile(tmpFile.Name() + ".sig")
+ if err != nil {
+ panic(err)
+ }
+
+ pKey, err := minisign.NewPublicKey(testPubKey)
+ if err != nil {
+ panic(err)
+ }
+
+ valid, err := pKey.VerifyFromFile(tmpFile.Name(), sig)
+ if err != nil {
+ panic(err)
+ }
+ if !valid {
+ panic("invalid signature")
+ }
+ return 1
+}
+
+func getKey(fileS string) (string, error) {
+ file, err := os.Open(fileS)
+ if err != nil {
+ log.Fatal(err)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ // Discard the first line
+ scanner.Scan()
+ scanner.Scan()
+ return scanner.Text(), scanner.Err()
+}
+
+func createKeyPair() (string, string) {
+ // Create key and put it in correct format
+ tmpKey, err := ioutil.TempFile("", "")
+ defer os.Remove(tmpKey.Name())
+ defer os.Remove(tmpKey.Name() + ".pub")
+ defer os.Remove(tmpKey.Name() + ".sec")
+ cmd := exec.Command("signify", "-G", "-n", "-p", tmpKey.Name()+".pub", "-s", tmpKey.Name()+".sec")
+ if output, err := cmd.CombinedOutput(); err != nil {
+ panic(fmt.Sprintf("could not verify the file: %v, output: \n%s", err, output))
+ }
+ secKey, err := getKey(tmpKey.Name() + ".sec")
+ if err != nil {
+ panic(err)
+ }
+ pubKey, err := getKey(tmpKey.Name() + ".pub")
+ if err != nil {
+ panic(err)
+ }
+ return secKey, pubKey
+}
diff --git a/crypto/signify/signify_test.go b/crypto/signify/signify_test.go
new file mode 100644
index 000000000000..af77eaf227e9
--- /dev/null
+++ b/crypto/signify/signify_test.go
@@ -0,0 +1,154 @@
+// Copyright 2020 The go-ethereum Authors
+// This file is part of the go-ethereum library.
+//
+// The go-ethereum library is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// The go-ethereum library 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 Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with the go-ethereum library. If not, see .
+
+// signFile reads the contents of an input file and signs it (in armored format)
+// with the key provided, placing the signature into the output file.
+
+package signify
+
+import (
+ "io/ioutil"
+ "math/rand"
+ "os"
+ "testing"
+ "time"
+
+ "github.com/jedisct1/go-minisign"
+)
+
+var (
+ testSecKey = "RWRCSwAAAABVN5lr2JViGBN8DhX3/Qb/0g0wBdsNAR/APRW2qy9Fjsfr12sK2cd3URUFis1jgzQzaoayK8x4syT4G3Gvlt9RwGIwUYIQW/0mTeI+ECHu1lv5U4Wa2YHEPIesVPyRm5M="
+ testPubKey = "RWTAPRW2qy9FjsBiMFGCEFv9Jk3iPhAh7tZb+VOFmtmBxDyHrFT8kZuT"
+)
+
+func TestSignify(t *testing.T) {
+ tmpFile, err := ioutil.TempFile("", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(tmpFile.Name())
+ defer tmpFile.Close()
+
+ rand.Seed(time.Now().UnixNano())
+
+ data := make([]byte, 1024)
+ rand.Read(data)
+ tmpFile.Write(data)
+
+ if err = tmpFile.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ err = SignifySignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "clé", "croissants")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(tmpFile.Name() + ".sig")
+
+ // Verify the signature using a golang library
+ sig, err := minisign.NewSignatureFromFile(tmpFile.Name() + ".sig")
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ pKey, err := minisign.NewPublicKey(testPubKey)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ valid, err := pKey.VerifyFromFile(tmpFile.Name(), sig)
+ if err != nil {
+ t.Fatal(err)
+ }
+ if !valid {
+ t.Fatal("invalid signature")
+ }
+}
+
+func TestSignifyTrustedCommentTooManyLines(t *testing.T) {
+ tmpFile, err := ioutil.TempFile("", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(tmpFile.Name())
+ defer tmpFile.Close()
+
+ rand.Seed(time.Now().UnixNano())
+
+ data := make([]byte, 1024)
+ rand.Read(data)
+ tmpFile.Write(data)
+
+ if err = tmpFile.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ err = SignifySignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "", "crois\nsants")
+ if err == nil || err.Error() == "" {
+ t.Fatalf("should have errored on a multi-line trusted comment, got %v", err)
+ }
+ defer os.Remove(tmpFile.Name() + ".sig")
+}
+
+func TestSignifyTrustedCommentTooManyLinesLF(t *testing.T) {
+ tmpFile, err := ioutil.TempFile("", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(tmpFile.Name())
+ defer tmpFile.Close()
+
+ rand.Seed(time.Now().UnixNano())
+
+ data := make([]byte, 1024)
+ rand.Read(data)
+ tmpFile.Write(data)
+
+ if err = tmpFile.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ err = SignifySignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "crois\rsants", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(tmpFile.Name() + ".sig")
+}
+
+func TestSignifyTrustedCommentEmpty(t *testing.T) {
+ tmpFile, err := ioutil.TempFile("", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(tmpFile.Name())
+ defer tmpFile.Close()
+
+ rand.Seed(time.Now().UnixNano())
+
+ data := make([]byte, 1024)
+ rand.Read(data)
+ tmpFile.Write(data)
+
+ if err = tmpFile.Close(); err != nil {
+ t.Fatal(err)
+ }
+
+ err = SignifySignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "", "")
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer os.Remove(tmpFile.Name() + ".sig")
+}
diff --git a/go.mod b/go.mod
old mode 100755
new mode 100644
index ae1cf64aaf9c..9a35f6447ff4
--- 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
diff --git a/go.sum b/go.sum
old mode 100755
new mode 100644
index 10bec96411e9..dedae7bc7a20
--- 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=