Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
# Dependency directories (remove the comment below to include it)
# vendor/

build/
/build/
bin/
testbin/
92 changes: 70 additions & 22 deletions git/git.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,12 @@ limitations under the License.
package git

import (
"bytes"
"errors"
"fmt"
"strings"
"time"

"github.com/ProtonMail/go-crypto/openpgp"
"github.com/fluxcd/pkg/git/signature"
)

const (
Expand Down Expand Up @@ -113,19 +112,37 @@ func (c *Commit) AbsoluteReference() string {
return c.Hash.Digest()
}

// Deprecated: Verify is deprecated, use VerifySSH or VerifyGPG
// wrapper function to ensure backwards compatibility
func (c *Commit) Verify(keyRings ...string) (string, error) {
return c.VerifyGPG(keyRings...)
}

// Verify the Signature of the commit with the given key rings.
// It returns the fingerprint of the key the signature was verified
// with, or an error. It does not verify the signature of the referencing
// tag (if present). Users are expected to explicitly verify the referencing
// tag's signature using `c.ReferencingTag.Verify()`
func (c *Commit) Verify(keyRings ...string) (string, error) {
fingerprint, err := verifySignature(c.Signature, c.Encoded, keyRings...)
func (c *Commit) VerifyGPG(keyRings ...string) (string, error) {
fingerprint, err := signature.VerifyPGPSignature(c.Signature, c.Encoded, keyRings...)
if err != nil {
return "", fmt.Errorf("unable to verify Git commit: %w", err)
}
return fingerprint, nil
}

// VerifySSH verifies the SSH signature of the commit with the given authorized keys.
// It returns the fingerprint of the key the signature was verified with, or an error.
// It does not verify the signature of the referencing tag (if present). Users are
// expected to explicitly verify the referencing tag's signature using `c.ReferencingTag.VerifySSH()`
func (c *Commit) VerifySSH(authorizedKeys ...string) (string, error) {
Comment thread
bb-Ricardo marked this conversation as resolved.
fingerprint, err := signature.VerifySSHSignature(c.Signature, c.Encoded, authorizedKeys...)
if err != nil {
return "", fmt.Errorf("unable to verify Git commit SSH signature: %w", err)
}
return fingerprint, nil
}

// ShortMessage returns the first 50 characters of a commit subject.
func (c *Commit) ShortMessage() string {
subject := strings.Split(c.Message, "\n")[0]
Expand All @@ -152,17 +169,33 @@ type Tag struct {
Message string
}

// Deprecated: Verify is deprecated, use VerifySSH or VerifyGPG
// wrapper function to ensure backwards compatibility
func (t *Tag) Verify(keyRings ...string) (string, error) {
return t.VerifyGPG(keyRings...)
}

// Verify the Signature of the tag with the given key rings.
// It returns the fingerprint of the key the signature was verified
// with, or an error.
func (t *Tag) Verify(keyRings ...string) (string, error) {
fingerprint, err := verifySignature(t.Signature, t.Encoded, keyRings...)
func (t *Tag) VerifyGPG(keyRings ...string) (string, error) {
fingerprint, err := signature.VerifyPGPSignature(t.Signature, t.Encoded, keyRings...)
if err != nil {
return "", fmt.Errorf("unable to verify Git tag: %w", err)
}
return fingerprint, nil
}

// VerifySSH verifies the SSH signature of the tag with the given authorized keys.
// It returns the fingerprint of the key the signature was verified with, or an error.
func (t *Tag) VerifySSH(authorizedKeys ...string) (string, error) {
fingerprint, err := signature.VerifySSHSignature(t.Signature, t.Encoded, authorizedKeys...)
if err != nil {
return "", fmt.Errorf("unable to verify Git tag SSH signature: %w", err)
}
return fingerprint, nil
}

// String returns a short string representation of the tag in the format
// of <name@hash>, for eg: "1.0.0@a0c14dc8580a23f79bc654faa79c4f62b46c2c22"
// If the tag is lightweight, it won't have a hash, so it'll simply return
Expand Down Expand Up @@ -210,21 +243,36 @@ func IsSignedTag(t Tag) bool {
return t.Signature != ""
}

func verifySignature(sig string, payload []byte, keyRings ...string) (string, error) {
if sig == "" {
return "", fmt.Errorf("unable to verify payload as the provided signature is empty")
}
// IsPGPSigned returns true if the commit has a PGP signature.
func (c *Commit) IsPGPSigned() bool {
return signature.IsPGPSignature(c.Signature)
}

for _, r := range keyRings {
reader := strings.NewReader(r)
keyring, err := openpgp.ReadArmoredKeyRing(reader)
if err != nil {
return "", fmt.Errorf("unable to read armored key ring: %w", err)
}
signer, err := openpgp.CheckArmoredDetachedSignature(keyring, bytes.NewBuffer(payload), bytes.NewBufferString(sig), nil)
if err == nil {
return signer.PrimaryKey.KeyIdString(), nil
}
}
return "", fmt.Errorf("unable to verify payload with any of the given key rings")
// IsSSHSigned returns true if the commit has an SSH signature.
func (c *Commit) IsSSHSigned() bool {
return signature.IsSSHSignature(c.Signature)
}

// SignatureType returns the type of the commit signature as a string.
// It returns "openpgp" for PGP signatures, "ssh" for SSH signatures,
// and "unknown" for unrecognized or empty signatures.
func (c *Commit) SignatureType() string {
return signature.GetSignatureType(c.Signature)
}

// IsPGPSigned returns true if the tag has a PGP signature.
func (t *Tag) IsPGPSigned() bool {
return signature.IsPGPSignature(t.Signature)
}

// IsSSHSigned returns true if the tag has an SSH signature.
func (t *Tag) IsSSHSigned() bool {
return signature.IsSSHSignature(t.Signature)
}

// SignatureType returns the type of the tag signature as a string.
// It returns "openpgp" for PGP signatures, "ssh" for SSH signatures,
// and "unknown" for unrecognized or empty signatures.
func (t *Tag) SignatureType() string {
return signature.GetSignatureType(t.Signature)
}
Loading