forked from
tangled.org/core
Monorepo for Tangled
1package commitverify
2
3import (
4 "log"
5
6 "tangled.org/core/appview/db"
7 "tangled.org/core/appview/models"
8 "tangled.org/core/crypto"
9 "tangled.org/core/types"
10)
11
12type verifiedCommit struct {
13 fingerprint string
14 hash string
15}
16
17type VerifiedCommits map[verifiedCommit]struct{}
18
19func (vcs VerifiedCommits) IsVerified(hash string) bool {
20 for vc := range vcs {
21 if vc.hash == hash {
22 return true
23 }
24 }
25 return false
26}
27
28func (vcs VerifiedCommits) Fingerprint(hash string) string {
29 for vc := range vcs {
30 if vc.hash == hash {
31 return vc.fingerprint
32 }
33 }
34 return ""
35}
36
37func GetVerifiedCommits(e db.Execer, emailToDid map[string]string, ndCommits []types.Commit) (VerifiedCommits, error) {
38 vcs := VerifiedCommits{}
39
40 didPubkeyCache := make(map[string][]models.PublicKey)
41
42 for _, commit := range ndCommits {
43 // skip unsigned commits early: no signature means no DB lookup needed,
44 // and most commits in a typical log are unsigned.
45 if commit.PGPSignature == "" {
46 continue
47 }
48
49 committerEmail := commit.Committer.Email
50 if did, exists := emailToDid[committerEmail]; exists {
51 // check if we've already fetched public keys for this did
52 pubKeys, ok := didPubkeyCache[did]
53 if !ok {
54 // fetch and cache public keys
55 keys, err := db.GetPublicKeysForDid(e, did)
56 if err != nil {
57 log.Printf("failed to fetch pubkey for %s: %v", committerEmail, err)
58 continue
59 }
60 pubKeys = keys
61 didPubkeyCache[did] = pubKeys
62 }
63
64 // try to verify with any associated pubkeys
65 payload := commit.Payload()
66 signature := commit.PGPSignature
67 for _, pk := range pubKeys {
68 if _, ok := crypto.VerifySignature([]byte(pk.Key), []byte(signature), []byte(payload)); ok {
69
70 fp, err := crypto.SSHFingerprint(pk.Key)
71 if err != nil {
72 log.Println("error computing ssh fingerprint:", err)
73 }
74
75 vc := verifiedCommit{fingerprint: fp, hash: commit.This}
76 vcs[vc] = struct{}{}
77 break
78 }
79 }
80
81 }
82 }
83
84 return vcs, nil
85}