1
1
package cli
2
2
3
3
import (
4
+ "context"
4
5
"crypto/x509"
5
6
"fmt"
6
7
"io"
7
8
"os"
9
+ "os/exec"
10
+ "path/filepath"
8
11
"strings"
9
12
10
13
cms "github.com/github/smimesign/ietf-cms"
11
14
"github.com/spf13/cobra"
12
15
"golang.org/x/xerrors"
13
16
14
17
"cdr.dev/slog"
15
- "github.com/coder/code-marketplace/storage/easyzip"
16
-
17
18
"github.com/coder/code-marketplace/extensionsign"
18
- "github.com/coder/code-marketplace/extensionsign/verify "
19
+ "github.com/coder/code-marketplace/storage/easyzip "
19
20
)
20
21
21
22
func signature () * cobra.Command {
@@ -26,89 +27,172 @@ func signature() *cobra.Command {
26
27
Aliases : []string {"sig" , "sigs" , "signatures" },
27
28
}
28
29
29
- cmd .AddCommand (compareSignatureSigZips (), verifyCmd (), decodeSigCmd ())
30
+ cmd .AddCommand (compareSignatureSigZips (), verifySig ())
30
31
return cmd
31
32
}
32
33
33
- func decodeSigCmd () * cobra.Command {
34
+ func verifySig () * cobra.Command {
34
35
cmd := & cobra.Command {
35
-
36
- Use : "decode" ,
37
- Short : "Decode a signature archive." ,
38
- Args : cobra .ExactArgs (1 ),
36
+ Use : "verify" ,
37
+ Short : "Decode & verify a signature archive." ,
38
+ Args : cobra .ExactArgs (2 ),
39
39
RunE : func (cmd * cobra.Command , args []string ) error {
40
40
logger := cmdLogger (cmd )
41
41
ctx := cmd .Context ()
42
- logger .Info (ctx , fmt .Sprintf ("Decoding %q" , args [0 ]))
42
+ extensionVsix := args [0 ]
43
+ p7sFile := args [1 ]
43
44
44
- data , err := os .ReadFile (args [0 ])
45
- if err != nil {
46
- return xerrors .Errorf ("read %q: %w" , args [0 ], err )
47
- }
45
+ logger .Info (ctx , fmt .Sprintf ("Decoding %q" , p7sFile ))
48
46
49
- signed , err := extensionsign . ExtractP7SSig ( data )
47
+ data , err := os . ReadFile ( p7sFile )
50
48
if err != nil {
51
- return xerrors .Errorf ("extract p7s : %w" , err )
49
+ return xerrors .Errorf ("read %q : %w" , p7sFile , err )
52
50
}
53
51
54
- detachedDataR , err := easyzip .GetZipFileReader (data , ".signature.manifest" )
52
+ msg , err := easyzip .GetZipFileReader (data , ".signature.manifest" )
55
53
if err != nil {
56
54
return xerrors .Errorf ("get manifest: %w" , err )
57
55
}
58
- detachedData , err := io .ReadAll (detachedDataR )
56
+ msgData , err := io .ReadAll (msg )
59
57
if err != nil {
60
58
return xerrors .Errorf ("read manifest: %w" , err )
61
59
}
62
60
63
- sd , err := cms . ParseSignedData ( signed )
61
+ signed , err := extensionsign . ExtractP7SSig ( data )
64
62
if err != nil {
65
- return xerrors .Errorf ("new signed data : %w" , err )
63
+ return xerrors .Errorf ("extract p7s : %w" , err )
66
64
}
67
65
68
- fmt .Println ("Detached:" , sd . IsDetached () )
69
- certs , err := sd . GetCertificates ( )
66
+ fmt .Println ("----------------Golang Verify----------------" )
67
+ valid , err := goVerify ( ctx , logger , msgData , signed )
70
68
if err != nil {
71
- return xerrors . Errorf ( "get certs: %w " , err )
69
+ logger . Error ( ctx , "go verify " , slog . Error ( err ) )
72
70
}
73
- fmt .Println ( "Certificates: " , len ( certs ))
71
+ logger . Info ( ctx , fmt .Sprintf ( "Valid: %t " , valid ))
74
72
75
- sdData , err := sd .GetData ()
73
+ fmt .Println ("----------------OpenSSL Verify----------------" )
74
+ valid , err = openSSLVerify (ctx , logger , msgData , signed )
76
75
if err != nil {
77
- return xerrors . Errorf ( "get data: %w " , err )
76
+ logger . Error ( ctx , "openssl verify " , slog . Error ( err ) )
78
77
}
79
- fmt .Println ("Data:" , len (sdData ))
80
-
81
- var verifyErr error
82
- var vcerts [][][]* x509.Certificate
78
+ logger .Info (ctx , fmt .Sprintf ("Valid: %t" , valid ))
83
79
84
- sys , err := x509 .SystemCertPool ()
80
+ fmt .Println ("----------------vsce-sign Verify----------------" )
81
+ valid , err = vsceSignVerify (ctx , logger , extensionVsix , p7sFile )
85
82
if err != nil {
86
- return xerrors .Errorf ("system cert pool: %w" , err )
87
- }
88
- opts := x509.VerifyOptions {
89
- Intermediates : sys ,
90
- Roots : sys ,
83
+ logger .Error (ctx , "openssl verify" , slog .Error (err ))
91
84
}
92
-
93
- if sd .IsDetached () {
94
- vcerts , verifyErr = sd .VerifyDetached (detachedData , opts )
95
- } else {
96
- vcerts , verifyErr = sd .Verify (opts )
97
- }
98
- if verifyErr != nil {
99
- logger .Fatal (ctx , "verify" , slog .Error (verifyErr ))
100
- }
101
-
102
- certChain := dimensions (vcerts )
103
- fmt .Println ("Verified!" )
104
- fmt .Println (certChain )
85
+ logger .Info (ctx , fmt .Sprintf ("Valid: %t" , valid ))
105
86
106
87
return nil
107
88
},
108
89
}
109
90
return cmd
110
91
}
111
92
93
+ func goVerify (ctx context.Context , logger slog.Logger , message []byte , signature []byte ) (bool , error ) {
94
+ sd , err := cms .ParseSignedData (signature )
95
+ if err != nil {
96
+ return false , xerrors .Errorf ("new signed data: %w" , err )
97
+ }
98
+
99
+ fmt .Println ("Detached:" , sd .IsDetached ())
100
+ certs , err := sd .GetCertificates ()
101
+ if err != nil {
102
+ return false , xerrors .Errorf ("get certs: %w" , err )
103
+ }
104
+ fmt .Println ("Certificates:" , len (certs ))
105
+
106
+ sdData , err := sd .GetData ()
107
+ if err != nil {
108
+ return false , xerrors .Errorf ("get data: %w" , err )
109
+ }
110
+ fmt .Println ("Data:" , len (sdData ))
111
+
112
+ var verifyErr error
113
+ var vcerts [][][]* x509.Certificate
114
+
115
+ sys , err := x509 .SystemCertPool ()
116
+ if err != nil {
117
+ return false , xerrors .Errorf ("system cert pool: %w" , err )
118
+ }
119
+ opts := x509.VerifyOptions {
120
+ Intermediates : sys ,
121
+ Roots : sys ,
122
+ }
123
+
124
+ if sd .IsDetached () {
125
+ vcerts , verifyErr = sd .VerifyDetached (message , opts )
126
+ } else {
127
+ vcerts , verifyErr = sd .Verify (opts )
128
+ }
129
+ if verifyErr != nil {
130
+ logger .Error (ctx , "verify" , slog .Error (verifyErr ))
131
+ }
132
+
133
+ certChain := dimensions (vcerts )
134
+ fmt .Println (certChain )
135
+ return verifyErr == nil , nil
136
+ }
137
+
138
+ func openSSLVerify (ctx context.Context , logger slog.Logger , message []byte , signature []byte ) (bool , error ) {
139
+ // openssl cms -verify -in message_from_alice_for_bob.msg -inform DER -CAfile ehealth_root_ca.cer | openssl cms -decrypt -inform DER -recip bob_etk_pair.pem | openssl cms -inform DER -cmsout -print
140
+ tmpdir := os .TempDir ()
141
+ tmpdir = filepath .Join (tmpdir , "verify-sigs" )
142
+ defer os .RemoveAll (tmpdir )
143
+ os .MkdirAll (tmpdir , 0755 )
144
+ msgPath := filepath .Join (tmpdir , ".signature.manifest" )
145
+ err := os .WriteFile (msgPath , message , 0644 )
146
+ if err != nil {
147
+ return false , xerrors .Errorf ("write message: %w" , err )
148
+ }
149
+
150
+ sigPath := filepath .Join (tmpdir , ".signature.p7s" )
151
+ err = os .WriteFile (sigPath , signature , 0644 )
152
+ if err != nil {
153
+ return false , xerrors .Errorf ("write signature: %w" , err )
154
+ }
155
+
156
+ cmd := exec .CommandContext (ctx , "openssl" , "smime" , "-verify" ,
157
+ "-in" , sigPath , "-content" , msgPath , "-inform" , "DER" ,
158
+ "-CAfile" , "/home/steven/go/src/github.com/coder/code-marketplace/extensionsign/testdata/cert2.pem" ,
159
+ )
160
+ output := & strings.Builder {}
161
+ cmd .Stdout = output
162
+ cmd .Stderr = output
163
+ err = cmd .Run ()
164
+ fmt .Println (output .String ())
165
+ if err != nil {
166
+ return false , xerrors .Errorf ("run verify %q: %w" , cmd .String (), err )
167
+ }
168
+
169
+ return cmd .ProcessState .ExitCode () == 0 , nil
170
+ }
171
+
172
+ func vsceSignVerify (ctx context.Context , logger slog.Logger , vsixPath , sigPath string ) (bool , error ) {
173
+ bin := os .Getenv ("VSCE_SIGN_PATH" )
174
+ if bin == "" {
175
+ return false , xerrors .Errorf ("VSCE_SIGN_PATH not set" )
176
+ }
177
+
178
+ cmd := exec .CommandContext (ctx , bin , "verify" ,
179
+ "--package" , vsixPath ,
180
+ "--signaturearchive" , sigPath ,
181
+ "-v" ,
182
+ )
183
+ fmt .Println (cmd .String ())
184
+ output := & strings.Builder {}
185
+ cmd .Stdout = output
186
+ cmd .Stderr = output
187
+ err := cmd .Run ()
188
+ fmt .Println (output .String ())
189
+ if err != nil {
190
+ return false , xerrors .Errorf ("run verify %q: %w" , cmd .String (), err )
191
+ }
192
+
193
+ return cmd .ProcessState .ExitCode () == 0 , nil
194
+ }
195
+
112
196
func dimensions (chain [][][]* x509.Certificate ) string {
113
197
var str strings.Builder
114
198
for _ , top := range chain {
@@ -123,17 +207,6 @@ func dimensions(chain [][][]*x509.Certificate) string {
123
207
return str .String ()
124
208
}
125
209
126
- func verifyCmd () * cobra.Command {
127
- cmd := & cobra.Command {
128
- Use : "verify" ,
129
- RunE : func (cmd * cobra.Command , args []string ) error {
130
- ctx := cmd .Context ()
131
- return verify .DownloadVsceSign (ctx )
132
- },
133
- }
134
- return cmd
135
- }
136
-
137
210
func compareSignatureSigZips () * cobra.Command {
138
211
cmd := & cobra.Command {
139
212
Use : "compare" ,
0 commit comments