aboutsummaryrefslogtreecommitdiff
path: root/doc/tips/Decrypting_files_in_special_remotes_without_git-annex.mdwn
diff options
context:
space:
mode:
authorGravatar wsha.code+ga@b38779424f41c5701bbe5937340be43ff1474b2d <wshacodega@web>2016-01-08 07:38:01 +0000
committerGravatar admin <admin@branchable.com>2016-01-08 07:38:01 +0000
commite233d4263a25181db86dc2e9726c60f98607fa84 (patch)
tree211185a4647ab5880846963b93c3ca76b2eed7f2 /doc/tips/Decrypting_files_in_special_remotes_without_git-annex.mdwn
parentc35db5ae689a3efb67d490ba33417b91e3b2b4f2 (diff)
Diffstat (limited to 'doc/tips/Decrypting_files_in_special_remotes_without_git-annex.mdwn')
-rw-r--r--doc/tips/Decrypting_files_in_special_remotes_without_git-annex.mdwn123
1 files changed, 123 insertions, 0 deletions
diff --git a/doc/tips/Decrypting_files_in_special_remotes_without_git-annex.mdwn b/doc/tips/Decrypting_files_in_special_remotes_without_git-annex.mdwn
new file mode 100644
index 000000000..3d2fd35a1
--- /dev/null
+++ b/doc/tips/Decrypting_files_in_special_remotes_without_git-annex.mdwn
@@ -0,0 +1,123 @@
+One of the selling points of `git-annex` is that it uses standard tools like `git` and `gpg` to deal with files, so that years from now it should be possible to explore and get useful data out of an old annex repository (this helps with [[future_proofing]]). If for whatever reason you need to decrypt files on [[special_remotes]] that use [[encryption]] without using `git-annex`, this can be done fairly easily using `gpg` (and `openssl` to compute the HMAC keys used to create the file names used on the special remote so you can look up the right file to decrypt). Here is an example script demonstrating how to compute the special remote file names and how to decrypt the special remote files.
+
+ #!/usr/bin/env bash
+
+ usage() {
+ echo "Usage: ga_decrypt.sh -r REMOTE [-k SYMLINK] [-d FILE]"
+ echo ""
+ echo " Either lookups up key on REMOTE for annex file linked with SYMLINK"
+ echo " or decrypts FILE encrypted for REMOTE."
+ echo ""
+ echo " -r: REMOTE is special remote to use"
+ echo " -k: SYMLINK is symlink in annex to print encrypted special remote key for"
+ echo " -d: FILE is path to special remote file to decrypt to STDOUT"
+ echo ""
+ echo "NOTES: "
+ echo " * Run in an indirect git annex repo."
+ echo " * Must specify -k or -d."
+ echo " * -k prints the key including the leading directory names used for a "
+ echo " directory remote (even if REMOTE is not a directory remote)"
+ echo " * -d works on a locally accessible file. It does not fetch a remote file"
+ echo " * Must have gpg and openssl"
+ }
+
+ decrypt_cipher() {
+ cipher="$1"
+ echo "$(echo -n "$cipher" | base64 -d | gpg --decrypt --quiet)"
+ }
+
+ lookup_key() {
+ encryption="$1"
+ cipher="$2"
+ symlink="$3"
+
+ if [ "$encryption" == "hybrid" ] || [ "$encryption" == "pubkey" ]; then
+ cipher="$(decrypt_cipher "$cipher")"
+ fi
+
+ # Pull out MAC cipher from beginning of cipher
+ if [ "$encryption" = "hybrid" ] ; then
+ cipher="$(echo -n "$cipher" | head -c 256 )"
+ elif [ "$encryption" = "shared" ] ; then
+ cipher="$(echo -n "$cipher" | base64 -d | tr -d '\n' | head -c 256 )"
+ elif [ "$encryption" = "pubkey" ] ; then
+ # pubkey cipher includes a trailing newline which was stripped in
+ # decrypt_cipher process substitution step above
+ IFS= read -rd '' cipher < <( printf "$cipher\n" )
+ fi
+
+ annex_key="$(basename "$(readlink "$symlink")")"
+ hash="$(echo -n "$annex_key" | openssl dgst -sha1 -hmac "$cipher" | sed 's/(stdin)= //')"
+ key="GPGHMACSHA1--$hash"
+ checksum="$(echo -n $key | md5sum)"
+ echo "${checksum:0:3}/${checksum:3:3}/$key"
+ }
+
+ decrypt_file() {
+ encryption="$1"
+ cipher="$2"
+ file_path="$3"
+
+ if [ "$encryption" = "pubkey" ] ; then
+ gpg --quiet --decrypt "${file_path}"
+ else
+ if [ "$encryption" = "hybrid" ] ; then
+ cipher="$(decrypt_cipher "$cipher" | tail -c +257)"
+ elif [ "$encryption" = "shared" ] ; then
+ cipher="$(echo -n "$cipher" | base64 -d | tr -d '\n' | tail -c +257 )"
+ fi
+ gpg --quiet --batch --passphrase "$cipher" --output - "${file_path}"
+ fi
+ }
+
+ main() {
+ OPTIND=1
+
+ mode=""
+ remote=""
+
+ while getopts "r:k:d:" opt; do
+ case "$opt" in
+ r) remote="$OPTARG"
+ ;;
+ k) if [ -z "$mode" ] ; then
+ mode="lookup key"
+ else
+ usage
+ exit 2
+ fi
+ symlink="$OPTARG"
+ ;;
+ d) if [ -z "$mode" ] ; then
+ mode="decrypt file"
+ else
+ usage
+ exit 2
+ fi
+ file_path="$OPTARG"
+ ;;
+ esac
+ done
+
+ if [ -z "$mode" ] || [ -z "$remote" ] ; then
+ usage
+ exit 2
+ fi
+
+ shift $((OPTIND-1))
+
+ # Pull out config for desired remote name
+ remote_config="$(git show git-annex:remote.log | grep 'name='"$remote ")"
+
+ # Get encryption type and cipher from config
+ encryption="$(echo "$remote_config" | grep -oP 'encryption\=.*? ' | tr -d ' \n' | sed 's/encryption=//')"
+ cipher="$(echo "$remote_config" | grep -oP 'cipher\=.*? ' | tr -d ' \n' | sed 's/cipher=//')"
+
+ if [ "$mode" = "lookup key" ] ; then
+ lookup_key "$encryption" "$cipher" "$symlink"
+ elif [ "$mode" = "decrypt file" ] ; then
+ decrypt_file "$encryption" "$cipher" "${file_path}"
+ fi
+ }
+
+ main "$@"