Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
969a707487 |
+20
-4
@@ -172,11 +172,22 @@ func parseStatusLine(statusOutput, keyword string) ([]string, bool) {
|
|||||||
func gpgSign(
|
func gpgSign(
|
||||||
ctx context.Context, data []byte, keyID GPGKeyID,
|
ctx context.Context, data []byte, keyID GPGKeyID,
|
||||||
) ([]byte, string, error) {
|
) ([]byte, string, error) {
|
||||||
// The signature goes to stdout, so the status lines go to stderr.
|
tmpDir, err := os.MkdirTemp("", "mfer-gpg-sign-*")
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", fmt.Errorf("failed to create temp dir: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
defer func() { _ = os.RemoveAll(tmpDir) }()
|
||||||
|
|
||||||
|
sigFile := filepath.Join(tmpDir, "signature.asc")
|
||||||
|
|
||||||
|
// The signature goes to sigFile, so --status-fd 1 can send gpg's status
|
||||||
|
// lines to stdout; its messages go to stderr.
|
||||||
stdout, stderr, err := runGPG(ctx, bytes.NewReader(data),
|
stdout, stderr, err := runGPG(ctx, bytes.NewReader(data),
|
||||||
"--detach-sign",
|
"--detach-sign",
|
||||||
gpgOptArmor,
|
gpgOptArmor,
|
||||||
gpgOptStatusFD, "2",
|
"--output", sigFile,
|
||||||
|
gpgOptStatusFD, "1",
|
||||||
"--local-user", string(keyID),
|
"--local-user", string(keyID),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -185,12 +196,17 @@ func gpgSign(
|
|||||||
|
|
||||||
// The last argument of SIG_CREATED is the fingerprint of the key that
|
// The last argument of SIG_CREATED is the fingerprint of the key that
|
||||||
// made the signature.
|
// made the signature.
|
||||||
created, ok := parseStatusLine(stderr.String(), "SIG_CREATED")
|
created, ok := parseStatusLine(stdout.String(), "SIG_CREATED")
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, "", fmt.Errorf("%w: %s", errSigningKeyNotReported, stderr.String())
|
return nil, "", fmt.Errorf("%w: %s", errSigningKeyNotReported, stderr.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
return stdout.Bytes(), created[len(created)-1], nil
|
sig, err := os.ReadFile(sigFile) //nolint:gosec // G304: inside tmpDir, made above
|
||||||
|
if err != nil {
|
||||||
|
return nil, "", fmt.Errorf("failed to read signature: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return sig, created[len(created)-1], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// gpgExportPublicKey exports the public key for the specified key ID.
|
// gpgExportPublicKey exports the public key for the specified key ID.
|
||||||
|
|||||||
+4
-1
@@ -210,6 +210,8 @@ func TestGPGOptionLikeKeyIDIsNotAnOption(t *testing.T) {
|
|||||||
assert.NotContains(t, string(fpr), "gpg (GnuPG)")
|
assert.NotContains(t, string(fpr), "gpg (GnuPG)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestGPGSignInvalidKey signs with a key that has no secret key in the
|
||||||
|
// keyring. The error must hold gpg's messages and none of its status lines.
|
||||||
func TestGPGSignInvalidKey(t *testing.T) {
|
func TestGPGSignInvalidKey(t *testing.T) {
|
||||||
// Set up test environment (we need GNUPGHOME set)
|
// Set up test environment (we need GNUPGHOME set)
|
||||||
_, gpgHome := testGPGEnv(t)
|
_, gpgHome := testGPGEnv(t)
|
||||||
@@ -218,7 +220,8 @@ func TestGPGSignInvalidKey(t *testing.T) {
|
|||||||
data := []byte("test data")
|
data := []byte("test data")
|
||||||
_, _, err := gpgSign(context.Background(), data,
|
_, _, err := gpgSign(context.Background(), data,
|
||||||
GPGKeyID("NONEXISTENT_KEY_ID_12345"))
|
GPGKeyID("NONEXISTENT_KEY_ID_12345"))
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
|
assert.NotContains(t, err.Error(), gpgStatusPrefix)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestBuilderWithSigning(t *testing.T) {
|
func TestBuilderWithSigning(t *testing.T) {
|
||||||
|
|||||||
Reference in New Issue
Block a user