Skip to content

Commit ccad7c0

Browse files
committed
chore: adding debugging code
1 parent 449f77c commit ccad7c0

File tree

8 files changed

+219
-66
lines changed

8 files changed

+219
-66
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ bin
33
coverage
44
extensions
55
.idea
6+
.run

Diff for: cli/server.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,11 @@ func serverFlags() (addFlags func(cmd *cobra.Command), opts *storage.Options) {
3131
cmd.Flags().StringVar(&opts.ExtDir, "extensions-dir", "", "The path to extensions.")
3232
cmd.Flags().StringVar(&opts.Artifactory, "artifactory", "", "Artifactory server URL.")
3333
cmd.Flags().StringVar(&opts.Repo, "repo", "", "Artifactory repository.")
34-
cmd.Flags().DurationVar(&opts.ListCacheDuration, "list-cache-duration", time.Minute, "The duration of the extension cache.")
3534
cmd.Flags().StringArrayVar(&certificates, "certs", []string{}, "The path to certificates that match the signing key.")
3635
cmd.Flags().StringVar(&signingKeyFile, "key", "", "The path to signing key file in PEM format.")
3736
cmd.Flags().BoolVar(&opts.SaveSigZips, "save-sigs", false, "Save signed extensions to disk for debugging.")
3837
_ = cmd.Flags().MarkHidden("save-sigs")
39-
38+
4039
if cmd.Use == "server" {
4140
// Server only flags
4241
cmd.Flags().DurationVar(&opts.ListCacheDuration, "list-cache-duration", time.Minute, "The duration of the extension cache.")

Diff for: cli/signature.go

+133-60
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,22 @@
11
package cli
22

33
import (
4+
"context"
45
"crypto/x509"
56
"fmt"
67
"io"
78
"os"
9+
"os/exec"
10+
"path/filepath"
811
"strings"
912

1013
cms "github.com/github/smimesign/ietf-cms"
1114
"github.com/spf13/cobra"
1215
"golang.org/x/xerrors"
1316

1417
"cdr.dev/slog"
15-
"github.com/coder/code-marketplace/storage/easyzip"
16-
1718
"github.com/coder/code-marketplace/extensionsign"
18-
"github.com/coder/code-marketplace/extensionsign/verify"
19+
"github.com/coder/code-marketplace/storage/easyzip"
1920
)
2021

2122
func signature() *cobra.Command {
@@ -26,89 +27,172 @@ func signature() *cobra.Command {
2627
Aliases: []string{"sig", "sigs", "signatures"},
2728
}
2829

29-
cmd.AddCommand(compareSignatureSigZips(), verifyCmd(), decodeSigCmd())
30+
cmd.AddCommand(compareSignatureSigZips(), verifySig())
3031
return cmd
3132
}
3233

33-
func decodeSigCmd() *cobra.Command {
34+
func verifySig() *cobra.Command {
3435
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),
3939
RunE: func(cmd *cobra.Command, args []string) error {
4040
logger := cmdLogger(cmd)
4141
ctx := cmd.Context()
42-
logger.Info(ctx, fmt.Sprintf("Decoding %q", args[0]))
42+
extensionVsix := args[0]
43+
p7sFile := args[1]
4344

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))
4846

49-
signed, err := extensionsign.ExtractP7SSig(data)
47+
data, err := os.ReadFile(p7sFile)
5048
if err != nil {
51-
return xerrors.Errorf("extract p7s: %w", err)
49+
return xerrors.Errorf("read %q: %w", p7sFile, err)
5250
}
5351

54-
detachedDataR, err := easyzip.GetZipFileReader(data, ".signature.manifest")
52+
msg, err := easyzip.GetZipFileReader(data, ".signature.manifest")
5553
if err != nil {
5654
return xerrors.Errorf("get manifest: %w", err)
5755
}
58-
detachedData, err := io.ReadAll(detachedDataR)
56+
msgData, err := io.ReadAll(msg)
5957
if err != nil {
6058
return xerrors.Errorf("read manifest: %w", err)
6159
}
6260

63-
sd, err := cms.ParseSignedData(signed)
61+
signed, err := extensionsign.ExtractP7SSig(data)
6462
if err != nil {
65-
return xerrors.Errorf("new signed data: %w", err)
63+
return xerrors.Errorf("extract p7s: %w", err)
6664
}
6765

68-
fmt.Println("Detached:", sd.IsDetached())
69-
certs, err := sd.GetCertificates()
66+
fmt.Println("----------------Golang Verify----------------")
67+
valid, err := goVerify(ctx, logger, msgData, signed)
7068
if err != nil {
71-
return xerrors.Errorf("get certs: %w", err)
69+
logger.Error(ctx, "go verify", slog.Error(err))
7270
}
73-
fmt.Println("Certificates:", len(certs))
71+
logger.Info(ctx, fmt.Sprintf("Valid: %t", valid))
7472

75-
sdData, err := sd.GetData()
73+
fmt.Println("----------------OpenSSL Verify----------------")
74+
valid, err = openSSLVerify(ctx, logger, msgData, signed)
7675
if err != nil {
77-
return xerrors.Errorf("get data: %w", err)
76+
logger.Error(ctx, "openssl verify", slog.Error(err))
7877
}
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))
8379

84-
sys, err := x509.SystemCertPool()
80+
fmt.Println("----------------vsce-sign Verify----------------")
81+
valid, err = vsceSignVerify(ctx, logger, extensionVsix, p7sFile)
8582
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))
9184
}
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))
10586

