11package selfupdate
22
3- // Borrowed code directly from https://github.com/jedisct1/go-minisign
4- // however modified to support reading signatures from remote URLs,
5- // local file etc.
63import (
7- "encoding/base64"
84 "errors"
9- "io/ioutil "
5+ "io"
106 "net/http"
11- "strings"
127
13- "golang.org/x/crypto/blake2b"
14- "golang.org/x/crypto/ed25519"
8+ "aead.dev/minisign"
159)
1610
1711type Verifier struct {
18- publicKey publicKey
19- signature signature
12+ publicKey minisign. PublicKey
13+ signature minisign. Signature
2014}
2115
22- type publicKey struct {
23- SignatureAlgorithm [2 ]byte
24- KeyID [8 ]byte
25- Key [32 ]byte
26- }
27-
28- type signature struct {
29- UntrustedComment string
30- SignatureAlgorithm [2 ]byte
31- KeyID [8 ]byte
32- Signature [64 ]byte
33- TrustedComment string
34- GlobalSignature [64 ]byte
35- }
36-
37- func parsePublicKey (publicKeyStr string ) (publicKey , error ) {
38- var pkey publicKey
39- bin , err := base64 .StdEncoding .DecodeString (publicKeyStr )
40- if err != nil || len (bin ) != 42 {
41- return pkey , errors .New ("Invalid encoded public key" )
42- }
43- copy (pkey .SignatureAlgorithm [:], bin [0 :2 ])
44- copy (pkey .KeyID [:], bin [2 :10 ])
45- copy (pkey .Key [:], bin [10 :42 ])
46- return pkey , nil
47- }
48-
49- func trimCarriageReturn (input string ) string {
50- return strings .TrimRight (input , "\r " )
51- }
52-
53- func decodeSignature (in string ) (signature , error ) {
54- var sign signature
55- lines := strings .SplitN (in , "\n " , 4 )
56- if len (lines ) < 4 {
57- return sign , errors .New ("Incomplete encoded signature" )
58- }
59- sign .UntrustedComment = trimCarriageReturn (lines [0 ])
60- bin1 , err := base64 .StdEncoding .DecodeString (lines [1 ])
61- if err != nil || len (bin1 ) != 74 {
62- return sign , errors .New ("Invalid encoded signature" )
63- }
64- sign .TrustedComment = trimCarriageReturn (lines [2 ])
65- bin2 , err := base64 .StdEncoding .DecodeString (lines [3 ])
66- if err != nil || len (bin2 ) != 64 {
67- return sign , errors .New ("Invalid encoded signature" )
16+ func (v * Verifier ) LoadFromURL (signatureURL string , passphrase string , transport http.RoundTripper ) error {
17+ var publicKey minisign.PublicKey
18+ if err := publicKey .UnmarshalText ([]byte (passphrase )); err != nil {
19+ return err
6820 }
69- copy (sign .SignatureAlgorithm [:], bin1 [0 :2 ])
70- copy (sign .KeyID [:], bin1 [2 :10 ])
71- copy (sign .Signature [:], bin1 [10 :74 ])
72- copy (sign .GlobalSignature [:], bin2 )
73- return sign , nil
74- }
7521
76- func parseSignatureFromURL (url string , transport http.RoundTripper ) (signature , error ) {
77- var sign signature
78- req , err := http .NewRequest (http .MethodGet , url , nil )
22+ client := & http.Client {Transport : transport }
23+ req , err := http .NewRequest (http .MethodGet , signatureURL , nil )
7924 if err != nil {
80- return sign , err
25+ return err
8126 }
82- client := & http.Client {Transport : transport }
8327 resp , err := client .Do (req )
8428 if err != nil {
85- return sign , err
29+ return err
8630 }
8731 defer resp .Body .Close ()
8832 if resp .StatusCode != http .StatusOK {
89- return sign , errors .New (resp .Status )
90- }
91- bin , err := ioutil .ReadAll (resp .Body )
92- if err != nil {
93- return sign , err
33+ return errors .New (resp .Status )
9434 }
95- return decodeSignature (string (bin ))
96- }
97-
98- func parseSignatureFromFile (file string ) (signature , error ) {
99- bin , err := ioutil .ReadFile (file )
100- if err != nil {
101- return signature {}, err
102- }
103- return decodeSignature (string (bin ))
104- }
10535
106- func ( v * Verifier ) LoadFromURL ( signatureURL string , passphrase string , transport http. RoundTripper ) error {
107- pkey , err := parsePublicKey ( passphrase )
36+ const MaxSize = 1 << 20
37+ b , err := io . ReadAll ( io . LimitReader ( resp . Body , MaxSize ) )
10838 if err != nil {
10939 return err
11040 }
111- v .publicKey = pkey
112-
113- sign , err := parseSignatureFromURL (signatureURL , transport )
114- if err != nil {
41+ var signature minisign.Signature
42+ if err = signature .UnmarshalText (b ); err != nil {
11543 return err
11644 }
117-
118- v .signature = sign
45+ v .publicKey , v .signature = publicKey , signature
11946 return nil
12047}
12148
12249func (v * Verifier ) LoadFromFile (signaturePath string , passphrase string ) error {
123- pkey , err := parsePublicKey ( passphrase )
124- if err != nil {
50+ var publicKey minisign. PublicKey
51+ if err := publicKey . UnmarshalText ([] byte ( passphrase )); err != nil {
12552 return err
12653 }
127- v .publicKey = pkey
128-
129- sign , err := parseSignatureFromFile (signaturePath )
54+ signature , err := minisign .SignatureFromFile (signaturePath )
13055 if err != nil {
13156 return err
13257 }
133-
134- v .signature = sign
58+ v .publicKey , v .signature = publicKey , signature
13559 return nil
13660}
13761
@@ -140,36 +64,12 @@ func NewVerifier() *Verifier {
14064}
14165
14266func (v * Verifier ) Verify (bin []byte ) error {
143- if v .publicKey .SignatureAlgorithm != [2 ]byte {'E' , 'd' } {
144- return errors .New ("Incompatible signature algorithm" )
145- }
146- prehashed := false
147- if v .signature .SignatureAlgorithm [0 ] == 0x45 && v .signature .SignatureAlgorithm [1 ] == 0x64 {
148- prehashed = false
149- } else if v .signature .SignatureAlgorithm [0 ] == 0x45 && v .signature .SignatureAlgorithm [1 ] == 0x44 {
150- prehashed = true
151- } else {
152- return errors .New ("Unsupported signature algorithm" )
153- }
154- if v .publicKey .KeyID != v .signature .KeyID {
155- return errors .New ("Incompatible key identifiers" )
156- }
157- if ! strings .HasPrefix (v .signature .TrustedComment , "trusted comment: " ) {
158- return errors .New ("Unexpected format for the trusted comment" )
159- }
160- if prehashed {
161- h , _ := blake2b .New512 (nil )
162- h .Write (bin )
163- bin = h .Sum (nil )
164- }
165- if ! ed25519 .Verify (ed25519 .PublicKey (v .publicKey .Key [:]), bin , v .signature .Signature [:]) {
166- return errors .New ("Invalid signature" )
67+ signature , err := v .signature .MarshalText ()
68+ if err != nil {
69+ return err
16770 }
168- if ! ed25519 .Verify (ed25519 .PublicKey (v .publicKey .Key [:]),
169- append (v .signature .Signature [:],
170- []byte (v .signature .TrustedComment )[17 :]... ),
171- v .signature .GlobalSignature [:]) {
172- return errors .New ("Invalid global signature" )
71+ if ! minisign .Verify (v .publicKey , bin , signature ) {
72+ return errors .New ("selfupdate: signature verification failed" )
17373 }
17474 return nil
17575}
0 commit comments