···11+package commitverify
22+33+import (
44+ "fmt"
55+ "log"
66+77+ "github.com/go-git/go-git/v5/plumbing/object"
88+ "tangled.sh/tangled.sh/core/appview/db"
99+ "tangled.sh/tangled.sh/core/crypto"
1010+ "tangled.sh/tangled.sh/core/types"
1111+)
1212+1313+type verifiedCommit struct {
1414+ fingerprint string
1515+ hash string
1616+}
1717+1818+type VerifiedCommits map[verifiedCommit]struct{}
1919+2020+func (vcs VerifiedCommits) IsVerified(hash string) bool {
2121+ for vc := range vcs {
2222+ if vc.hash == hash {
2323+ return true
2424+ }
2525+ }
2626+ return false
2727+}
2828+2929+func (vcs VerifiedCommits) Fingerprint(hash string) string {
3030+ for vc := range vcs {
3131+ if vc.hash == hash {
3232+ return vc.fingerprint
3333+ }
3434+ }
3535+ return ""
3636+}
3737+3838+func GetVerifiedObjectCommits(e db.Execer, emailToDid map[string]string, commits []*object.Commit) (VerifiedCommits, error) {
3939+ ndCommits := []types.NiceDiff{}
4040+ for _, commit := range commits {
4141+ ndCommits = append(ndCommits, ObjectCommitToNiceDiff(commit))
4242+ }
4343+ return GetVerifiedCommits(e, emailToDid, ndCommits)
4444+}
4545+4646+func GetVerifiedCommits(e db.Execer, emailToDid map[string]string, ndCommits []types.NiceDiff) (VerifiedCommits, error) {
4747+ vcs := VerifiedCommits{}
4848+4949+ didPubkeyCache := make(map[string][]db.PublicKey)
5050+5151+ for _, commit := range ndCommits {
5252+ c := commit.Commit
5353+5454+ committerEmail := c.Committer.Email
5555+ if did, exists := emailToDid[committerEmail]; exists {
5656+ // check if we've already fetched public keys for this did
5757+ pubKeys, ok := didPubkeyCache[did]
5858+ if !ok {
5959+ // fetch and cache public keys
6060+ keys, err := db.GetPublicKeysForDid(e, did)
6161+ if err != nil {
6262+ log.Printf("failed to fetch pubkey for %s: %v", committerEmail, err)
6363+ continue
6464+ }
6565+ pubKeys = keys
6666+ didPubkeyCache[did] = pubKeys
6767+ }
6868+6969+ // try to verify with any associated pubkeys
7070+ for _, pk := range pubKeys {
7171+ if _, ok := crypto.VerifyCommitSignature(pk.Key, commit); ok {
7272+7373+ fp, err := crypto.SSHFingerprint(pk.Key)
7474+ if err != nil {
7575+ log.Println("error computing ssh fingerprint:", err)
7676+ }
7777+ fmt.Println(fp)
7878+7979+ vc := verifiedCommit{fingerprint: fp, hash: c.This}
8080+ vcs[vc] = struct{}{}
8181+ break
8282+ }
8383+ }
8484+8585+ }
8686+ }
8787+8888+ return vcs, nil
8989+}
9090+9191+// ObjectCommitToNiceDiff is a compatibility function to convert a
9292+// commit object into a NiceDiff structure.
9393+func ObjectCommitToNiceDiff(c *object.Commit) types.NiceDiff {
9494+ var niceDiff types.NiceDiff
9595+9696+ // set commit information
9797+ niceDiff.Commit.Message = c.Message
9898+ niceDiff.Commit.Author = c.Author
9999+ niceDiff.Commit.This = c.Hash.String()
100100+ niceDiff.Commit.Committer = c.Committer
101101+ niceDiff.Commit.Tree = c.TreeHash.String()
102102+ niceDiff.Commit.PGPSignature = c.PGPSignature
103103+104104+ changeId, ok := c.ExtraHeaders["change-id"]
105105+ if ok {
106106+ niceDiff.Commit.ChangedId = string(changeId)
107107+ }
108108+109109+ // set parent hash if available
110110+ if len(c.ParentHashes) > 0 {
111111+ niceDiff.Commit.Parent = c.ParentHashes[0].String()
112112+ }
113113+114114+ // XXX: Stats and Diff fields are typically populated
115115+ // after fetching the actual diff information, which isn't
116116+ // directly available in the commit object itself.
117117+118118+ return niceDiff
119119+}
-52
appview/repo/repo_util.go
···44 "context"
55 "crypto/rand"
66 "fmt"
77- "log"
87 "math/big"
98109 "github.com/go-git/go-git/v5/plumbing/object"
1111- "tangled.sh/tangled.sh/core/appview/db"
1212- "tangled.sh/tangled.sh/core/crypto"
1313- "tangled.sh/tangled.sh/core/types"
1410)
15111612func uniqueEmails(commits []*object.Commit) []string {
···8985 }
90869187 return emailToDidOrHandle
9292-}
9393-9494-func verifiedObjectCommits(r *Repo, emailToDid map[string]string, commits []*object.Commit) (map[string]bool, error) {
9595- ndCommits := []types.NiceDiff{}
9696- for _, commit := range commits {
9797- ndCommits = append(ndCommits, types.ObjectCommitToNiceDiff(commit))
9898- }
9999- return verifiedCommits(r, emailToDid, ndCommits)
100100-}
101101-102102-func verifiedCommits(r *Repo, emailToDid map[string]string, ndCommits []types.NiceDiff) (map[string]bool, error) {
103103- hashToVerified := make(map[string]bool)
104104-105105- didPubkeyCache := make(map[string][]db.PublicKey)
106106-107107- for _, commit := range ndCommits {
108108- c := commit.Commit
109109-110110- committerEmail := c.Committer.Email
111111- if did, exists := emailToDid[committerEmail]; exists {
112112- // check if we've already fetched public keys for this did
113113- pubKeys, ok := didPubkeyCache[did]
114114- if !ok {
115115- // fetch and cache public keys
116116- keys, err := db.GetPublicKeysForDid(r.db, did)
117117- if err != nil {
118118- log.Printf("failed to fetch pubkey for %s: %v", committerEmail, err)
119119- continue
120120- }
121121- pubKeys = keys
122122- didPubkeyCache[did] = pubKeys
123123- }
124124-125125- verified := false
126126-127127- // try to verify with any associated pubkeys
128128- for _, pk := range pubKeys {
129129- if _, ok := crypto.VerifyCommitSignature(pk.Key, commit); ok {
130130- verified = true
131131- break
132132- }
133133- }
134134-135135- hashToVerified[c.This] = verified
136136- }
137137- }
138138-139139- return hashToVerified, nil
14088}
1418914290func randomString(n int) string {
-30
types/diff.go
···77777878 return files
7979}
8080-8181-// ObjectCommitToNiceDiff is a compatibility function to convert a
8282-// commit object into a NiceDiff structure.
8383-func ObjectCommitToNiceDiff(c *object.Commit) NiceDiff {
8484- var niceDiff NiceDiff
8585-8686- // set commit information
8787- niceDiff.Commit.Message = c.Message
8888- niceDiff.Commit.Author = c.Author
8989- niceDiff.Commit.This = c.Hash.String()
9090- niceDiff.Commit.Committer = c.Committer
9191- niceDiff.Commit.Tree = c.TreeHash.String()
9292- niceDiff.Commit.PGPSignature = c.PGPSignature
9393-9494- changeId, ok := c.ExtraHeaders["change-id"]
9595- if ok {
9696- niceDiff.Commit.ChangedId = string(changeId)
9797- }
9898-9999- // set parent hash if available
100100- if len(c.ParentHashes) > 0 {
101101- niceDiff.Commit.Parent = c.ParentHashes[0].String()
102102- }
103103-104104- // XXX: Stats and Diff fields are typically populated
105105- // after fetching the actual diff information, which isn't
106106- // directly available in the commit object itself.
107107-108108- return niceDiff
109109-}