github.com/google/trillian-examples@v0.0.0-20240520080811-0d40d35cef0e/binary_transparency/firmware/devices/usbarmory/bootloader/minisign.go (about)

     1  // https://github.com/jedisct1/go-minisign
     2  //
     3  // Copyright (c) 2018-2019 Frank Denis
     4  //
     5  // This code is a modified version of go-minisign which ignores trusted
     6  // comments to support verification of both signify as well as minisign
     7  // signatures.
     8  //
     9  // Use of this source code is governed by the license that can be found at:
    10  //   https://github.com/jedisct1/go-minisign/blob/master/LICENSE
    11  
    12  //go:build armory
    13  // +build armory
    14  
    15  package main
    16  
    17  import (
    18  	"encoding/base64"
    19  	"errors"
    20  	"strings"
    21  
    22  	"golang.org/x/crypto/ed25519"
    23  )
    24  
    25  type PublicKey struct {
    26  	SignatureAlgorithm [2]byte
    27  	KeyId              [8]byte
    28  	PublicKey          [32]byte
    29  }
    30  
    31  type Signature struct {
    32  	UntrustedComment   string
    33  	SignatureAlgorithm [2]byte
    34  	KeyId              [8]byte
    35  	Signature          [64]byte
    36  	TrustedComment     string
    37  	GlobalSignature    [64]byte
    38  }
    39  
    40  func NewPublicKey(publicKeyStr string) (PublicKey, error) {
    41  	var publicKey PublicKey
    42  
    43  	bin, err := base64.StdEncoding.DecodeString(publicKeyStr)
    44  
    45  	if err != nil || len(bin) != 42 {
    46  		return publicKey, errors.New("Invalid encoded public key")
    47  	}
    48  
    49  	copy(publicKey.SignatureAlgorithm[:], bin[0:2])
    50  	copy(publicKey.KeyId[:], bin[2:10])
    51  	copy(publicKey.PublicKey[:], bin[10:42])
    52  
    53  	return publicKey, nil
    54  }
    55  
    56  func DecodeSignature(in string) (Signature, error) {
    57  	var signature Signature
    58  
    59  	lines := strings.SplitN(in, "\n", 4)
    60  
    61  	if len(lines) < 2 {
    62  		return signature, errors.New("Incomplete encoded signature")
    63  	}
    64  
    65  	signature.UntrustedComment = lines[0]
    66  
    67  	bin1, err := base64.StdEncoding.DecodeString(lines[1])
    68  
    69  	if err != nil || len(bin1) != 74 {
    70  		return signature, errors.New("Invalid encoded signature")
    71  	}
    72  
    73  	copy(signature.SignatureAlgorithm[:], bin1[0:2])
    74  	copy(signature.KeyId[:], bin1[2:10])
    75  	copy(signature.Signature[:], bin1[10:74])
    76  
    77  	if len(lines) == 4 {
    78  		signature.TrustedComment = lines[2]
    79  
    80  		bin2, err := base64.StdEncoding.DecodeString(lines[3])
    81  
    82  		if err != nil || len(bin2) != 64 {
    83  			return signature, errors.New("Invalid encoded signature")
    84  		}
    85  
    86  		copy(signature.GlobalSignature[:], bin2)
    87  	}
    88  
    89  	return signature, nil
    90  }
    91  
    92  func (publicKey *PublicKey) Verify(bin []byte, signature Signature) (bool, error) {
    93  	if publicKey.SignatureAlgorithm != signature.SignatureAlgorithm {
    94  		return false, errors.New("Incompatible signature algorithm")
    95  	}
    96  
    97  	if signature.SignatureAlgorithm[0] != 0x45 || signature.SignatureAlgorithm[1] != 0x64 {
    98  		return false, errors.New("Unsupported signature algorithm")
    99  	}
   100  
   101  	if publicKey.KeyId != signature.KeyId {
   102  		return false, errors.New("Incompatible key identifiers")
   103  	}
   104  
   105  	if !ed25519.Verify(ed25519.PublicKey(publicKey.PublicKey[:]), bin, signature.Signature[:]) {
   106  		return false, errors.New("Invalid signature")
   107  	}
   108  
   109  	if len(signature.TrustedComment) != 0 {
   110  		if !strings.HasPrefix(signature.TrustedComment, "trusted comment: ") {
   111  			return false, errors.New("Unexpected format for the trusted comment")
   112  		}
   113  
   114  		if !ed25519.Verify(ed25519.PublicKey(publicKey.PublicKey[:]), append(signature.Signature[:], []byte(signature.TrustedComment)[17:]...), signature.GlobalSignature[:]) {
   115  			return false, errors.New("Invalid global signature")
   116  		}
   117  	}
   118  
   119  	return true, nil
   120  }