forked from
tangled.org/core
Monorepo for Tangled — https://tangled.org
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 committerEmail := commit.Committer.Email
44 if did, exists := emailToDid[committerEmail]; exists {
45 // check if we've already fetched public keys for this did
46 pubKeys, ok := didPubkeyCache[did]
47 if !ok {
48 // fetch and cache public keys
49 keys, err := db.GetPublicKeysForDid(e, did)
50 if err != nil {
51 log.Printf("failed to fetch pubkey for %s: %v", committerEmail, err)
52 continue
53 }
54 pubKeys = keys
55 didPubkeyCache[did] = pubKeys
56 }
57
58 // try to verify with any associated pubkeys
59 payload := commit.Payload()
60 signature := commit.PGPSignature
61 for _, pk := range pubKeys {
62 if _, ok := crypto.VerifySignature([]byte(pk.Key), []byte(signature), []byte(payload)); ok {
63
64 fp, err := crypto.SSHFingerprint(pk.Key)
65 if err != nil {
66 log.Println("error computing ssh fingerprint:", err)
67 }
68
69 vc := verifiedCommit{fingerprint: fp, hash: commit.This}
70 vcs[vc] = struct{}{}
71 break
72 }
73 }
74
75 }
76 }
77
78 return vcs, nil
79}