Skip to content

Commit

Permalink
Let user set a custom path to openssl #108
Browse files Browse the repository at this point in the history
Add the optional `--set-openssl-path` argument to tell transcrypt
to use an explicit path to the openssl binary, instead of whatever
version is found on the user's `$PATH`.

The OpenSSL path can be changed on init, during an upgrade,
or along with any other transcrypt command (even by itself).

The openssl path is saved as a new `transcrypt.openssl-path` Git
config local setting in the repository, alongside the other transcrypt
settings like cipher, password etc.
  • Loading branch information
jmurty committed Feb 27, 2021
1 parent 561d158 commit dce1ad0
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 11 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ The format is based on [Keep a Changelog][1], and this project adheres to

## [Unreleased]

### Added

- Add `--set-openssl-path` option to configure transcrypt to use a specific
openssl version instead of the default version found in `$PATH`. This will be
most useful to macOS users who might want to use a newer version of OpenSSL.
This option can be used on init, on upgrade, or by itself.

### Fixed

- Respect Git `core.hooksPath` setting when installing the pre-commit hook. (#104)
Expand Down
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,9 @@ directory.
the password to derive the key from;
defaults to 30 random base64 characters

--set-openssl-path=PATH_TO_OPENSSL
use OpenSSL at this path; defaults to 'openssl' in $PATH

-y, --yes
assume yes and accept defaults for non-specified options

Expand Down
3 changes: 3 additions & 0 deletions man/transcrypt.1.ronn
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ The transcrypt source code and full documentation may be downloaded from
the password to derive the key from;
defaults to 30 random base64 characters

* `--set-openssl-path`=<path_to_openssl>:
use OpenSSL at this path; defaults to 'openssl' in $PATH

* `-y`, `--yes`:
assume yes and accept defaults for non-specified options

Expand Down
42 changes: 42 additions & 0 deletions tests/test_init.bats
Original file line number Diff line number Diff line change
Expand Up @@ -97,3 +97,45 @@ SETUP_SKIP_INIT_TRANSCRYPT=1
[[ "${lines[6]}" = " PASSWORD: abc123" ]]
[[ "${lines[8]}" = " transcrypt -c aes-256-cbc -p 'abc123'" ]]
}

@test "init: transcrypt.openssl-path config setting defaults to 'openssl'" {
init_transcrypt
[[ "$(git config --get transcrypt.openssl-path)" = 'openssl' ]]
}

@test "init: --set-openssl-path changes transcrypt.openssl-path" {
init_transcrypt
[[ "$(git config --get transcrypt.openssl-path)" = 'openssl' ]]
}

@test "init: --set-openssl-path is applied during init" {
init_transcrypt
run ../transcrypt --set-openssl-path=/test/path
[[ "$(git config --get transcrypt.openssl-path)" = "/test/path" ]]
}

@test "init: --set-openssl-path is applied during upgrade" {
init_transcrypt
[[ "$(git config --get transcrypt.openssl-path)" = 'openssl' ]]

# Set openssl path
FULL_OPENSSL_PATH=$(which openssl)

"$BATS_TEST_DIRNAME"/../transcrypt --upgrade --yes --set-openssl-path="$FULL_OPENSSL_PATH"
[[ "$(git config --get transcrypt.openssl-path)" = "$FULL_OPENSSL_PATH" ]]
[[ ! "$(git config --get transcrypt.openssl-path)" = 'openssl' ]]
}

@test "init: transcrypt.openssl-path config setting is retained with --upgrade" {
init_transcrypt
[[ "$(git config --get transcrypt.openssl-path)" = 'openssl' ]]

# Set openssl path
FULL_OPENSSL_PATH=$(which openssl)
run ../transcrypt --set-openssl-path="$FULL_OPENSSL_PATH"''

# Retain transcrypt.openssl-path config setting on upgrade
"$BATS_TEST_DIRNAME"/../transcrypt --upgrade --yes
[[ "$(git config --get transcrypt.openssl-path)" = "$FULL_OPENSSL_PATH" ]]
[[ ! "$(git config --get transcrypt.openssl-path)" = 'openssl' ]]
}
37 changes: 26 additions & 11 deletions transcrypt
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,9 @@ git_clean() {
else
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
salt=$(openssl dgst -hmac "${filename}:${password}" -sha256 "$filename" | tr -d '\r\n' | tail -c16)
ENC_PASS=$password openssl enc -"$cipher" -md MD5 -pass env:ENC_PASS -e -a -S "$salt" -in "$tempfile"
openssl_path=$(git config --get --local transcrypt.openssl-path)
salt=$("${openssl_path}" dgst -hmac "${filename}:${password}" -sha256 "$filename" | tr -d '\r\n' | tail -c16)
ENC_PASS=$password "$openssl_path" enc "-${cipher}" -md MD5 -pass env:ENC_PASS -e -a -S "$salt" -in "$tempfile"
fi
}

