From f9902f8989f105c3838e9918b34bb3a44c174052 Mon Sep 17 00:00:00 2001 From: Peter Cai Date: Mon, 10 Oct 2022 16:08:44 -0400 Subject: [PATCH] Support an extra symmetric passphrase for protecting the crypt subtree This can help protect against gpg vulnerabilities (e.g. quantum computing) and/or leakage. --- gocrypt.bash | 71 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 67 insertions(+), 4 deletions(-) diff --git a/gocrypt.bash b/gocrypt.bash index 4a98efc..37cf4ae 100755 --- a/gocrypt.bash +++ b/gocrypt.bash @@ -5,9 +5,11 @@ readonly gocrypt_dir=".gocrypt" readonly gocrypt_dec_dir="gocrypt" readonly gocrypt_passwd_file="gocrypt-passwd" +readonly gocrypt_needs_passphrase_marker=".gocrypt-needs-passphrase" gocrypt_sys_check() { which gocryptfs > /dev/null || gocrypt_die "gocryptfs not found in PATH" + which perl > /dev/null || gocrypt_die "perl not found in PATH" } gocrypt_env_check() { @@ -30,21 +32,59 @@ gocrypt_die() { exit 1 } +gocrypt_derive_password() { + local data="$1" + local key="$2" + + perl <<< "use Digest::SHA qw(hmac_sha256_hex);\$digest=hmac_sha256_hex(\"$data\n\", \"$key\");print(\$digest);" +} + gocrypt_init() { + local needs_passphrase=false + local passphrase="" + while [ $# -gt 0 ]; do + case "$1" in + -p|--passphrase) + needs_passphrase=true + ;; + *) + gocrypt_die "Unexpected argument: $1" + ;; + esac + shift + done + [ $# -eq 0 ] || gocrypt_die "Unexpected argument" gocrypt_sys_check if [ -d "$gocrypt_dir" ] || [ -f "$gocrypt_dir" ]; then gocrypt_die "gocrypt plugin already initialized for your password store" fi + if $needs_passphrase; then + echo -n "Enter passphrase: " + read -s passphrase + local passphrase_confirm="" + echo + echo -n "Confirm passphrase: " + read -s passphrase_confirm + echo + + [ "$passphrase" == "$passphrase_confirm" ] || gocrypt_die "Passphrase mismatch" + fi + cmd_generate "$gocrypt_passwd_file" 32 + local gocrypt_passwd="$(cmd_show "$gocrypt_passwd_file")" # Initialize gocryptfs mkdir "$gocrypt_dir" - gocryptfs -passfile /dev/stdin -init "$gocrypt_dir" <<< "$(cmd_show "$gocrypt_passwd_file")" + if $needs_passphrase; then + touch "$gocrypt_needs_passphrase_marker" + gocrypt_passwd="$(gocrypt_derive_password "$gocrypt_passwd" "$passphrase")" + fi + gocryptfs -passfile /dev/stdin -init "$gocrypt_dir" <<< "$gocrypt_passwd" || gocrypt_die "Unable to initialize gocryptfs" # Mount the gocryptfs subdirectory and initialze what is inside of it - gocrypt_open + _gocrypt_passwd="$gocrypt_passwd" gocrypt_open || gocrypt_die "Cannot open the gocryptfs we just initialized" touch "$gocrypt_dec_dir"/.pass-gocrypt # By default, we use the same gpg-id inside, but the user can decide to use a different one later by doing it manually ln -s ../.gpg-id "$gocrypt_dec_dir"/.gpg-id @@ -55,6 +95,7 @@ gocrypt_init() { echo "gocrypt" >> .gitignore cmd_git add .gitignore + $needs_passphrase && cmd_git add "$gocrypt_needs_passphrase_marker" cmd_git add "$gocrypt_dir" cmd_git commit -m "Initialized encrypted storage for gocrypt plugin" } @@ -64,7 +105,22 @@ gocrypt_open() { gocrypt_close_check mkdir -p "$gocrypt_dec_dir" - gocryptfs -passfile /dev/stdin "$gocrypt_dir" "$gocrypt_dec_dir" <<< "$(cmd_show "$gocrypt_passwd_file")" + local gocrypt_passwd="" + + if [ ! -z "$_gocrypt_passwd" ]; then + gocrypt_passwd="$_gocrypt_passwd" + else + gocrypt_passwd="$(cmd_show "$gocrypt_passwd_file")" + + if [ -f "$gocrypt_needs_passphrase_marker" ]; then + local passphrase="" + echo -n "Enter passphrase: " + read -s passphrase + gocrypt_passwd="$(gocrypt_derive_password "$gocrypt_passwd" "$passphrase")" + fi + fi + + gocryptfs -passfile /dev/stdin "$gocrypt_dir" "$gocrypt_dec_dir" <<< "$gocrypt_passwd" } gocrypt_close() { @@ -96,7 +152,7 @@ gocrypt_help() { $PROGRAM gocrypt - hide part of the password store in a subdirectory encrypted with gocryptfs usage - $PROGRAM gocrypt init + $PROGRAM gocrypt init [-p|--passphrase] Initialize a encrypted subdirectory at \$PASSWORD_STORE_DIR/$gocrypt_dir. The password used by gocryptfs will be generated by pass and stored at \$PASSWORD_STORE_DIR/$gocrypt_passwd_file.gpg. The encrypted subdirectory, along with the generated (encrypted) password, will be committed to @@ -106,6 +162,13 @@ usage subtree. You can change this manually by mounting (opening) the directory and replacing this symlink with a custom one. + You can optionally use an extra piece of symmetric passphrase to encrypt the subdirectory, by + passing the argument -p or --passphrase when invoking this command to initialize. In this case, + the passphrase you input will be used along with the generated password to derive a new master + password for gocryptfs. This second piece of passphrase will not be stored in the password store, + and you will be asked for it every time you invoke \`$PROGRAM gocrypt open\`. This mode adds an + extra layer of protection in case the gpg-encrypted master password is somehow compromised. + $PROGRAM gocrypt open Mount the encrypted subdirectory to \$PASSWORD_STORE_DIR/$gocrypt_dec_dir.