Skip to content

Commit 014738c

Browse files
committed
feat: use internal OpenPGP implementation
1 parent eafb30c commit 014738c

File tree

4 files changed

+121
-35
lines changed

4 files changed

+121
-35
lines changed

go.mod

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ go 1.23.3
44

55
require (
66
github.com/alecthomas/kong v1.4.0
7+
golang.org/x/crypto v0.9.0
78
golang.org/x/mod v0.22.0
89
pault.ag/go/debian v0.17.0
910
)
@@ -12,6 +13,5 @@ require (
1213
github.com/kjk/lzma v0.0.0-20161016003348-3fd93898850d // indirect
1314
github.com/klauspost/compress v1.16.5 // indirect
1415
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
15-
golang.org/x/crypto v0.9.0 // indirect
1616
pault.ag/go/topsort v0.1.1 // indirect
1717
)

internal/publish/pgp.go

+81
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package publish
2+
3+
import (
4+
"crypto"
5+
"encoding/hex"
6+
"fmt"
7+
"io"
8+
9+
_ "crypto/sha256"
10+
11+
_ "golang.org/x/crypto/ripemd160"
12+
13+
"golang.org/x/crypto/openpgp"
14+
"golang.org/x/crypto/openpgp/clearsign"
15+
"golang.org/x/crypto/openpgp/packet"
16+
)
17+
18+
type signer struct {
19+
keys []*packet.PrivateKey
20+
}
21+
22+
func newSigner(keychain io.Reader) (*signer, error) {
23+
pr := packet.NewReader(keychain)
24+
s := &signer{}
25+
for {
26+
pkt, err := pr.Next()
27+
if err == io.EOF {
28+
break
29+
}
30+
if err != nil {
31+
return nil, err
32+
}
33+
switch key := pkt.(type) {
34+
case *packet.PrivateKey:
35+
if !key.IsSubkey && key.PublicKey.PublicKey != nil {
36+
fmt.Println("private", hex.EncodeToString(key.PublicKey.Fingerprint[:]), key.IsSubkey)
37+
s.keys = append(s.keys, key)
38+
}
39+
}
40+
}
41+
return s, nil
42+
}
43+
44+
type seekable interface {
45+
io.Reader
46+
io.Seeker
47+
}
48+
49+
func (s *signer) DetachSign(in seekable, out io.Writer) error {
50+
if len(s.keys) == 0 {
51+
return fmt.Errorf("no private keys found")
52+
}
53+
cfg := &packet.Config{
54+
DefaultHash: crypto.SHA256,
55+
}
56+
for _, key := range s.keys {
57+
if _, err := in.Seek(0, io.SeekStart); err != nil {
58+
return err
59+
}
60+
signer := &openpgp.Entity{PrivateKey: key}
61+
if err := openpgp.DetachSign(out, signer, in, cfg); err != nil {
62+
return err
63+
}
64+
}
65+
return nil
66+
}
67+
68+
func (s *signer) ClearSign(in seekable, out io.Writer) error {
69+
if len(s.keys) == 0 {
70+
return fmt.Errorf("no private keys found")
71+
}
72+
73+
w, err := clearsign.EncodeMulti(out, s.keys, nil)
74+
if err != nil {
75+
return err
76+
}
77+
if _, err := io.Copy(w, in); err != nil {
78+
return err
79+
}
80+
return w.Close()
81+
}

internal/publish/publish.go

+12-6
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package publish
22

33
import (
44
"fmt"
5+
"os"
56
"path/filepath"
67
)
78

@@ -13,11 +14,6 @@ type CLI struct {
1314
}
1415

1516
func (c *CLI) Run() error {
16-
keyring, err := filepath.Abs(c.Keyring)
17-
if err != nil {
18-
return fmt.Errorf("publish: %w", err)
19-
}
20-
2117
pkgs, err := scanPackages(c.Dists)
2218
if err != nil {
2319
return fmt.Errorf("publish: %w", err)
@@ -33,11 +29,21 @@ func (c *CLI) Run() error {
3329
return fmt.Errorf("publish: globbing: %w", err)
3430
}
3531

32+
fd, err := os.Open(c.Keyring)
33+
if err != nil {
34+
return fmt.Errorf("publish: %w", err)
35+
}
36+
sign, err := newSigner(fd)
37+
fd.Close()
38+
if err != nil {
39+
return fmt.Errorf("publish: %w", err)
40+
}
41+
3642
for _, dist := range dists {
3743
if err := writeRelease(dist); err != nil {
3844
return fmt.Errorf("publish: %w", err)
3945
}
40-
if err := signRelease(dist, keyring, c.SignUser); err != nil {
46+
if err := signRelease(dist, sign); err != nil {
4147
return fmt.Errorf("publish: %w", err)
4248
}
4349
}

internal/publish/release.go

+27-28
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,9 @@ package publish
22

33
import (
44
"compress/gzip"
5-
"fmt"
65
"io"
76
"log/slog"
87
"os"
9-
"os/exec"
108
"path/filepath"
119
"slices"
1210
"strings"
@@ -145,43 +143,44 @@ func writeRelease(dist string) error {
145143
return nil
146144
}
147145

148-
func signRelease(dist, keyring string, users []string) error {
149-
opts := []string{
150-
"-o", filepath.Join(dist, "InRelease"),
151-
"--yes",
152-
"--no-default-keyring",
153-
"--keyring", keyring,
146+
func signRelease(dist string, s *signer) error {
147+
in, err := os.Open(filepath.Join(dist, "Release"))
148+
if err != nil {
149+
return err
154150
}
155-
for _, user := range users {
156-
opts = append(opts, "-u", user)
151+
defer in.Close()
152+
153+
out, err := os.Create(filepath.Join(dist, "Release.gpg"))
154+
if err != nil {
155+
return err
157156
}
158-
opts = append(opts, "--clear-sign", filepath.Join(dist, "Release"))
159-
if bs, err := exec.Command("gpg", opts...).CombinedOutput(); err != nil {
160-
return fmt.Errorf("Failed to sign release: %s", bs)
157+
if err := s.DetachSign(in, out); err != nil {
158+
return err
161159
}
162-
if err := compress(filepath.Join(dist, "InRelease")); err != nil {
160+
if err := out.Close(); err != nil {
163161
return err
164162
}
165-
166-
opts = []string{
167-
"-o", filepath.Join(dist, "Release.gpg"),
168-
"-a",
169-
"--yes",
170-
"--no-default-keyring",
171-
"--keyring", keyring,
163+
if err := compress(out.Name()); err != nil {
164+
return err
172165
}
173-
for _, user := range users {
174-
opts = append(opts, "-u", user)
166+
167+
if _, err := in.Seek(0, io.SeekStart); err != nil {
168+
return err
175169
}
176-
opts = append(opts, "--detach-sign", filepath.Join(dist, "Release"))
177170

178-
if bs, err := exec.Command("gpg", opts...).CombinedOutput(); err != nil {
179-
return fmt.Errorf("Failed to sign release: %s", bs)
171+
out, err = os.Create(filepath.Join(dist, "InRelease"))
172+
if err != nil {
173+
return err
180174
}
181-
if err := compress(filepath.Join(dist, "Release.gpg")); err != nil {
175+
if err := s.ClearSign(in, out); err != nil {
176+
return err
177+
}
178+
if err := out.Close(); err != nil {
179+
return err
180+
}
181+
if err := compress(out.Name()); err != nil {
182182
return err
183183
}
184-
185184
return nil
186185
}
187186

0 commit comments

Comments
 (0)