Expand All @@ -142,7 +143,8 @@ git_smudge() {
trap 'rm -f "$tempfile"' EXIT
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
tee "$tempfile" | ENC_PASS=$password openssl enc -"$cipher" -md MD5 -pass env:ENC_PASS -d -a 2>/dev/null || cat "$tempfile"
openssl_path=$(git config --get --local transcrypt.openssl-path)
tee "$tempfile" | ENC_PASS=$password "$openssl_path" enc "-${cipher}" -md MD5 -pass env:ENC_PASS -d -a 2>/dev/null || cat "$tempfile"
}

git_textconv() {
Expand All @@ -153,7 +155,8 @@ git_textconv() {
fi
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
ENC_PASS=$password openssl enc -"$cipher" -md MD5 -pass env:ENC_PASS -d -a -in "$filename" 2>/dev/null || cat "$filename"
openssl_path=$(git config --get --local transcrypt.openssl-path)
ENC_PASS=$password "$openssl_path" enc "-${cipher}" -md MD5 -pass env:ENC_PASS -d -a -in "$filename" 2>/dev/null || cat "$filename"
}

# shellcheck disable=SC2005,SC2002,SC2181
Expand Down Expand Up @@ -209,7 +212,7 @@ run_safety_checks() {
fi

# check for dependencies
for cmd in {column,grep,mktemp,openssl,sed,tee}; do
for cmd in {column,grep,mktemp,"${openssl_path}",sed,tee}; do
command -v "$cmd" >/dev/null || die 'required command "%s" was not found' "$cmd"
done

Expand All @@ -226,12 +229,12 @@ run_safety_checks() {
# unset the cipher variable if it is not supported by openssl
validate_cipher() {
local list_cipher_commands
if openssl list-cipher-commands &>/dev/null; then
if "${openssl_path}" list-cipher-commands &>/dev/null; then
# OpenSSL < v1.1.0
list_cipher_commands='openssl list-cipher-commands'
list_cipher_commands="${openssl_path} list-cipher-commands"
else
# OpenSSL >= v1.1.0
list_cipher_commands='openssl list -cipher-commands'
list_cipher_commands="${openssl_path} list -cipher-commands"
fi

local supported
Expand Down Expand Up @@ -284,7 +287,7 @@ get_password() {
if [[ $answer =~ $YES_REGEX ]] || [[ ! $answer ]]; then
local password_length=30
local random_base64
random_base64=$(openssl rand -base64 $password_length)
random_base64=$(${openssl_path} rand -base64 $password_length)
password=$random_base64
else
printf 'Password: '
Expand Down Expand Up @@ -493,6 +496,7 @@ save_configuration() {
git config transcrypt.version "$VERSION"
git config transcrypt.cipher "$cipher"
git config transcrypt.password "$password"
git config transcrypt.openssl-path "$openssl_path"

# write the filter settings
if [[ -d $(git rev-parse --git-common-dir) ]]; then
Expand Down Expand Up @@ -661,8 +665,8 @@ uninstall_transcrypt() {
pre_commit_hook="${GIT_HOOKS}/pre-commit"
pre_commit_hook_installed="${GIT_HOOKS}/pre-commit-crypt"
if [[ -f "$pre_commit_hook" ]]; then
hook_md5=$(openssl md5 -hex <"$pre_commit_hook")
installed_md5=$(openssl md5 -hex <"$pre_commit_hook_installed")
hook_md5=$("${openssl_path}" md5 -hex <"$pre_commit_hook")
installed_md5=$("${openssl_path}" md5 -hex <"$pre_commit_hook_installed")
if [[ "$hook_md5" = "$installed_md5" ]]; then
rm "$pre_commit_hook"
else
Expand Down Expand Up @@ -736,6 +740,8 @@ upgrade_transcrypt() {
# Keep current cipher and password
cipher=$(git config --get --local transcrypt.cipher)
password=$(git config --get --local transcrypt.password)
# Keep current openssl-path, or set to default if no existing value
openssl_path=$(git config --get --local transcrypt.openssl-path 2>/dev/null || printf '%s' "$openssl_path")

# Keep contents of .gitattributes
ORIG_GITATTRIBUTES=$(cat "$GIT_ATTRIBUTES")
Expand Down Expand Up @@ -887,6 +893,9 @@ help() {
the password to derive the key from;
defaults to 30 random base64 characters
--set-openssl-path=PATH_TO_OPENSSL
use OpenSSL at this path; defaults to 'openssl' in \$PATH
-y, --yes
assume yes and accept defaults for non-specified options
Expand Down Expand Up @@ -988,6 +997,7 @@ rekey=''
show_file=''
uninstall=''
upgrade=''
openssl_path='openssl'

# used to bypass certain safety checks
requires_existing_config=''
Expand Down Expand Up @@ -1031,6 +1041,11 @@ while [[ "${1:-}" != '' ]]; do
--password=*)
password=${1#*=}
;;
--set-openssl-path=*)
openssl_path=${1#*=}
# Immediately apply config setting
git config transcrypt.openssl-path "$openssl_path"
;;
-y | --yes)
interactive=''
;;
Expand Down

0 comments on commit dce1ad0

Please sign in to comment.