AGWA / git-crypt

Transparent file encryption in git
https://www.agwa.name/projects/git-crypt/
GNU General Public License v3.0
8.33k stars 479 forks source link

What's the directory structure? #82

Closed christianbundy closed 8 years ago

christianbundy commented 8 years ago

I'm hoping to understand the way that git-crypt does paths a bit better. For example: .git-crypt/keys/default/0/DEADBEEF.gpg.

What do default and 0 mean? Could the keys directory be removed? Any time I see a few otherwise-empty directories stacked it sets off red flags in my mind, so I figured I'd ask. Thanks for your work on this!

AGWA commented 8 years ago

default is the key name corresponding to the --key-name command line option. 0 is the key version. The version is always 0 at the moment but in the future will be used to support key rollover.

If you remove the keys directory then you won't be able to unlock the repository with GPG anymore. If you don't like git-crypt creating files in your repository then you can export a symmetric key file with git-crypt export-key, but you'll be responsible for storing it securely and won't be able to use git-crypt's built-in GPG support.

christianbundy commented 8 years ago

I'd love to be able to have a single GPG-encrypted file for multiple recipients rather than having one file for each person, and store each version of the key in the encrypted file. For example:

.git-crypt
├── default.gpg
└── deploy.gpg

The contents of these files would be a concatenated list of each key version, and the entire file would be encrypted for each recipient.

Even better, .git-crypt would just be a single ASCII-armored file in the root project directory, but really any improvement on the .git-crypt/keys/default/0/DEAFBEEF.gpg pattern would be very appreciated. :~)

AGWA commented 8 years ago

Not all users will have access to all key versions, so at a minimum you need a different file for each version. I considered using multiple recipients instead of writing a separate file for each user, but the problem with this approach is that to add a new user you'd need to know the public key for all existing users, not just the public key of the user you're adding. That would be a usability nightmare. In theory, the PGP file format allows you to add a recipient without knowing the current recipients' public keys, but gpg doesn't expose this and writing a PGP implementation did not seem like a good use of time.

I'm curious why you think the current layout is in such desperate need of improvement?

christianbundy commented 8 years ago

I'm not sure that I understand why a user who has access to default-1 wouldn't have access to default-0, but that would be an easy fix. Instead of a file like this:

enc(default-0, default-1)
enc(deploy-0, deploy-1)

You would have something like this:

enc(default-0)
enc(default-1)
enc(deploy-0)
enc(deploy-1)

You may also get the public key for all existing users with gpg --list-only --no-default-keyring --secret-keyring /dev/null, but I'm not sure whether that gives the full pubkey or just a short identifier.

Don't get me wrong, I don't think it's desperate at all. The reason I bring this up is that almost every other integration I've used (pre-processors, post-processors, continuous integration, deployment managers, package managers, etc.) have only used one file, so having multiple directories and a handful of binary files (especially with such long names) with feels particularly heavy.

AGWA commented 8 years ago

That command doesn't provide the full public key. The encrypted file doesn't store the full public key of every recipient.

Anyways, a lot of thought went into designing a scheme that would satisfy git-crypt's requirements, and this is what I came up with. Any alternative would need to satisfy the same requirements and be substantially better to justify breaking backwards compatibility.

As for using the filesystem to express structure instead of monolithic files, I find that to be more Unix-like and in the spirit of Git itself - just take a look inside any .git directory :-)