If multiple GPG keys exist that could be used to decrypt the repository
key, but GPG fails on one of them (e.g., the first one because it is
stored on a SmartCard that is not plugged in), then no other keys are
used to try to decrypt it, failing entirely instead of trying the
additional GPG keys.
Modified-by: Andrew Ayer <agwa@andrewayer.name>
* Make exception variable const
* Make whitespace conform to project conventions
Signed-off-by: Andrew Ayer <agwa@andrewayer.name>
Closes: #88
Previously, lock/unlock needed to spawn a separate `git check-attr`
process for every single file in the repository (whether encrypted
or not). This was extremely inefficient, especially on Windows.
Now, git-crypt spawns a single `git check-attr` process and communicates
with it over stdin. In a repository with thousands of files, this
results in a speedup of nearly 100x.
This relies on the --stdin and -z options to `git check-attr`, which
were only added in Git 1.8.5 (released 27 Nov 2013). With older versions
of Git, git-crypt falls back to the old and slower code.
This will be useful as we start to gate code on the version of Git that's installed.
A lot of code out in the wild seems to assume that the output of `git version`
is "git version $VERSION", so I'm assuming it's safe for git-crypt to rely
on that too.
If this option is specified, then the GPG users are added even
if their keys are not trusted by GPG.
In addition, if a full fingerprint, prefixed by 0x, is specified,
it is assumed to be trusted, regardless of its trust level in the
GPG trustdb.
Non-files (symlinks and gitlinks (used by sub-modules)) cannot be
encrypted, so we shouldn't try messing with them. This fixes `git-crypt
status` when used on a repository with sub-modules or symlinks when the
path to the sub-module or symlink has the git-crypt attribute (which
can happen inadvertently when using wildcards in .gitattributes).
It will force a lock even if working directory is unclean. Useful
for deconfiguring git-crypt if you've accidentally unlocked with the
wrong key or gotten into a similarly sticky situation.
This will let us run 'git lock' even if no filters are configured.
This logic is more complicated than I would like because running
'git config --remove-section' on a non-existent section results in
a noisy error (with text printed to stderr and an exit code of 128)
instead of a quiet error like the other 'git config' commands.
Starting with Git 2.2.2, `git checkout -f HEAD` no longer checks out
files if their mtimes haven't changed. This causes files to remain
encrypted in the work tree after running `git-crypt unlock`, and to
remain decrypted after running `git-crypt lock`'.
To fix this, git-crypt now figures out what files are encrypted (by
checking `git check-attr` on every file output by `git ls-files`),
touches those files, and then runs `git checkout` on them.
Previously, if you had a .gitattributes file in the root of your
repository that matched `*`, the files under .git-crypt would also be
encrypted, rendering the repository un-decryptable, unless you explicitly
excluded the .git-crypt directory, which was easy to overlook.
Now, `git-crypt add-gpg-user` automatically adds a .gitattributes file
to the .git-crypt directory to prevent its encryption.
IMPORTANT: If you are currently using GPG mode to encrypt an entire
repository, it is strongly advised that you upgrade git-crypt and then
do the following to ensure that the files inside .git-crypt are stored
properly:
1. Remove existing key files: `rm .git-crypt/keys/*/0/*`
2. Re-add GPG user(s): `git-crypt add-gpg-user GPG_USER_ID ...`
While writing the documention, I found that "GPG user" was less confusing
terminology than "GPG key," since you aren't really adding a "key"
to git-crypt, and git-crypt already uses "key" to refer to other concepts
(cf. the -k/--key-name options).
This does the reverse of what git-crypt unlock does:
- unconfigures the git filters
- forcibly checks out HEAD version
Usage:
git crypt lock locks repo using the "default" key
git crypt lock -k NAME locks the repo, using unlocked key named NAME
git crypt lock --key-name=NAME
git crypt lock -a locks the repo, removing ALL unlocked keys
git crypt lock --all
Result is that you can now decrypt and then revert back to encrypted
form of files and vice versa.
Modified-by: Andrew Ayer <agwa@andrewayer.name>
* Make argv argument to lock() const.
* Minor whitespace/style fixes to conform to project conventions.
Signed-off-by: Andrew Ayer <agwa@andrewayer.name>
Since Git consults the checked-out .gitattributes instead of the
.gitattributes in effect at the time the file was committed, Git
may invoke the smudge filter on old versions of a file that were
committed without encryption.
Git-crypt's position has always been that authentication is best left
to Git, since 1) Git provides immutable history based on SHA-1 hashes
as well as GPG-signed commits and tags, and 2) git-crypt can't be used
safely anyways unless the overall integrity of your repository is assured.
But, since git-crypt already has easy access to a (truncated) HMAC of the
file when decrypting, there's really no reason why git-crypt shouldn't
just verify it and provide an additional layer of protection.
Storing the key name in the key file makes it unnecessary to pass the
--key-name option to git-crypt unlock.
This breaks compatibility with post-revamp keys. On the plus side,
keys are now extensible so in the future it will be easier to make
changes to the format without breaking compatibility.
This will help distinguish keys encrypted with GPG from keys encrypted by
other means. (For example, a future version of git-crypt might support
passphrase-encrypted keys.)