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 }