git-secret/RFC/RFC001.md
2018-06-15 08:55:33 +01:00

6.4 KiB

RFC 0001 - A stable and forwards compatible public key storage format

Feature Name: Stable public key storage

Status: Final

Type: Enhancement

Related components: Core

Start Date: 2018-06-14

Author: Simon Massey

GitHub issues:

  • #136 GnuPG2 2.2 vs 2.1 conflicts in keybox format

Summary

A new internal public key storage format that avoids forwards compatibility issues between GPG releases. This proposal will keep forwards compatibility with older versions of git-secret.

Motivation

GPG maintains backwards compatibility but not forwards compatibility. Running a new GPG version can and will upgrade the keyring storage files in a way that is not recognised by older versions of GPG. This is not normally a problem for typical GPG usage. Users will upgrade and rarely downgrade. It is a problem for git-secret as the keyring storage is committed to git and shared between users. Someone using an older version of GPG can no longer open the upgraded keyring file.

Approach

git-secret will move away from using the keyring format as shared storage of public keys. Instead, it will store public keys as exported keys in ASCII armor format. The public key export format is stable and forwards compatible. GPG users will typically be running different GPG or PGP versions and are able to exchange keys successfully. Bugs that effect git-secret's ability to use exported public keys will likey affect typical GPG key exchange usage. Such bugs are likely to be caught and fixed by the wider opensource community.

git-secret may need to store and process meta-data about keys to make it efficient to work with keys that are stored within individual files. It will use the machine-readable "colon listings format" for this purpose.

It is anticipated that bash and gawk will be sufficient to work efficiently with the new file formats.

Design

The new storage format will be implimented as follows:

  1. Keys will be stored in ~/.gitsecret/keys in gpg --armor --export format. The use of ASCII armour rather than binary format is to make debugging of key related issues easier. The filename of the key will be <keyid>.pub.gpg (using Field 5 the "64-bit keyid" of the colon listings format)
  2. Key meta data will be stored alongside the key file in the gpg --keyid-format long --with-colons format. The file name will be <keyid>.pub.cln
  3. A folder ~/.gitsecret/cache will be added to .gitignore. At this location, a public keyring will be maintained on a per user bases and won't be shared between users. This is simply a "keyring cache" of the keys used to encrypt files.

git-secret-tell will:

  1. Scan the set of *.pub.cln files to find all currently told identities. If the given identity is in the list do nothing.
  2. If the given identity isn't listed run gpg --armor --export against the users $HOME keyring to create the <key-id>.pub.gpg.
  3. Run --keyid-format long --with-colons of the exported key to create the <key-id>.pub.cln.

Note that the additional steps to ensure that older versions of git-secret know about the newly told identity will be outlined below.

git-secret-hide will:

  1. Extract the list of "64-bit keyid"s who are told from the *.pub.cln files. Note that multiple identities can be listed against each key.
  2. Checked this against the list of "64-bit keyid"s in the "keyring cache" at ~/.gitsecret/cache.
  3. Import any missing keys into the "keyring cache". It is anticipated that gawk will be sufficient to perform this calculation.
  4. Run the current logic using the "keyring cache".

Note that the additional steps to ensure that older versions of git-secret know about the newly told user will be outlined below.

git-secret-whoknows will:

  1. The list of identities will be loaded by parsing the .pub.cln files. Note that multiple identities can be listed against each key.

git-secret-usage will:

  1. Document the git-secret-migrate command discussed in the next section.

git-secret-reveal will:

  • Be unchanged.

git-secret-remove will:

  • Be unchanged.

git-secret-list will:

  • Be unchanged.

git-secret-killperson will:

  1. Remove the key from the keyring cache.
  2. Delete both <key-id>.pub.gpg and <key-id>.pub.cln files.

git-secret-init will:

  1. Add ~/.gitsecret/cache into .gitignore.
  2. Run any current logic using the ignored "keyring cache".

git-secret-clean will:

  • Be unchanged.

git-secret-changes will:

  1. Show differences the <key-id>.pub.gpg and <key-id>.pub.cln files in ~/.gitsecret/keys.

git-secret-add will:

  • Be unchanged.

A new command git-secret-migrate will:

  1. Create the folder ~/.gitsecret/cache and add it to the .gitignore file.
  2. Extract all keys from the old keyring generating <key-id>.pub.gpg and <key-id>.pub.cln files in ~/.gitsecret/keys

Version Compatibility

Backwards compatibility will the old keyring storage approach will be maintained as follows:

  1. For each changed command a guard will be added that checks for the existance of .gitsecret/cache.
  2. If the folder exists it proceeds as normal.
  3. If it does not exist it will report that the repo was initialised by an older version of git-secret and tell the user to run git-secret-migrate

Forwards compatibility with older versions of git-secret will be maintained as follows.

git-secret-hide will:

  1. Have a guard that will check for the existence of the old keyring. If it exists it will check it for any new public keys and extract them into the new format prior to running.

git-secret-tell will:

  1. Will check for the existence of the old keyring. If it exists it will load the new public key into it.

git-secret-killperson

  1. Will check for the existence of the old keyring. If it exists it will delete the user from it.

Drawbacks

To maintain forward compatibility the approach requires the existing logic to kept working for a period of time. We can give a deprecated warning if the forwards compatibility logic is running. The warning can be suppressed using a command-line flag.

Alternatives

What other designs have been considered? Unknown.

What is the impact of not doing this? Team members are locked out of secrets when only one other team member upgrades GPG. This can go undetected until the victims needs the secrets in a hurry for production support. Bad things then happen.

Unresolved questions

What parts of the design are still to be done? None.