README

PGP Signing with GPG2
=====================

.. sectnum::
.. contents:: Table of Contents

This signer implements the Pretty Good Privacy signature format. It
accepts data on the `/sign/data` interface and returns armored
detached signatures like the `pgp` signer.

**Try the `pgp` signer first since it keeps private keys in memory,
 which is more secure.**

Only use the this signer if the `pgp` signer doesn't understand your
key format and you need to load private keys with passphrases exported
with the `unsupported and non-standard gnu-dummy S2K algorithm`_ and
sign with a subkey. Also prefer the `pgp` signer, since this signer 1)
requires a the gpg2 binary with version >2.1, 2) writes private keys
to keyrings on disk, and 3) shells out to the `gpg2` binary.

.. _`unsupported and non-standard gnu-dummy S2K algorithm`: https://github.com/golang/go/issues/13605


Example Usage:

.. code:: bash

    # request a signature using the autograph client
    $ go run client.go -d $(base64 /tmp/pgpinput.txt) -k pgpsubkey \
      -o /tmp/testsig.pgp -ko /tmp/testkey.asc

    # import the public key returned by autograph into a temp keyring
    $ gpg --no-default-keyring --keyring /tmp/testkeyring.pgp \
      --secret-keyring /tmp/testsecring.gpg --import /tmp/testkey.asc

    # verify the signature using the temp keyring
    $ gpg --no-default-keyring --keyring /tmp/testkeyring.pgp \
      --secret-keyring /tmp/testsecring.gpg \
      --verify /tmp/testsig.pgp /tmp/pgpinput.txt


Configuration
-------------

Add a signer to `autograph.yaml` with the following **required** fields

1. a PGP public key (e.g. a key exported with `gpg --armor --export $KEYID`)
2. a PGP private key (e.g. a subkey exported with `gpg --armor --export-secret-subkeys $SUBKEYID`)
3. a KeyID or fingerprint specifying which private key sign with (e.g. `$SUBKEYID` from the above export)
4. a passphrase to unlock the private key

For example:

.. code:: yaml

    signers:
    - id: some-pgp-key
      type: gpg2
      keyid: 0xE09F6B4F9E6FDCCB
      passphrase: abcdef123
      privatekey: |
        -----BEGIN PGP PRIVATE KEY BLOCK-----

        lQOYBFuW9xABCACzCLYHwgGba7hi+lwhD/Hr5qqpg+UuN+88NclYgLWyl1nPpx2D
        ...
        HQASoA7mirON
        =vJUu
        -----END PGP PRIVATE KEY BLOCK-----
      publickey: |
        -----BEGIN PGP PUBLIC KEY BLOCK-----
        ...
        =459B
        -----END PGP PUBLIC KEY BLOCK-----

Signature request
-----------------

This signer only supports the `/sign/data/` endpoint.

.. code:: json

    [
        {
            "input": "Y2FyaWJvdW1hdXJpY2UK",
            "keyid": "pgpsubkey"
        }
    ]

Signature response
------------------

The response to a data signing request contains a PGP armored detached
signature in its raw form with newlines preserved but wrapped on a single line
due to JSON marshalling. You can write it out to a file to recover the standard
armored signature that gnupg expects.

.. code:: json

    [
      {
        "ref": "7khgpu4gcfdv30w8joqxjy1cc",
        "type": "pgp",
        "signer_id": "some-pgp-key",
        "public_key":"-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nxsBNBFuW9xABCACzCLYHwg...",
        "signature":"-----BEGIN PGP SIGNATURE-----\n\nwsBcBAABCAAQBQJbt3KqCRDdCl2Z...."
      }
    ]
Expand ▾ Collapse ▴

Documentation

Index

Constants

View Source
const (
	// Type of this signer is "gpg2" represents a signer that
	// shells out to gpg2 to sign artifacts since the golang "pgp"
	// signer doesn't support signing with subkeys
	// https://godoc.org/golang.org/x/crypto/openpgp#ArmoredDetachSign
	// or loading keys exported with gnu-dummy s2k encrypted
	// passphrases https://github.com/golang/go/issues/13605
	Type = "gpg2"
)

Variables

This section is empty.

Functions

func Unmarshal

func Unmarshal(sigstr string) (signer.Signature, error)

    Unmarshal also does very little. It simply converts the armored signature from a string to an []byte, but doesn't attempt to parse it, and returns it as a Signature

    Types

    type GPG2Signer

    type GPG2Signer struct {
    	signer.Configuration
    
    	// KeyID is the fingerprint of the gpg key or subkey to use
    	// e.g. 0xA2B637F535A86009
    	KeyID string
    	// contains filtered or unexported fields
    }

      GPG2Signer holds the configuration of the signer

      func New

      func New(conf signer.Configuration) (s *GPG2Signer, err error)

        New initializes a pgp signer using a configuration

        func (*GPG2Signer) AtExit

        func (s *GPG2Signer) AtExit() error

          AtExit removes the temp dir containing the signer key and sec rings when the app is shut down gracefully

          func (*GPG2Signer) Config

          func (s *GPG2Signer) Config() signer.Configuration

            Config returns the configuration of the current signer

            func (*GPG2Signer) GetDefaultOptions

            func (s *GPG2Signer) GetDefaultOptions() interface{}

              GetDefaultOptions returns default options of the signer

              func (*GPG2Signer) SignData

              func (s *GPG2Signer) SignData(data []byte, options interface{}) (signer.Signature, error)

                SignData takes data and returns an armored signature with pgp header and footer

                type Options

                type Options struct {
                }

                  Options are not implemented for this signer

                  type Signature

                  type Signature struct {
                  	Data []byte
                  }

                    Signature is a PGP signature

                    func (*Signature) Marshal

                    func (sig *Signature) Marshal() (string, error)

                      Marshal doesn't do much for this signer. sig.Data already contains an armored signature, so we simply convert it to a string and return it

                      Source Files