git-cipher is a utility script for encrypting sensitive files for storage in a
public Git repo.
git cipher encrypt [FILES...] # encrypts files git cipher decrypt [FILES...] # decrypts files git cipher log [FILES...] # shows log with (plaintext) diffs git cipher help
git clone https://github.com/wincent/git-cipher.git
Alternatively, you can install the Gem:
gem install git-cipher
Note: If you install the
git-cipher executable somewhere in your
Git will treat it as a subcommand, which means you can invoke it as
git cipher. Otherwise, you will have to provide the full path to the
To install the external prerequisites, use your preferred method. For example, on OS X you might choose to use Homebrew:
brew install git gnupg gpg-agent
Selecting a key for encryption and decryption
There are three ways to override the default signing key (which is
email@example.com and probably not useful to anybody other than me):
1. Set the
GPG_USER environment variable
GPG_USERfirstname.lastname@example.org git cipher decrypt # or alternatively: export GPG_USERemail@example.com git cipher decrypt
git-config to set
git config cipher.gpguser firstname.lastname@example.org # per-repo git config --global cipher.gpguser email@example.com # globally
DEFAULT_GPG_USER in the
This last may be appropriate if you've installed by cloning the Git repo.
This section describes the background and rationale for the design of
git-cipher was originally developed within the context of an
Ansible-powered configuration repo. Some
of the files contained sensitive information so I couldn't commit them to the
repo as plaintext, but I did still want to version control them, so needed to
encrypt them prior to committing.
At the time (prior to version 1.5) Ansible didn't have the Vault feature
(equivalent to Chef's encrypted data bags), so the
git-cipher was developed.
When the Vault feature did arrive, I decided to continue using
because I liked the convenience of being able to work using my normal editor and
Ansible workflow (Vault requires you to edit files through the
command, and pass special arguments to
ansible-playbook when running
git-cipher stores encrypted versions of sensitive files in the Git repo with
.encrypted file extension. Before running Ansible commands, we decrypt the
necessary files with
git cipher decrypt. This works well because Ansible
doesn't employ a client-server architecture like Chef or Puppet; it suffices to
have the decrypted files available on the local machine where the repo is
checked out and the commands are run.
The plain-text versions of the encrypted files should be ignored via the
gitignore mechanism (although that is only a recommendation and
does nothing to enforce the policy, beyond printing a warning when it sees that
the plaintext version of an encrypted file is not being ignored).
This approach compares to using
git encrypt as recommended in "An
example of provisioning and deployment with
There are a couple of problems with that approach; one is that it uses
encryption" in the name of
convenience, while noting that it is insecure. Additionally, a lengthy thread
on the Git mailing
list argues that
this is an abuse of the clean/smudge filtering system.
We use semantically secure GPG encryption and make use of timestamp
comparisons to avoid unnecessary churn (in other words, we only update the
encrypted version of a file if the plain text version is newer). Note that we
effectively trust the local system's integrity, relying on filesystem
encryption, filesystem permissions, and the general security of the system to
keep the plain-text safe. Also note that, like the clean/smudge filtering, we
are effectively forgoing some of the niceties that Git offers (compression,
meaningful diffs etc) in exchange for security. (But note: you can also split
your encrypted content across smaller individual files and then pull the values
from those files into a template, preserving the ability to get meaningful diffs
of the template files themselves. The
log subcommand also goes some way
towards providing visualization of change over time in encrypted files.)
git-cipher can be obtained as a RubyGem, the executable itself is,
by-design, a single file. This is to reduce the dependency footprint, making it
more suitable for use in boot-strapped environments (which might not have
RubyGems installed yet).
You may see prompts like the following, depending on the trust level of your signing key:
It is NOT certain that the key belongs to the person named in the user ID. If you *really* know what you are doing, you may answer the next question with yes.
You can avoid these prompts by setting the trust level to "ultimate" like this:
gpg --edit-key firstname.lastname@example.org # or $GPG_USER > trust > quit
git-cipher was hacked together by Greg Hurrell (email@example.com).
This is minimal, currently with no tests, no Bundler, no Rakefile. To cut a new release, update the version number in the gemspec and:
git tag -s 0.2 -m "0.2 release" git push --follow-tags origin master gem build git-cipher.gemspec gem push git-cipher-0.2.gem
git-cipher is licensed under the MIT license. See the
LICENSE.txt file in
git-cipher repo for more details.