Explorar el Código

crypto/signify, build: fix archive signing with signify (#21977)

This fixes some issues in crypto/signify and makes release signing work.

The archive signing step in ci.go used getenvBase64, which decodes the key data.
This is incorrect here because crypto/signify already base64-decodes the key.
Felix Lange hace 4 años
padre
commit
f935b1d542
Se han modificado 4 ficheros con 66 adiciones y 82 borrados
  1. 13 13
      .travis.yml
  2. 8 6
      build/ci.go
  3. 41 59
      crypto/signify/signify.go
  4. 4 4
      crypto/signify/signify_test.go

+ 13 - 13
.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 -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
+        - go run build/ci.go archive -type tar -signer LINUX_SIGNING_KEY -signify 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 -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
+        - go run build/ci.go archive -arch 386 -type tar -signer LINUX_SIGNING_KEY -signify 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 -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
+        - GOARM=5 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify 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 -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
+        - GOARM=6 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify 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 -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
+        - GOARM=7 go run build/ci.go archive -arch arm -type tar -signer LINUX_SIGNING_KEY -signify 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 -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
+        - go run build/ci.go archive -arch arm64 -type tar -signer LINUX_SIGNING_KEY -signify 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 -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
+        - go run build/ci.go archive -arch mips -type tar -signer LINUX_SIGNING_KEY -signify 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 -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
+        - go run build/ci.go archive -arch mipsle -type tar -signer LINUX_SIGNING_KEY -signify 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 signify LINUX_SIGNIFY_KEY -upload gethstore/builds
+        - go run build/ci.go archive -arch mips64 -type tar -signer LINUX_SIGNING_KEY signify 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 -signify LINUX_SIGNIFY_KEY -upload gethstore/builds
+        - go run build/ci.go archive -arch mips64le -type tar -signer LINUX_SIGNING_KEY -signify 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 -signify ANDROID_SIGNIFY_KEY  -deploy https://oss.sonatype.org -upload gethstore/builds
+        - go run build/ci.go aar -signer ANDROID_SIGNING_KEY -signify 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 -signify OSX_SIGNIFY_KEY -upload gethstore/builds
+        - go run build/ci.go archive -type tar -signer OSX_SIGNING_KEY -signify 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 -signify IOS_SIGNIFY_KEY -deploy trunk -upload gethstore/builds
+        - go run build/ci.go xcode -signer IOS_SIGNING_KEY -signify SIGNIFY_KEY -deploy trunk -upload gethstore/builds
 
     # These builders run the tests
     - stage: build

+ 8 - 6
build/ci.go

@@ -58,7 +58,7 @@ import (
 	"time"
 
 	"github.com/cespare/cp"
-	signifyPkg "github.com/ethereum/go-ethereum/crypto/signify"
+	"github.com/ethereum/go-ethereum/crypto/signify"
 	"github.com/ethereum/go-ethereum/internal/build"
 	"github.com/ethereum/go-ethereum/params"
 )
@@ -449,7 +449,7 @@ func archiveBasename(arch string, archiveVersion string) string {
 	return platform + "-" + archiveVersion
 }
 
-func archiveUpload(archive string, blobstore string, signer string, signify string) error {
+func archiveUpload(archive string, blobstore string, signer string, signifyVar string) error {
 	// If signing was requested, generate the signature files
 	if signer != "" {
 		key := getenvBase64(signer)
@@ -457,9 +457,11 @@ func archiveUpload(archive string, blobstore string, signer string, signify stri
 			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 {
+	if signifyVar != "" {
+		key := os.Getenv(signifyVar)
+		untrustedComment := "verify with geth-release.pub"
+		trustedComment := fmt.Sprintf("%s (%s)", archive, time.Now().UTC().Format(time.RFC1123))
+		if err := signify.SignFile(archive, archive+".sig", key, untrustedComment, trustedComment); err != nil {
 			return err
 		}
 	}
@@ -478,7 +480,7 @@ func archiveUpload(archive string, blobstore string, signer string, signify stri
 				return err
 			}
 		}
-		if signify != "" {
+		if signifyVar != "" {
 			if err := build.AzureBlobstoreUpload(archive+".sig", filepath.Base(archive+".sig"), auth); err != nil {
 				return err
 			}

+ 41 - 59
crypto/signify/signify.go

@@ -20,99 +20,81 @@
 package signify
 
 import (
+	"bytes"
+	"crypto/ed25519"
 	"encoding/base64"
 	"errors"
 	"fmt"
 	"io/ioutil"
-	"os"
 	"strings"
 	"time"
-
-	"crypto/ed25519"
 )
 
 var (
-	errInvalidKeyHeader = errors.New("Incorrect key header")
+	errInvalidKeyHeader = errors.New("incorrect key header")
 	errInvalidKeyLength = errors.New("invalid, key length != 104")
 )
 
-func parsePrivateKey(key string) (ed25519.PrivateKey, []byte, []byte, error) {
+func parsePrivateKey(key string) (k ed25519.PrivateKey, header []byte, keyNum []byte, err 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
+// SignFile creates a signature of the input file.
+//
+// This accepts base64 keys in the format created by the 'signify' tool.
+// The signature is written to the 'output' file.
+func SignFile(input string, output string, key string, untrustedComment string, trustedComment string) error {
+	// Pre-check comments and ensure they're set to something.
+	if strings.IndexByte(untrustedComment, '\n') >= 0 {
+		return errors.New("untrusted comment must not contain newline")
 	}
-	defer in.Close()
-
-	out, err := os.Create(output)
-	if err != nil {
-		return err
+	if strings.IndexByte(trustedComment, '\n') >= 0 {
+		return errors.New("trusted comment must not contain newline")
+	}
+	if untrustedComment == "" {
+		untrustedComment = "verify with " + input + ".pub"
+	}
+	if trustedComment == "" {
+		trustedComment = fmt.Sprintf("timestamp:%d", time.Now().Unix())
 	}
-	defer out.Close()
 
-	skey, header, keyNum, err := parsePrivateKey(key)
+	filedata, err := ioutil.ReadFile(input)
 	if err != nil {
 		return err
 	}
-
-	filedata, err := ioutil.ReadAll(in)
+	skey, header, keyNum, err := parsePrivateKey(key)
 	if err != nil {
 		return err
 	}
 
+	// Create the main data signature.
 	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
+	var dataSig []byte
+	dataSig = append(dataSig, header...)
+	dataSig = append(dataSig, keyNum...)
+	dataSig = append(dataSig, rawSig...)
+
+	// Create the comment signature.
+	var commentSigInput []byte
+	commentSigInput = append(commentSigInput, rawSig...)
+	commentSigInput = append(commentSigInput, []byte(trustedComment)...)
+	commentSig := ed25519.Sign(skey, commentSigInput)
+
+	// Create the output file.
+	var out = new(bytes.Buffer)
+	fmt.Fprintln(out, "untrusted comment:", untrustedComment)
+	fmt.Fprintln(out, base64.StdEncoding.EncodeToString(dataSig))
+	fmt.Fprintln(out, "trusted comment:", trustedComment)
+	fmt.Fprintln(out, base64.StdEncoding.EncodeToString(commentSig))
+	return ioutil.WriteFile(output, out.Bytes(), 0644)
 }

+ 4 - 4
crypto/signify/signify_test.go

@@ -52,7 +52,7 @@ func TestSignify(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	err = SignifySignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "clé", "croissants")
+	err = SignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "clé", "croissants")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -96,7 +96,7 @@ func TestSignifyTrustedCommentTooManyLines(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	err = SignifySignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "", "crois\nsants")
+	err = SignFile(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)
 	}
@@ -121,7 +121,7 @@ func TestSignifyTrustedCommentTooManyLinesLF(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	err = SignifySignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "crois\rsants", "")
+	err = SignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "crois\rsants", "")
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -146,7 +146,7 @@ func TestSignifyTrustedCommentEmpty(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	err = SignifySignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "", "")
+	err = SignFile(tmpFile.Name(), tmpFile.Name()+".sig", testSecKey, "", "")
 	if err != nil {
 		t.Fatal(err)
 	}