From dd778bf7569097e9e638fe492035c75483954cc6 Mon Sep 17 00:00:00 2001 From: James Murty Date: Sun, 6 Oct 2024 23:10:35 +1100 Subject: [PATCH] Remove hard dependency on `xxd` which can be onerous, fall back to `printf` or `perl` instead Remove hard dependency on `xxd` which is often a heavy requirement because it is only available with Vim on some platforms. Fall back to using `printf` (provided it has full %b support) or `perl` when either of these are available, and only require that `xxd` be installed and available when that is the only viable option. Adapted from #181. Thanks @andreineculau! --- CHANGELOG.md | 4 ++++ INSTALL.md | 5 ++--- README.md | 4 ++-- transcrypt | 28 ++++++++++++++++++++++++---- 4 files changed, 32 insertions(+), 9 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8a7835a..ee282d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -53,6 +53,10 @@ system, you must also run the `--upgrade` command in each repository: ### Changed +- Remove hard dependency on `xxd` which is often a heavy requirement because it + is only available with Vim on some platforms. Fall back to `printf` with full + %b support or `perl` when either of these are available, and only require + `xxd` when it is the only viable option (#181) - Prevent global options set in `GREP_OPTIONS` enviroment variable from breaking transcrypt's use of grep (#166) - If `CDPATH` is set then cd will print the path (#156) diff --git a/INSTALL.md b/INSTALL.md index a965d37..403262b 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -6,8 +6,8 @@ The requirements to run transcrypt are minimal: - Git - OpenSSL - `column` command (on Ubuntu/Debian install `bsdmainutils`) -- `xxd` command if using OpenSSL version 3 - (on Ubuntu/Debian is included with `vim`) +- if using OpenSSL 3+ one of: `xxd` (on Ubuntu/Debian is included with `vim`) + or `printf` command (with %b directive) or `perl` ...and optionally: @@ -74,4 +74,3 @@ collection: or via the packages system: # `pkg install -y security/transcrypt` - diff --git a/README.md b/README.md index 2fc8fb0..bfdc264 100644 --- a/README.md +++ b/README.md @@ -56,8 +56,8 @@ The requirements to run transcrypt are minimal: - Git - OpenSSL - `column` and `hexdump` commands (on Ubuntu/Debian install `bsdmainutils`) -- `xxd` command if using OpenSSL version 3 - (on Ubuntu/Debian is included with `vim`) +- if using OpenSSL 3+ one of: `xxd` (on Ubuntu/Debian is included with `vim`) + or `printf` command (with %b directive) or `perl` ...and optionally: diff --git a/transcrypt b/transcrypt index 8dbb57c..0abecf4 100755 --- a/transcrypt +++ b/transcrypt @@ -188,6 +188,26 @@ is_salt_prefix_workaround_required() { # (keyed with a combination of the filename and transcrypt password), and # then use the last 16 bytes of that HMAC for the file's unique salt. +# shellcheck disable=SC2155 +readonly IS_PRINTF_BIN_SUPPORTED=$([[ "$(echo -n "41" | sed "s/../\\\\x&/g" | xargs -0 printf "%b")" == "A" ]] && echo 'true' || echo 'false') + +# Apply one of three methods to convert a hex string to binary data, or +hex_to_bin() { + # alternative 1 but xxd often only comes with a vim install + if command -v "xxd" >/dev/null; then + xxd -r -p + # alternative 2, but requires printf that supports "%b" + # (macOS /usr/bin/printf doesn't) + elif $IS_PRINTF_BIN_SUPPORTED; then + sed "s/../\\\\x&/g" | xargs -0 printf "%b" + # alternative 3 as perl is fairly common + elif command -v "perl" >/dev/null; then + perl -pe "s/([0-9A-Fa-f]{2})/chr(hex(\$1))/eg" + else + die 'required command not found: xxd, or printf that supports "%%b", or perl' + fi +} + git_clean() { context=$(extract_context_name_from_name_value_arg "$1") [[ "$context" ]] && shift @@ -216,7 +236,7 @@ git_clean() { if [ "$(is_salt_prefix_workaround_required)" == "true" ]; then # Encrypt the file to base64, ensuring it includes the prefix 'Salted__' with the salt. #133 ( - echo -n "Salted__" && echo -n "$salt" | xxd -r -p && + echo -n "Salted__" && echo -n "$salt" | hex_to_bin && # Encrypt file to binary ciphertext ENC_PASS=$password "$openssl_path" enc -e "-${cipher}" -md MD5 -pass env:ENC_PASS -S "$salt" -in "$tempfile" ) | @@ -396,10 +416,10 @@ run_safety_checks() { 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 - # check for extra `xxd` dependency when running against OpenSSL version 3+ + + # check for a working method to convert a hex string to binary data if [ "$(is_salt_prefix_workaround_required)" == "true" ]; then - cmd="xxd" - command -v "$cmd" >/dev/null || die 'required command "%s" was not found' "$cmd" + echo -n "41" | hex_to_bin >/dev/null fi # ensure the repository is clean (if it has a HEAD revision) so we can force