Hacker News new | past | comments | ask | show | jobs | submit login
Storing sensitive data in a git repository using git-crypt (twinbit.it)
38 points by paolomainardi on Apr 1, 2014 | hide | past | web | favorite | 24 comments



After 4 months of usage, I don't recommend using git-crypt.

The main issue is that because transforms between the encrypted and decrypted state are transparent, it's very easy to commit files in clear that should have been encrypted. The .gitattributes patterns are not always obvious. Also .gitattibutes doesn't support encrypting the whole repo because it's lacking the negating parameter that allow you to encrypt everything except the .gitattribute file.

The second issue is that a lot of times I ended up having my repo in an inconsistent state. Some times, especially during rebases, something would go wrong and encrypted files would get marked as dirty even if they haven't changed. Running `git checkout` on these files would not work to put them back in a consistent state. I would have to remove the git-crypt config in .git/config and reset the repo to fix the issue. Some times the file didn't decrypt properly, although thing might have been an issue between the combination of git and git-crypt versions.

So in short, git-crypt is an awesome idea but I think is at the wrong level of abstraction. It relies on feature that haven't really been designed for security.

EDIT: To be a bit more constructive: the first issue could be mitigated by adding a `git-crypt check <path>` that tells you if a file is encrypted or not behind the scene.


Thanks for your feedback. It's true that there are still edge cases where the repo can get in an inconsistent state. This is the biggest issue I need to address before the 1.0 release. I should be able to provide commands that will fix up the repo if this happens. And thanks for pointing me in the direction of rebases - I clearly haven't done enough testing with them.

As for security, .gitattributes actually does have negation capability (see the article for an example) so you can encrypt the whole repo by default and explicitly whitelist files to not be encrypted. But I must emphasize that if you are encrypting most or all of the files in your repo, git-crypt is not the best tool because as you point out, git filters haven't really been designed for this. Where git-crypt really shines is where most of your repo is public, but you have a few files (perhaps private keys named *.key, or a file with API credentials) which you need to encrypt. I do like your suggestion of a command to check if a file is being encrypted, and plan to implement that.


I had to go back to the man pages. I think I got stuck at the "Unlike .gitignore, negative patterns are forbidden." and missed that you could unset attributes instead :)

In the process I also found `git check-attr` that goes 90% of the way of the `git crypt check` idea. Eg: `git check-attr -a -- path/to/file` will output git-crypt if the file is encrypted. A `git crypt ls` that lists all the encrypted files could be useful too to give more visibility.


> In the process I also found `git check-attr` that goes 90% of the way of the `git crypt check` idea. Eg: `git check-attr -a -- path/to/file` will output git-crypt if the file is encrypted. A `git crypt ls` that lists all the encrypted files could be useful too to give more visibility.

That's extremely useful - thanks for passing on that info!


> Where git-crypt really shines is where most of your repo is public, but you have a few files (perhaps private keys named *.key, or a file with API credentials) which you need to encrypt.

Awesome, this is just my use case. I had been not sure if this was actually the use case you were focusing on -- I'd suggest maybe including that exact above sentence in the README, so potential users can understand what you are intending the tool for.


git-crypt author here. This is a nice article on git-crypt.

There's a major new feature in the pipeline for git-crypt: GPG support. You'll be able to easily grant access to collaborators (or to yourself, on a different device) by running `git-crypt add-collab GPGKEYID`. There will no longer be a need to schlep a symmetric key file around.

GPG support is currently on a feature branch and undergoing testing. See https://github.com/AGWA/git-crypt/issues/3 if you're interested.


author here, thanks for the project, for the gpg based feature branch and for liking the article!


Another similar project that aims to do the same thing: https://github.com/elasticdog/transcrypt

The readme contains an itemized comparison, though it sounds some of this actual comparison may be out of date or more specific to git-encrypt (yet another project) git-crypt does appear to use openssl libraries for example.

transcrypt is just a Bash script and does not require compilation

transcrypt uses OpenSSL's symmetric cipher routines rather then implementing its own crypto

transcrypt does not have to remain installed after the initial repository configuration

transcrypt generates a unique salt for each encrypted file

transcrypt uses safety checks to avoid clobbering or duplicating configuration data

transcrypt facilitates setting up additional clones as well as rekeying

transcrypt adds an alias git ls-crypt to list all encrypted files


Cool, thanks for pointing me towards transcrypt - I hadn't heard of it until now. You are correct: git-crypt does use the OpenSSL libraries; we do not roll our own crypto.

I'm happy to see transcrypt didn't make the most common crypto mistake that Git crypto projects made, which is to use a block cipher in ECB mode or CBC mode with a fixed IV. That said, I don't think it's a good idea to implement this with shell scripts. While shell scripts are extremely convenient, it's very hard to write them securely. For example, in one place transcrypt leaks your passphrase as an argument to an openssl command, meaning there's an instant where another user could see it in the output of `ps`.


I use gitcrypt to keep sensitive configuration data out of git history, while still being able to diff, log, merge etc those files. It works well for that.

Note, gitcrypt uses symmetric encryption and stores the shared key in your gitconfig. It would be nice to use gpg instead for git's "smudge" and "clean" filters, but I can't for the life of me get a sane gpg-agent forwarding setup going, which renders that idea pretty useless.

Anyone have suggestions there?


git-crypt author here. GPG support will be the upcoming release (see my other comment). It's actually not as simple as just putting gpg in the smudge and clean filters, since gpg's non-deterministic encryption confuses git.

Afraid I can't help with your gpg-agent forwarding. The few times I've needed to do that I had to proxy the GPG agent connection via socat and through ssh port forwarding, which is not very sane (but might be improved with a few well-designed scripts).


