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.
		
			
				
	
	
		
			101 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			101 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| // 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 <http://www.gnu.org/licenses/>.
 | |
| 
 | |
| // 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 (
 | |
| 	"bytes"
 | |
| 	"crypto/ed25519"
 | |
| 	"encoding/base64"
 | |
| 	"errors"
 | |
| 	"fmt"
 | |
| 	"io/ioutil"
 | |
| 	"strings"
 | |
| 	"time"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	errInvalidKeyHeader = errors.New("incorrect key header")
 | |
| 	errInvalidKeyLength = errors.New("invalid, key length != 104")
 | |
| )
 | |
| 
 | |
| 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
 | |
| }
 | |
| 
 | |
| // 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")
 | |
| 	}
 | |
| 	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())
 | |
| 	}
 | |
| 
 | |
| 	filedata, err := ioutil.ReadFile(input)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 	skey, header, keyNum, err := parsePrivateKey(key)
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	// Create the main data signature.
 | |
| 	rawSig := ed25519.Sign(skey, filedata)
 | |
| 	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)
 | |
| }
 |