+119
appview/commitverify/verify.go
+119
appview/commitverify/verify.go
···
1
+
package commitverify
2
+
3
+
import (
4
+
"fmt"
5
+
"log"
6
+
7
+
"github.com/go-git/go-git/v5/plumbing/object"
8
+
"tangled.sh/tangled.sh/core/appview/db"
9
+
"tangled.sh/tangled.sh/core/crypto"
10
+
"tangled.sh/tangled.sh/core/types"
11
+
)
12
+
13
+
type verifiedCommit struct {
14
+
fingerprint string
15
+
hash string
16
+
}
17
+
18
+
type VerifiedCommits map[verifiedCommit]struct{}
19
+
20
+
func (vcs VerifiedCommits) IsVerified(hash string) bool {
21
+
for vc := range vcs {
22
+
if vc.hash == hash {
23
+
return true
24
+
}
25
+
}
26
+
return false
27
+
}
28
+
29
+
func (vcs VerifiedCommits) Fingerprint(hash string) string {
30
+
for vc := range vcs {
31
+
if vc.hash == hash {
32
+
return vc.fingerprint
33
+
}
34
+
}
35
+
return ""
36
+
}
37
+
38
+
func GetVerifiedObjectCommits(e db.Execer, emailToDid map[string]string, commits []*object.Commit) (VerifiedCommits, error) {
39
+
ndCommits := []types.NiceDiff{}
40
+
for _, commit := range commits {
41
+
ndCommits = append(ndCommits, ObjectCommitToNiceDiff(commit))
42
+
}
43
+
return GetVerifiedCommits(e, emailToDid, ndCommits)
44
+
}
45
+
46
+
func GetVerifiedCommits(e db.Execer, emailToDid map[string]string, ndCommits []types.NiceDiff) (VerifiedCommits, error) {
47
+
vcs := VerifiedCommits{}
48
+
49
+
didPubkeyCache := make(map[string][]db.PublicKey)
50
+
51
+
for _, commit := range ndCommits {
52
+
c := commit.Commit
53
+
54
+
committerEmail := c.Committer.Email
55
+
if did, exists := emailToDid[committerEmail]; exists {
56
+
// check if we've already fetched public keys for this did
57
+
pubKeys, ok := didPubkeyCache[did]
58
+
if !ok {
59
+
// fetch and cache public keys
60
+
keys, err := db.GetPublicKeysForDid(e, did)
61
+
if err != nil {
62
+
log.Printf("failed to fetch pubkey for %s: %v", committerEmail, err)
63
+
continue
64
+
}
65
+
pubKeys = keys
66
+
didPubkeyCache[did] = pubKeys
67
+
}
68
+
69
+
// try to verify with any associated pubkeys
70
+
for _, pk := range pubKeys {
71
+
if _, ok := crypto.VerifyCommitSignature(pk.Key, commit); ok {
72
+
73
+
fp, err := crypto.SSHFingerprint(pk.Key)
74
+
if err != nil {
75
+
log.Println("error computing ssh fingerprint:", err)
76
+
}
77
+
fmt.Println(fp)
78
+
79
+
vc := verifiedCommit{fingerprint: fp, hash: c.This}
80
+
vcs[vc] = struct{}{}
81
+
break
82
+
}
83
+
}
84
+
85
+
}
86
+
}
87
+
88
+
return vcs, nil
89
+
}
90
+
91
+
// ObjectCommitToNiceDiff is a compatibility function to convert a
92
+
// commit object into a NiceDiff structure.
93
+
func ObjectCommitToNiceDiff(c *object.Commit) types.NiceDiff {
94
+
var niceDiff types.NiceDiff
95
+
96
+
// set commit information
97
+
niceDiff.Commit.Message = c.Message
98
+
niceDiff.Commit.Author = c.Author
99
+
niceDiff.Commit.This = c.Hash.String()
100
+
niceDiff.Commit.Committer = c.Committer
101
+
niceDiff.Commit.Tree = c.TreeHash.String()
102
+
niceDiff.Commit.PGPSignature = c.PGPSignature
103
+
104
+
changeId, ok := c.ExtraHeaders["change-id"]
105
+
if ok {
106
+
niceDiff.Commit.ChangedId = string(changeId)
107
+
}
108
+
109
+
// set parent hash if available
110
+
if len(c.ParentHashes) > 0 {
111
+
niceDiff.Commit.Parent = c.ParentHashes[0].String()
112
+
}
113
+
114
+
// XXX: Stats and Diff fields are typically populated
115
+
// after fetching the actual diff information, which isn't
116
+
// directly available in the commit object itself.
117
+
118
+
return niceDiff
119
+
}
-52
appview/repo/repo_util.go
-52
appview/repo/repo_util.go
···
4
4
"context"
5
5
"crypto/rand"
6
6
"fmt"
7
-
"log"
8
7
"math/big"
9
8
10
9
"github.com/go-git/go-git/v5/plumbing/object"
11
-
"tangled.sh/tangled.sh/core/appview/db"
12
-
"tangled.sh/tangled.sh/core/crypto"
13
-
"tangled.sh/tangled.sh/core/types"
14
10
)
15
11
16
12
func uniqueEmails(commits []*object.Commit) []string {
···
89
85
}
90
86
91
87
return emailToDidOrHandle
92
-
}
93
-
94
-
func verifiedObjectCommits(r *Repo, emailToDid map[string]string, commits []*object.Commit) (map[string]bool, error) {
95
-
ndCommits := []types.NiceDiff{}
96
-
for _, commit := range commits {
97
-
ndCommits = append(ndCommits, types.ObjectCommitToNiceDiff(commit))
98
-
}
99
-
return verifiedCommits(r, emailToDid, ndCommits)
100
-
}
101
-
102
-
func verifiedCommits(r *Repo, emailToDid map[string]string, ndCommits []types.NiceDiff) (map[string]bool, error) {
103
-
hashToVerified := make(map[string]bool)
104
-
105
-
didPubkeyCache := make(map[string][]db.PublicKey)
106
-
107
-
for _, commit := range ndCommits {
108
-
c := commit.Commit
109
-
110
-
committerEmail := c.Committer.Email
111
-
if did, exists := emailToDid[committerEmail]; exists {
112
-
// check if we've already fetched public keys for this did
113
-
pubKeys, ok := didPubkeyCache[did]
114
-
if !ok {
115
-
// fetch and cache public keys
116
-
keys, err := db.GetPublicKeysForDid(r.db, did)
117
-
if err != nil {
118
-
log.Printf("failed to fetch pubkey for %s: %v", committerEmail, err)
119
-
continue
120
-
}
121
-
pubKeys = keys
122
-
didPubkeyCache[did] = pubKeys
123
-
}
124
-
125
-
verified := false
126
-
127
-
// try to verify with any associated pubkeys
128
-
for _, pk := range pubKeys {
129
-
if _, ok := crypto.VerifyCommitSignature(pk.Key, commit); ok {
130
-
verified = true
131
-
break
132
-
}
133
-
}
134
-
135
-
hashToVerified[c.This] = verified
136
-
}
137
-
}
138
-
139
-
return hashToVerified, nil
140
88
}
141
89
142
90
func randomString(n int) string {
-30
types/diff.go
-30
types/diff.go
···
77
77
78
78
return files
79
79
}
80
-
81
-
// ObjectCommitToNiceDiff is a compatibility function to convert a
82
-
// commit object into a NiceDiff structure.
83
-
func ObjectCommitToNiceDiff(c *object.Commit) NiceDiff {
84
-
var niceDiff NiceDiff
85
-
86
-
// set commit information
87
-
niceDiff.Commit.Message = c.Message
88
-
niceDiff.Commit.Author = c.Author
89
-
niceDiff.Commit.This = c.Hash.String()
90
-
niceDiff.Commit.Committer = c.Committer
91
-
niceDiff.Commit.Tree = c.TreeHash.String()
92
-
niceDiff.Commit.PGPSignature = c.PGPSignature
93
-
94
-
changeId, ok := c.ExtraHeaders["change-id"]
95
-
if ok {
96
-
niceDiff.Commit.ChangedId = string(changeId)
97
-
}
98
-
99
-
// set parent hash if available
100
-
if len(c.ParentHashes) > 0 {
101
-
niceDiff.Commit.Parent = c.ParentHashes[0].String()
102
-
}
103
-
104
-
// XXX: Stats and Diff fields are typically populated
105
-
// after fetching the actual diff information, which isn't
106
-
// directly available in the commit object itself.
107
-
108
-
return niceDiff
109
-
}