// SPDX-FileCopyrightText: 2025 Romain Maneschi // // SPDX-License-Identifier: EUPL-1.2 package user import ( "maps" "slices" "github.com/42wim/sshsig" "github.com/go-git/go-git/v6/plumbing" "github.com/go-git/go-git/v6/plumbing/object" ) const ( namespace = "git" ) func IsValidSignCommit(groups []Group, com *object.Commit) (bool, string, error) { if com.Signature == "" { return false, "", nil } keys := findCryptoKeysByEmail(groups, com.Committer.Email) if len(keys) == 0 { return false, "", nil } encoded := &plumbing.MemoryObject{} com.EncodeWithoutSignature(encoded) r, err := encoded.Reader() if err != nil { return false, "", err } defer r.Close() for _, key := range keys { if err := sshsig.Verify(r, []byte(com.Signature), []byte(key), namespace); err == nil { return true, key, nil } else if _, err := com.Verify(key); err == nil { // TODO not optimal because verify encodeWithoutSignature for each return true, key, nil } } return false, "", nil } func findCryptoKeysByEmail(groups []Group, email string) []string { keys := make(map[string]any, 0) for _, group := range groups { for _, u := range group.Users { if slices.Contains(u.Emails, email) { for _, k := range u.Ssh { keys[k] = 1 } } } } return slices.Collect(maps.Keys(keys)) }