github.com/google/trillian-examples@v0.0.0-20240520080811-0d40d35cef0e/binary_transparency/firmware/internal/crypto/signature.go (about)

     1  // Copyright 2020 Google LLC. All Rights Reserved.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package crypto
    16  
    17  import (
    18  	"crypto"
    19  	"crypto/rand"
    20  	"crypto/rsa"
    21  	"crypto/sha512"
    22  	"crypto/x509"
    23  	"encoding/pem"
    24  	"errors"
    25  	"fmt"
    26  	"io"
    27  	"strings"
    28  
    29  	"github.com/google/trillian-examples/binary_transparency/firmware/api"
    30  )
    31  
    32  var (
    33  	// Publisher makes statements containing the firmware metadata.
    34  	Publisher = Claimant{
    35  		priv: TestVendorRSAPriv,
    36  		pub:  TestVendorRSAPub,
    37  	}
    38  
    39  	// AnnotatorMalware makes annotation statements about malware in firmware.
    40  	AnnotatorMalware = Claimant{
    41  		priv: TestAnnotationPriv,
    42  		pub:  TestAnnotationPub,
    43  	}
    44  )
    45  
    46  // Claimant is someone that makes statements, and can sign and verify them.
    47  type Claimant struct {
    48  	// Note that outside of a demo the private key should never be used like this!
    49  	priv, pub string
    50  }
    51  
    52  func (c *Claimant) getPrivateKey() (*rsa.PrivateKey, error) {
    53  	mKey := strings.NewReader(c.priv)
    54  	priv, err := io.ReadAll(mKey)
    55  	if err != nil {
    56  		return nil, fmt.Errorf("read failed! %s", err)
    57  	}
    58  
    59  	privPem, rest := pem.Decode(priv)
    60  	if len(rest) != 0 {
    61  		return nil, fmt.Errorf("extraneous data: %v", rest)
    62  	}
    63  	if privPem == nil {
    64  		return nil, fmt.Errorf("pem decoded to nil")
    65  	}
    66  	if privPem.Type != "RSA PRIVATE KEY" {
    67  		return nil, fmt.Errorf("RSA private key is of the wrong type %s", privPem.Type)
    68  	}
    69  
    70  	var privateKey *rsa.PrivateKey
    71  	if privateKey, err = x509.ParsePKCS1PrivateKey(privPem.Bytes); err != nil {
    72  		return nil, fmt.Errorf("unable to parse RSA private key %v", err)
    73  	}
    74  
    75  	return privateKey, nil
    76  }
    77  
    78  func (c *Claimant) getPublicKey() (*rsa.PublicKey, error) {
    79  	mKey := strings.NewReader(c.pub)
    80  	pub, err := io.ReadAll(mKey)
    81  	if err != nil {
    82  		return nil, fmt.Errorf("public key read failed! %s", err)
    83  	}
    84  
    85  	pubPem, rest := pem.Decode(pub)
    86  	if len(rest) != 0 {
    87  		return nil, fmt.Errorf("extraneous data: %v", rest)
    88  	}
    89  	if pubPem == nil {
    90  		return nil, fmt.Errorf("pem decoded to nil")
    91  	}
    92  	if pubPem.Type != "RSA PUBLIC KEY" {
    93  		return nil, fmt.Errorf("RSA public key is of the wrong type %s", pubPem.Type)
    94  	}
    95  
    96  	var pubKey *rsa.PublicKey
    97  	if pubKey, err = x509.ParsePKCS1PublicKey(pubPem.Bytes); err != nil {
    98  		return nil, fmt.Errorf("unable to parse RSA public key %v", err)
    99  	}
   100  
   101  	return pubKey, nil
   102  }
   103  
   104  // SignMessage is used to sign the Statement
   105  func (c *Claimant) SignMessage(stype api.StatementType, msg []byte) ([]byte, error) {
   106  	if len(msg) > 64*1024*1024 {
   107  		return nil, errors.New("msg too large")
   108  	}
   109  	bs := make([]byte, len(msg)+1)
   110  	bs[0] = byte(stype)
   111  	copy(bs[1:], msg)
   112  
   113  	// Before signing, we need to hash the message
   114  	// The hash is what we actually sign
   115  	h := sha512.Sum512(bs)
   116  
   117  	// Get the required key for signing
   118  	key, err := c.getPrivateKey()
   119  	if err != nil {
   120  		return nil, fmt.Errorf("private key fetch failed %v", err)
   121  	}
   122  	// use PSS over PKCS#1 v1.5 for enhanced security
   123  	signature, err := rsa.SignPSS(rand.Reader, key, crypto.SHA512, h[:], nil)
   124  	if err != nil {
   125  		return nil, fmt.Errorf("failed to sign statement %v", err)
   126  	}
   127  	return signature, nil
   128  }
   129  
   130  // VerifySignature is used to verify the incoming message
   131  func (c *Claimant) VerifySignature(stype api.StatementType, stmt []byte, signature []byte) error {
   132  	// Get the required key for signing
   133  	key, err := c.getPublicKey()
   134  	if err != nil {
   135  		return fmt.Errorf("public key fetch failed %v", err)
   136  	}
   137  	bs := make([]byte, len(stmt)+1)
   138  	bs[0] = byte(stype)
   139  	copy(bs[1:], stmt)
   140  
   141  	// Before verify, we need to hash the message
   142  	// The hash is what we actually verify
   143  	h := sha512.Sum512(bs)
   144  
   145  	if err = rsa.VerifyPSS(key, crypto.SHA512, h[:], signature, nil); err != nil {
   146  		return fmt.Errorf("failed to verify signature %v", err)
   147  	}
   148  	// If we don't get any error from the `VerifyPSS` method, implies our
   149  	// signature is valid
   150  	return nil
   151  }
   152  
   153  // ClaimantForType returns the relevant Claimant for the given Statement type.
   154  func ClaimantForType(t api.StatementType) (*Claimant, error) {
   155  	switch t {
   156  	case api.FirmwareMetadataType:
   157  		return &Publisher, nil
   158  	case api.MalwareStatementType:
   159  		return &AnnotatorMalware, nil
   160  	default:
   161  		return nil, fmt.Errorf("Unknown Claimant type %v", t)
   162  	}
   163  }