Compare commits

...

7 commits

2 changed files with 101 additions and 17 deletions

View file

@ -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,20 +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
pass generate "$gocrypt_passwd_file" 32
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" <<< "$(pass 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
@ -53,30 +94,57 @@ gocrypt_init() {
echo "# Gocrypt" >> .gitignore
echo "gocrypt" >> .gitignore
pass git add .gitignore
pass git add "$gocrypt_dir"
pass git commit -m "Initialized encrypted storage for gocrypt plugin"
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"
}
gocrypt_open() {
[ $# -eq 0 ] || gocrypt_die "Unexpected argument"
gocrypt_close_check
mkdir -p "$gocrypt_dec_dir"
gocryptfs -passfile /dev/stdin "$gocrypt_dir" "$gocrypt_dec_dir" <<< "$(pass 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() {
[ $# -eq 0 ] || gocrypt_die "Unexpected argument"
gocrypt_open_check
fusermount -u "$gocrypt_dec_dir"
fusermount -u "$gocrypt_dec_dir" || fusermount -u -z "$gocrypt_dec_dir"
}
gocrypt_delegate() {
gocrypt_open_check
# Delegate command to another `pass` instance that manages what is inside of the mountpoint
PASSWORD_STORE_DIR="$PWD/$gocrypt_dec_dir" pass $@
PASSWORD_STORE_DIR="$PWD/$gocrypt_dec_dir" "$PROGRAM" "$@"
# Commit if there has been changes due to this operation
pass git add "$gocrypt_dir"
pass git commit -m "Encrypted pass operation inside gocrypt" "$gocrypt_dir" || echo "No git commit created"
cmd_git add "$gocrypt_dir"
cmd_git commit -m "Encrypted pass operation inside gocrypt" "$gocrypt_dir" || echo "No git commit created"
}
gocrypt_crypt() {
[ $# -eq 1 ] || gocrypt_die "Unexpected argument"
gocrypt_open_check
[ ! -f "$1.gpg" ] && gocrypt_die "Not found: $1"
cmd_show "$1" | EDITOR=tee gocrypt_delegate edit "$1"
cmd_delete -f "$1"
echo "Moved $1 into encrypted storage"
}
gocrypt_help() {
@ -84,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
@ -94,12 +162,24 @@ 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.
$PROGRAM gocrypt close
Unmount the encrypted subtree, if it was opened before.
$PROGRAM gocrypt crypt <pass_name>
Move a password <pass_name> from the original password store to the encrypted subdirectory. Note
that if you use git, this will still leave a record in the git repository of the original password
store.
$PROGRAM gocrypt help
Print this help message.
@ -139,19 +219,23 @@ case "$1" in
;;
init)
shift
gocrypt_init $@
gocrypt_init "$@"
;;
open)
shift
gocrypt_open $@
gocrypt_open "$@"
;;
crypt)
shift
gocrypt_crypt "$@"
;;
close)
shift
gocrypt_close $@
gocrypt_close "$@"
;;
ls|list|grep|find|search|show|insert|add|edit|generate|rm|remove|delete|mv|rename|cp|copy|git)
# No shift here since we need to delegate these commands to another pass instance
gocrypt_delegate $@
gocrypt_delegate "$@"
;;
*)
gocrypt_die "Unknown command $1 for gocrypt"

View file

@ -1,3 +1,3 @@
#!/usr/bin/env sh
PASSWORD_STORE_DIR=$PWD/pass PASSWORD_STORE_EXTENSIONS_DIR=$PWD PASSWORD_STORE_ENABLE_EXTENSIONS=true pass $@
PASSWORD_STORE_DIR=$PWD/pass PASSWORD_STORE_EXTENSIONS_DIR=$PWD PASSWORD_STORE_ENABLE_EXTENSIONS=true pass "$@"