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.
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.
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!
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.
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.
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
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`.
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?
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).
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.
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.)
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.
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.
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:
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...
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)
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.