carlos / platform Public

Clone
git clone https://amadan.net/carlos/platform

Plain git — no account needed to clone.

Download

Download this file

1package publicrelease
2
3import (
4 "crypto/ed25519"
5 "encoding/base64"
6 "errors"
7 "regexp"
8 "strings"
9)
10
11// ErrSums is every way a checksum list can fail VerifySums.
12var ErrSums = errors.New("publicrelease: signed checksum list refused")
13
14var sumLine = regexp.MustCompile(`^([0-9a-f]{64}) (\S+)$`)
15
16// VerifySums checks a release's SHA256SUMS.txt against its .sig with pubKey
17// (base64 ed25519, over the raw sums bytes, as Feed.Sums checks it) and
18// returns asset name to sha256. Unlike Feed.Sums it is strict, because its
19// caller signs what it returns into deployment authority: every line must be
20// sha256sum's text form, "<64 lowercase hex> <name>", each name once, and a
21// list with no lines is refused. It reads nothing from the network.
22func VerifySums(pubKey string, sums []byte, sig string) (map[string]string, error) {
23 pub, err := base64.StdEncoding.DecodeString(pubKey)
24 if err != nil || len(pub) != ed25519.PublicKeySize {
25 return nil, ErrSums
26 }
27 raw, err := base64.StdEncoding.DecodeString(strings.TrimSpace(sig))
28 if err != nil || len(raw) != ed25519.SignatureSize || !ed25519.Verify(ed25519.PublicKey(pub), sums, raw) {
29 return nil, ErrSums
30 }
31 text := string(sums)
32 if !strings.HasSuffix(text, "\n") {
33 return nil, ErrSums
34 }
35 out := map[string]string{}
36 for _, line := range strings.Split(strings.TrimSuffix(text, "\n"), "\n") {
37 m := sumLine.FindStringSubmatch(line)
38 if m == nil {
39 return nil, ErrSums
40 }
41 if _, dup := out[m[2]]; dup {
42 return nil, ErrSums
43 }
44 out[m[2]] = m[1]
45 }
46 return out, nil
47}
48