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 }