10687
return nil
10788
},
10889
}
10990
return cmd
11091
}
11192

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+
112196
func dimensions(chain [][][]*x509.Certificate) string {
113197
var str strings.Builder
114198
for _, top := range chain {
@@ -123,17 +207,6 @@ func dimensions(chain [][][]*x509.Certificate) string {
123207
return str.String()
124208
}
125209

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-
137210
func compareSignatureSigZips() *cobra.Command {
138211
cmd := &cobra.Command{
139212
Use: "compare",

Diff for: extensionsign/algo.go

+82
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package extensionsign
2+
3+
import (
4+
"context"
5+
"crypto"
6+
"crypto/x509"
7+
"encoding/pem"
8+
"os"
9+
"os/exec"
10+
"path/filepath"
11+
12+
cms "github.com/github/smimesign/ietf-cms"
13+
"golang.org/x/xerrors"
14+
)
15+
16+
var SigningAlgorithm = OpenSSLSign
17+
18+
func CMSAlgo(data []byte, certs []*x509.Certificate, signer crypto.Signer) (result []byte, err error) {
19+
return cms.SignDetached(data, certs, signer)
20+
}
21+
22+
// openssl smime -sign -signer <cert> -inkey <key> -binary -in .signature.manifest -outform der -out openssl.p7s
23+
func OpenSSLSign(data []byte, certs []*x509.Certificate, signer crypto.Signer) (result []byte, err error) {
24+
tmpdir := os.TempDir()
25+
tmpdir = filepath.Join(tmpdir, "sign-sigs")
26+
defer os.RemoveAll(tmpdir)
27+
28+
err = os.MkdirAll(tmpdir, 0755)
29+
if err != nil {
30+
return nil, xerrors.Errorf("create temp dir: %w", err)
31+
}
32+
33+
certPath := filepath.Join(tmpdir, "certs.pem")
34+
certFile, err := os.OpenFile(certPath, os.O_CREATE|os.O_WRONLY, 0644)
35+
if err != nil {
36+
return nil, xerrors.Errorf("open cert file: %w", err)
37+
}
38+
39+
for _, cert := range certs {
40+
if len(cert.Raw) == 0 {
41+
return nil, xerrors.Errorf("empty certificate")
42+
}
43+
err = pem.Encode(certFile, &pem.Block{Type: "CERTIFICATE", Bytes: cert.Raw})
44+
if err != nil {
45+
return nil, err
46+
}
47+
}
48+
49+
keyPath := "/home/steven/go/src/github.com/coder/code-marketplace/extensionsign/testdata/key2.pem"
50+
//keyFile, err := os.Open(keyPath)
51+
//if err != nil {
52+
// return nil, err
53+
//}
54+
//pem.Encode(keyFile, &pem.Block{Type: "PRIVATE KEY", )
55+
56+
msgPath := filepath.Join(tmpdir, ".signature.manifest")
57+
messageFile, err := os.OpenFile(msgPath, os.O_CREATE|os.O_WRONLY, 0644)
58+
if err != nil {
59+
return nil, err
60+
}
61+
_, err = messageFile.Write(data)
62+
if err != nil {
63+
return nil, xerrors.Errorf("write message: %w", err)
64+
}
65+
66+
signed := filepath.Join(tmpdir, "openssl.p7s")
67+
cmd := exec.CommandContext(context.Background(), "openssl", "cms", "-sign",
68+
"-signer", certPath,
69+
"-inkey", keyPath,
70+
"-binary",
71+
"-in", msgPath,
72+
"-outform", "der",
73+
"-out", signed,
74+
)
75+
76+
err = cmd.Run()
77+
if err != nil {
78+
return nil, xerrors.Errorf("run openssl: %w", err)
79+
}
80+
81+
return os.ReadFile(signed)
82+
}

Diff for: extensionsign/sigzip.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
"encoding/json"
99
"io"
1010

11-
cms "github.com/github/smimesign/ietf-cms"
1211
"golang.org/x/xerrors"
1312

1413
"github.com/coder/code-marketplace/storage/easyzip"
@@ -61,7 +60,7 @@ func SignAndZipManifest(certs []*x509.Certificate, secret crypto.Signer, manifes
6160
}
6261

6362
// Signature file
64-
signature, err := cms.SignDetached(manifest, certs, secret)
63+
signature, err := SigningAlgorithm(manifest, certs, secret)
6564
if err != nil {
6665
return nil, xerrors.Errorf("sign: %w", err)
6766
}

Diff for: storage/signature.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ import (
99
"io/fs"
1010
"path/filepath"
1111

12-
cms "github.com/github/smimesign/ietf-cms"
1312
"github.com/spf13/afero/mem"
1413
"golang.org/x/xerrors"
1514

@@ -51,7 +50,7 @@ func NewSignatureStorage(logger slog.Logger, signer crypto.Signer, certs []*x509
5150
}
5251

5352
// Attempt to sign something to ensure certs/keys are correct and supported
54-
_, err := cms.SignDetached([]byte("testing configuration"), certs, signer)
53+
_, err := extensionsign.SigningAlgorithm([]byte("testing configuration"), certs, signer)
5554
if err != nil {
5655
return nil, xerrors.Errorf("extension signer: %w", err)
5756
}

0 commit comments

Comments
 (0)