Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add SignKey gpg entity param to allow easier pgp signing of commits #1198

Merged
merged 12 commits into from
Jun 22, 2019
54 changes: 54 additions & 0 deletions github/git_commits.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,13 @@
package github

import (
"bytes"
"context"
"errors"
"fmt"
"time"

"golang.org/x/crypto/openpgp"
)

// SignatureVerification represents GPG signature verification.
Expand Down Expand Up @@ -37,6 +41,11 @@ type Commit struct {
// is only populated for requests that fetch GitHub data like
// Pulls.ListCommits, Repositories.ListCommits, etc.
CommentCount *int `json:"comment_count,omitempty"`

// SigningKey denotes a key to sign the commit with. If not nil this key will
// be used to sign the commit. The private key must be present and already
// decrypted. Ignored if Verification.Signature is defined.
SigningKey *openpgp.Entity `json:"-"`
}

func (c Commit) String() string {
Expand Down Expand Up @@ -116,6 +125,13 @@ func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string
if commit.Tree != nil {
body.Tree = commit.Tree.SHA
}
if commit.SigningKey != nil {
signature, err := createSignature(commit.SigningKey, body)
if err != nil {
return nil, nil, err
}
body.Signature = &signature
}
if commit.Verification != nil {
body.Signature = commit.Verification.Signature
}
Expand All @@ -133,3 +149,41 @@ func (s *GitService) CreateCommit(ctx context.Context, owner string, repo string

return c, resp, nil
}

func createSignature(SigningKey *openpgp.Entity, commit *createCommit) (string, error) {
if commit.Author == nil {
anandkumarpatel marked this conversation as resolved.
Show resolved Hide resolved
return "", errors.New("createSignature: commit.Author=nil")
}
message := createSignatureMessage(commit)

writer := new(bytes.Buffer)
reader := bytes.NewReader([]byte(message))
if err := openpgp.ArmoredDetachSign(writer, SigningKey, reader, nil); err != nil {
return "", err
}

return writer.String(), nil
}

func createSignatureMessage(commit *createCommit) string {
message := ""
anandkumarpatel marked this conversation as resolved.
Show resolved Hide resolved

if commit.Tree != nil {
message = fmt.Sprintf("tree %s\n", *commit.Tree)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use the getters... commit.GetTree().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are no getters defined for createCommit object

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, whups, my bad. Thanks, @anandkumarpatel.

}

for _, parent := range commit.Parents {
message += fmt.Sprintf("parent %s\n", parent)
}

message += fmt.Sprintf("author %s <%s> %d %s\n", commit.Author.GetName(), commit.Author.GetEmail(), commit.Author.GetDate().Unix(), commit.Author.GetDate().Format("-0700"))
committer := commit.Committer
if committer == nil {
committer = commit.Author
}
anandkumarpatel marked this conversation as resolved.
Show resolved Hide resolved

// There needs to be a double newline after committer
message += fmt.Sprintf("committer %s <%s> %d %s\n\n", committer.GetName(), committer.GetEmail(), committer.GetDate().Unix(), committer.GetDate().Format("-0700"))
message += fmt.Sprintf("%s", *commit.Message)
anandkumarpatel marked this conversation as resolved.
Show resolved Hide resolved
return message
}
Loading