GPG support will be the upcoming release (see my other comment).

Saw that -- awesome. I rolled something similar where gitcrypt.salt and gitcrypt.pass were stored in a gpg-encrypted file. After cloning, you decrypt once with gpg, then un-smudge all the encrypted files. No more gpg after that.

How does your solution differ? Is the shared gitcrypt.pass gone entirely? Do I potentially need access to a gpg keyring every time I checkout, diff, log, etc?

The few times I've needed to do that I had to proxy the GPG agent connection via socat and through ssh port forwarding, which is not very sane.

Yeah, it's too messy for me. My question was, if ssh-agent can be forwarded, why can't gpg-agent be forwarded? Boy was that a rabbit hole.

It seems the ssh-agent forwarding protocol is specific enough that it couldn't be used for gpg-agent.

Also, while gpg-agent can apparently stand in for ssh-agent when it comes to ssh keys, ssh-agent can't stand in for gpg-agent with gpg keys.

Furthermore, I got the sense that the gpg folks don't even want gpg-agent forwarding either -- too insecure for them.


> Saw that -- awesome. I rolled something similar where gitcrypt.salt and gitcrypt.pass were stored in a gpg-encrypted file. After cloning, you decrypt once with gpg, then un-smudge all the encrypted files. No more gpg after that.

That's essentially how the GPG feature works.

git-crypt doesn't use anything called "gitcrypt.salt" or "gitcrypt.pass" though - you might be confusing git-crypt with another project. (I may very well end up renaming git-crypt - it's a way too generic name.)


That's essentially how the GPG feature works.

Cool. I think that's the way to go. If you needed GPG for things beyond the initial checkout, automated git deploys (among other things) would be out of the question.

You might be confusing git-crypt with another project.

Oh, wow, you're right. I'm using a forked version of something called git-encrypt: https://github.com/shadowhand/git-encrypt

This is just a shell script (no compiled code), started about a year before your git-crypt, but interestingly the design is very similar. Both of you are using smudge and clean filters with AES 256.


I evaluated git-crypt for a previous venture and ended up using gitolite hooks instead. The setup I built stored users PGP Key ID, associated the Key ID with their gitolite account and used hooks to encrypt content for users with permission to the repo. A system account was created with a corresponding keypair to handle user add/mod/del by decrypting and re-encrypting content for the appropriate users in a given repo.

The beauty of this setup was, it was all over SSH and all keys used to access, sign and encrypt content (included the system user) were stored on smart cards.

If security is important, it's wise to take steps that align with or exceed your risk appetite.


Also check out git-remote-gcrypt for fully encrypted remotes.

https://github.com/blake2-ppc/git-remote-gcrypt


I wrote something which allows storing encrypted files in a Git repository.

The main difference is instead of encrypting a full file it uses a template mechanism to encrypt just values. I wrote a quick start which covers it further. I've been meaning to write a blog post which further explains the use case with more details. Anyway, check it out here:

https://github.com/jyap808/jaeger


I use and recommend git-crypt. It's great when you need to version sensitive files but don't want to give everyone access to them.


A question I've had for a while: Is the nature of the cryptography in git-crypt such that I could feel secure storing a few encrypted files including passwords in a git with public access, such as a public github?


Yes, I believe git-crypt is secure for that use case (as long as you keep your git-crypt key secure, of course). Although I'm not a professional cryptographer, I've taken Coursera's crypto course, have read Cryptography Engineering, and keep myself informed of the various pitfalls and attacks on crypto.

On the theory side, git-crypt uses AES in CTR mode with a nonce derived from the HMAC of the file. This is provably secure against an attack model called deterministic chosen-plaintext attack. In this regard, git-crypt is more secure than many similar projects (such as git-encrypt), which use AES in ECB mode or CBC mode with a fixed IV. These systems leak information and are not secure against deterministic chosen-plaintext attacks.

On the implementation side, git-crypt uses OpenSSL's crypto functions and the crypto code is extremely simple - pretty much a textbook example of how to properly do AES in CTR mode.

If anyone's curious, here's the code where AES-CTR is implemented: https://github.com/AGWA/git-crypt/blob/master/crypto.cpp#L76

And here is where it calculates the nonce (and also checks to make sure the counter value won't be overflowed): https://github.com/AGWA/git-crypt/blob/master/commands.cpp#L...


yea been wondering about this as well.. basically usage in general.

i've been thinking its a cheap-skate way to get private repos for free on github... XD but really the ideal use case would be to be able to keep passwords & sensitive info in the repo but have it make it to production without having to manually re-config.

i'm assuming if you put the key on your webserver it would be able to do this? also assuming you are on a service where you can actually access the filesystem outside your repo

(o and the reason this relates to your comment being.... would be nice to have it pass through github on way to prod. then it could be a nice dev+github+AWS kindof deploy process)


Yep, my use case is basically the same as yours.

I'm not just trying to score a free private repo, I actually want to share my app code with others open source who would like to view it -- even though the app itself is customized for our context, I don't mind letting people see it.

If you deploy your app with capistrano or similar automation, there are various ways to handle deploy. Not neccesarily any need to access any file systems, if you are deploying to heroku for instance, you might just need your deploy tool to set heroku config/env variables.

Anyhow, as far as whether git-crypt is really designed for this use case, I'm encouraged by a comment from the author here in this thread: "Where git-crypt really shines is where most of your repo is public, but you have a few files (perhaps private keys named *.key, or a file with API credentials) which you need to encrypt." Where most of your repo is actually public, yep, but just a file or two with credentials etc that need to be encrypted, yep! Okay, sweet.


Does git-crypt require a hook script of any kind on the server side ?


If you use bare repositories, no.




Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact

Search: