From 627d804000cb2142f620a884af489a1f2e8101b9 Mon Sep 17 00:00:00 2001 From: EduardDurech <39579228+EduardDurech@users.noreply.github.com> Date: Thu, 29 Sep 2022 19:21:38 +0200 Subject: [PATCH 1/3] New input functionality for new KeyStoreAPI + list supports showing saved preferences + delete supports deleting saved preferences + encrypt data interface + decrypt data interface + generate supports making random alias + generate supports new quiet, unlocked, invalidate, authorization, and flags + generate supports new purposes and algorithms for Symmetric Ciphers --- scripts/termux-keystore.in | 281 ++++++++++++++++++++++++++++++------- 1 file changed, 228 insertions(+), 53 deletions(-) diff --git a/scripts/termux-keystore.in b/scripts/termux-keystore.in index d6d7ccc..bb4d5eb 100644 --- a/scripts/termux-keystore.in +++ b/scripts/termux-keystore.in @@ -7,39 +7,81 @@ SCRIPTNAME=termux-keystore show_usage () { echo "Usage: $SCRIPTNAME command" echo "These commands are supported:" - echo " list [-d]" - echo " delete " - echo " generate [-a alg] [-s size] [-u validity]" + echo " list [-sd]" + echo " delete [-s pref]" + echo " generate [alias] [-bcilq] [-a alg] [-s size] [-p purposes] [-u validity]" echo " sign " echo " verify " + echo " encrypt [-q] [-p path] [-s pref]" + echo " decrypt [-q] [-p path] [-s pref]" echo - echo "list: List the keys stored inside the keystore." - echo " -d Detailed results (includes key parameters)." + echo "list: List either the keys stored inside the keystore or data in shared preferences." + echo " -s Shared preferences. Shows shared preferences. [Omit to show keys]" + echo " -d Detailed results. For keys, shows key parameters." + echo " For shared preferences, shows data of preferences." echo - echo "delete: Permanently delete a given key from the keystore." - echo " alias Alias of the key to delete." + echo "delete: Delete either a given key from the keystore or a given shared preference." + echo " alias Alias of the key or shared preference-associated key to delete." + echo " -s pref Shared preference to delete. [Omit to delete key" + echo " and all shared preferences]" echo echo "generate: Create a new key inside the hardware keystore." - echo " alias Alias of the key." - echo " -a alg Algorithm to use (either 'RSA' or 'EC'). Defaults to RSA." - echo " -s size Key size to use. For RSA, the options are 2048, 3072" - echo " and 4096. For EC, the options are 256, 384 and 521." - echo " -u validity User validity duration in seconds. Omit to disable." - echo " When enabled, the key can only be used for the" - echo " duration specified after the device unlocks. After" - echo " the duration has passed, the user needs to re-lock" - echo " and unlock the device again to be able to use this key." + echo " alias Alias of the key. If not supplied then randomly generated." + echo " For generation, ensure /dev/urandom is accessible." + echo " -b Biometric flag, require e.g. fingerprint, iris, or face." + echo " -c Credentials flag, require e.g. PIN, pattern, or password. (≥Android11)" + echo " -i Invalidate flag, key invalidated by new biometric enrollments. (≥Android7)" + echo " -l Locked flag, allows key access while device is locked. (≥Android9)" + echo " -q Quiet flag, silences key specifications output." + echo " -a alg Algorithm. Asymmetric key pairs are 'RSA' or 'EC'." + echo " Symmetric key ciphers or cipher options specified as" + echo " 'ALG/MODE/PADDING'. ALG is 'RSA' or 'AES'." + echo " See: Android keystore#SupportedAlgorithms" + echo " [Asymmetric Default: 'RSA']" + echo " [Symmetric Default: 'AES/GCM/NoPadding']" + echo " -s size Key size. For RSA, the options are 2048, 3072, and 4096." + echo " For EC, the options are 256, 384, and 521." + echo " For AES, the options are 128, 192, and 256." + echo " [Defaults to smallest size]" + echo " -p purposes Key purposes. See: Android KeyProperties.PURPOSE flags" + echo " [Asymmetric Default is sign+verify: '4|8']" + echo " [Symmetric Default is encrypt+decrypt: '1|2']" + echo " -u validity User validity duration in seconds. Specifies duration the key can be" + echo " used for after authorization if -c or -b were supplied. Default" + echo " requires authorization for every key invocation. [Default: -1]" echo echo "sign: Sign using the given key, the data is read from stdin and the" echo "signature is output to stdout." echo " alias Alias of the key to use for signing." echo " algorithm Algorithm to use, e.g. 'SHA256withRSA'. This should" - echo " match the algorithm of the key." + echo " match the algorithm of the key." echo echo "verify: Verify a signature. The data (original file) is read from stdin." echo " alias Alias of the key to use for verify." echo " algorithm Algorithm that was used to sign this data." echo " signature Signature file to use in verification." + echo + echo "encrypt: Encrypt using the given key, the data is read from a file or stdin" + echo "(in that precedence) and the encrypted data is output to stdout and/or" + echo "shared preferences with a user-supplied name. Output is of the form" + echo "[IV.length][IV][Encrypted Data] (IV omitted if IV.length is 0)." + echo " alias Alias of the key to use for encrypting." + echo " algorithm Algorithm to use in the form 'ALG/MODE/PADDING'. This should match the" + echo " algorithm of the key." + echo " -q Quiet flag, silences encrypted data output." + echo " -p path Path of input file. Name of filepath containing data to be encrypted." + echo " -s pref Shared preference. Name of shared preference to store encrypted data." + echo + echo "decrypt: Decrypt using the given key, the data is read from a file, shared preference, or" + echo "stdin (in that precedence) and the decrypted data can be output to stdout. Input is" + echo "expected in the form [IV.length][IV][Encrypted Data] (IV omitted if IV.length is 0)." + echo " alias Alias of the key to use for decrypting." + echo " algorithm Algorithm to use in the form 'ALG/MODE/PADDING'. This should match the" + echo " algorithm of the key." + echo " -q Quiet flag, silences decrypted data output." + echo " -p path Path of input file. Name of filepath containing data to be decrypted." + echo " -s pref Shared preference. Name of shared preference containing data to be" + echo " decrypted." } @@ -50,17 +92,36 @@ check_args () { fi } -list_keys () { - if [ "$#" -gt 0 ] && [ "$1" = "-d" ]; then - $CMD_BASE -e command list --ez detailed true - else - $CMD_BASE -e command list - fi +list_Data () { + DETAILED=0; PREF=0; + while getopts ds NAME; do + case "$NAME" in + d) DETAILED=1 ;; + s) PREF=1 ;; + ?) ;; + esac + done + + $CMD_BASE -e command list --ei detailed "$DETAILED" --ei pref "$PREF" } -delete_key () { - check_args delete 1 $# - $CMD_BASE -e command delete -e alias "$1" +delete_data () { + if [ $# -lt 1 ]; then + echo "$SCRIPTNAME delete: alias required" + exit 1 + fi + ALIAS=$1; shift + PREF=-1; + while getopts s: NAME; do + case "$NAME" in + s) PREF=$OPTARG ;; + ?) ;; + esac + done + shift $((OPTIND-1)) + if [ "$#" -gt 0 ]; then echo "Unmatched argument \"$1\" ignoring: \"$*\""; fi + + $CMD_BASE -e command delete -e alias "$ALIAS" -e pref "$PREF" } sign_data () { @@ -74,53 +135,167 @@ verify_data () { -e signature "$(realpath "$3")" } -generate_key () { - if [ $# -lt 1 ]; then - echo "$SCRIPTNAME generate: alias argument is required" +encrypt_data () { + if [ $# -lt 2 ]; then + echo "$SCRIPTNAME decrypt: alias and algorithm required" exit 1 fi - ALIAS=$1; shift - ALGORITHM=RSA; SIZE=-1; CURVE=secp256r1; VALIDITY=0 - while getopts a:s:c:u: NAME; do + ALIAS=$1; ALGORITHM=$2; shift 2 + INFILE=-1; STORE=-1; QUIET=0; + while getopts p:s:q NAME; do case "$NAME" in - a) ALGORITHM=$OPTARG ;; - s) SIZE=$OPTARG ;; - u) VALIDITY=$OPTARG ;; + p) INFILE=$(realpath "$OPTARG") ;; + s) STORE=$OPTARG ;; + q) QUIET=1 ;; ?) ;; esac done + shift $((OPTIND-1)) + if [ "$#" -gt 0 ]; then echo "Unmatched argument \"$1\" ignoring: \"$*\""; fi - if [ "$ALGORITHM" = "RSA" ]; then - case "$SIZE" in - -1) SIZE=2048 ;; - 2048|3072|4096) ;; - *) echo "$SCRIPTNAME: invalid RSA key size $SIZE"; exit 1 ;; - esac - elif [ "$ALGORITHM" = "EC" ]; then - case "$SIZE" in - -1|256) CURVE=secp256r1 ;; - 384) CURVE=secp384r1 ;; - 521) CURVE=secp521r1 ;; - *) echo "$SCRIPTNAME: invalid EC key size $SIZE"; exit 1 ;; + $CMD_BASE -e command encrypt -e alias "$ALIAS" -e algorithm "$ALGORITHM" \ + -e filepath "$INFILE" -e store "$STORE" --ei quiet "$QUIET" | base64 -d +} + +decrypt_data () { + if [ $# -lt 2 ]; then + echo "$SCRIPTNAME decrypt: alias and algorithm required" + exit 1 + fi + ALIAS=$1; ALGORITHM=$2; shift 2 + INFILE=-1; STORE=-1; QUIET=0; + while getopts p:s:q NAME; do + case "$NAME" in + p) INFILE=$(realpath "$OPTARG") ;; + s) STORE=$OPTARG ;; + q) QUIET=1 ;; + ?) ;; esac + done + shift $((OPTIND-1)) + if [ "$#" -gt 0 ]; then echo "Unmatched argument \"$1\" ignoring: \"$*\""; fi + + $CMD_BASE -e command decrypt -e alias "$ALIAS" -e algorithm "$ALGORITHM" \ + -e filepath "$INFILE" -e store "$STORE" --ei quiet "$QUIET" | base64 -d +} + +generate_key () { + #If noargs or args starts with flags + if [ "$#" -eq 0 ] || [ -n "${1%%[!-]*}" ]; then + ALIAS="$(head -c 5 /dev/urandom | base32)" + echo "Generated Alias: \"${ALIAS?"unable to generate, please provide as argument"}\"" else - echo "$SCRIPTNAME: invalid algorithm $ALGORITHM"; exit 1 + ALIAS=$1 + shift + fi + # Defaults + _ALGORITHM="RSA"; MODE=-1; PADDING=-1; SIZE=-1; PURPOSES=-1 + UNLOCKED=1; VALIDITY=-1; INVALIDATE=0; AUTH=0; + # Args handler + while getopts a:s:p:u:qlicb NAME; do + case "$NAME" in + q) QUIET=1 ;; + l) UNLOCKED=0 ;; + i) INVALIDATE=1 ;; + c) AUTH=$((AUTH|1)) ;; + b) AUTH=$((AUTH|2)) ;; + a) _ALGORITHM=$OPTARG ;; + s) SIZE=$OPTARG ;; + p) PURPOSES=$OPTARG ;; + u) VALIDITY=$OPTARG ;; + ?) ;; + esac + done + shift $((OPTIND-1)) + if [ "$#" -gt 0 ]; then echo "Unmatched argument \"$1\" ignoring: \"$*\""; fi + + ALGORITHM=${_ALGORITHM%%/*} + # Begin splice by / + case "$ALGORITHM" in + "$_ALGORITHM") ;; + *) MODE=${_ALGORITHM#*/} + MODE=${MODE%/*} + if [ "$ALGORITHM" = "${_ALGORITHM%/*/*}" ]; then PADDING=${_ALGORITHM##*/}; fi ;; + esac + # End splice by / + + case "$ALGORITHM" in + "RSA") case "$SIZE" in + -1) SIZE=2048 ;; + 2048|3072|4096) ;; + *) echo "$SCRIPTNAME: invalid RSA key size $SIZE"; exit 1 ;; + esac + case "$MODE" in + -1) ;; + "ECB") case "$PADDING" in + -1) PADDING="OAEPPadding" ;; + "NoPadding"|"PKCS1Padding"|"OAEPPadding") ;; + *) echo "$SCRIPTNAME: invalid padding RSA/$MODE/$PADDING"; exit 1 ;; + esac ;; + *) echo "$SCRIPTNAME: invalid RSA mode $MODE"; exit 1 ;; + esac ;; + "EC") case "$SIZE" in + -1) SIZE=256 ;; + 256|384|521) ;; + *) echo "$SCRIPTNAME: invalid EC key size $SIZE"; exit 1 ;; + esac + MODE=-1 + PADDING=-1 ;; + "AES") case "$SIZE" in + -1) SIZE=128 ;; + 128|192|256) ;; + *) echo "$SCRIPTNAME: invalid AES key size $SIZE"; exit 1 ;; + esac + case "$MODE" in + -1) MODE="GCM" + PADDING="NoPadding";; + "CTR"|"GCM") case "$PADDING" in + -1|"NoPadding") PADDING="NoPadding" ;; + *) echo "$SCRIPTNAME: invalid padding AES/$MODE/$PADDING" + exit 1 ;; + esac ;; + "CBC"|"ECB") case "$PADDING" in + -1|"PKCS7Padding") PADDING="PKCS7Padding" ;; + *) echo "$SCRIPTNAME: invalid padding AES/$MODE/$PADDING" + exit 1 ;; + esac ;; + *) echo "$SCRIPTNAME: invalid AES mode $MODE"; exit 1 ;; + esac ;; + *) echo "$SCRIPTNAME: invalid algorithm $ALGORITHM"; exit 1 ;; + esac + if [ "$PURPOSES" -eq -1 ]; then + case "$MODE" in + "-1") PURPOSES="4|8" ;; # Sign+Verify for Pairs + *) case "$ALGORITHM" in + "AES") PURPOSES="1|2" ;; # Encrypt+Decrypt for Ciphers + "RSA") PURPOSES="1|2|4|8" ;; + esac ;; + esac + fi + + if [ -z "${QUIET:+1}" ]; then + _ALGORITHM="$ALGORITHM/$MODE/$PADDING" + echo "Algorithm: ${_ALGORITHM%%/-1*}" + echo "Size: $SIZE" + echo "Purposes: $PURPOSES" fi - # purpose 12 is SIGN+VERIFY $CMD_BASE -e command generate -e alias "$ALIAS" -e algorithm "$ALGORITHM" \ - --ei purposes 12 --esa digests NONE,SHA-1,SHA-256,SHA-384,SHA-512 \ - --ei size "$SIZE" -e curve "$CURVE" --ei validity "$VALIDITY" + --ei purposes "$(($PURPOSES))" --esa digests NONE,SHA-1,SHA-256,SHA-384,SHA-512 \ + --ei size "$SIZE" -e mode "$MODE" -e padding "$PADDING" --ei unlocked "$UNLOCKED" \ + --ei validity "$VALIDITY" --ei invalidate "$INVALIDATE" --ei auth "$AUTH" } ACTION="${1-}" if [ "$#" -gt 0 ]; then shift; fi case "$ACTION" in - list) list_keys "$@" ;; + list) list_Data "$@" ;; generate) generate_key "$@" ;; - delete) delete_key "$@" ;; + delete) delete_data "$@" ;; sign) sign_data "$@" ;; verify) verify_data "$@" ;; + encrypt) encrypt_data "$@" ;; + decrypt) decrypt_data "$@" ;; *) show_usage ;; esac From e1174c0cde7cb31ee260faa9b24ed8b938cfe676 Mon Sep 17 00:00:00 2001 From: EduardDurech <39579228+EduardDurech@users.noreply.github.com> Date: Sat, 15 Oct 2022 20:23:08 +0200 Subject: [PATCH 2/3] Update termux-keystore.in --- scripts/termux-keystore.in | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/scripts/termux-keystore.in b/scripts/termux-keystore.in index bb4d5eb..641e2d1 100644 --- a/scripts/termux-keystore.in +++ b/scripts/termux-keystore.in @@ -12,8 +12,8 @@ show_usage () { echo " generate [alias] [-bcilq] [-a alg] [-s size] [-p purposes] [-u validity]" echo " sign " echo " verify " - echo " encrypt [-q] [-p path] [-s pref]" - echo " decrypt [-q] [-p path] [-s pref]" + echo " encrypt [-q] [-p path] [-s pref] [-t timeout]" + echo " decrypt [-q] [-p path] [-s pref] [-t timeout]" echo echo "list: List either the keys stored inside the keystore or data in shared preferences." echo " -s Shared preferences. Shows shared preferences. [Omit to show keys]" @@ -31,6 +31,7 @@ show_usage () { echo " -b Biometric flag, require e.g. fingerprint, iris, or face." echo " -c Credentials flag, require e.g. PIN, pattern, or password. (≥Android11)" echo " -i Invalidate flag, key invalidated by new biometric enrollments. (≥Android7)" + echo " (iff -u validity=-1)" echo " -l Locked flag, allows key access while device is locked. (≥Android9)" echo " -q Quiet flag, silences key specifications output." echo " -a alg Algorithm. Asymmetric key pairs are 'RSA' or 'EC'." @@ -71,6 +72,9 @@ show_usage () { echo " -q Quiet flag, silences encrypted data output." echo " -p path Path of input file. Name of filepath containing data to be encrypted." echo " -s pref Shared preference. Name of shared preference to store encrypted data." + echo " -t timeout Timeout for authentication in seconds. Specifies the valid timeframe for" + echo " authentication. Some devices continue showing the prompt or" + echo " automatically cancel. Default is system-dependent. [Default: -1]" echo echo "decrypt: Decrypt using the given key, the data is read from a file, shared preference, or" echo "stdin (in that precedence) and the decrypted data can be output to stdout. Input is" @@ -82,6 +86,9 @@ show_usage () { echo " -p path Path of input file. Name of filepath containing data to be decrypted." echo " -s pref Shared preference. Name of shared preference containing data to be" echo " decrypted." + echo " -t timeout Timeout for authentication in seconds. Specifies the valid timeframe for" + echo " authentication. Some devices continue showing the prompt or" + echo " automatically cancel. Default is system-dependent. [Default: -1]" } @@ -141,11 +148,12 @@ encrypt_data () { exit 1 fi ALIAS=$1; ALGORITHM=$2; shift 2 - INFILE=-1; STORE=-1; QUIET=0; - while getopts p:s:q NAME; do + INFILE=-1; STORE=-1; TIMEOUT=-1; QUIET=0; + while getopts p:s:t:q NAME; do case "$NAME" in p) INFILE=$(realpath "$OPTARG") ;; s) STORE=$OPTARG ;; + t) TIMEOUT=$OPTARG ;; q) QUIET=1 ;; ?) ;; esac @@ -154,7 +162,8 @@ encrypt_data () { if [ "$#" -gt 0 ]; then echo "Unmatched argument \"$1\" ignoring: \"$*\""; fi $CMD_BASE -e command encrypt -e alias "$ALIAS" -e algorithm "$ALGORITHM" \ - -e filepath "$INFILE" -e store "$STORE" --ei quiet "$QUIET" | base64 -d + -e filepath "$INFILE" -e store "$STORE" --ei quiet "$QUIET" \ + --ei authenticationTimeout "$TIMEOUT" | base64 -d } decrypt_data () { @@ -163,11 +172,12 @@ decrypt_data () { exit 1 fi ALIAS=$1; ALGORITHM=$2; shift 2 - INFILE=-1; STORE=-1; QUIET=0; - while getopts p:s:q NAME; do + INFILE=-1; STORE=-1; TIMEOUT=-1; QUIET=0; + while getopts p:s:t:q NAME; do case "$NAME" in p) INFILE=$(realpath "$OPTARG") ;; s) STORE=$OPTARG ;; + t) TIMEOUT=$OPTARG ;; q) QUIET=1 ;; ?) ;; esac @@ -176,7 +186,8 @@ decrypt_data () { if [ "$#" -gt 0 ]; then echo "Unmatched argument \"$1\" ignoring: \"$*\""; fi $CMD_BASE -e command decrypt -e alias "$ALIAS" -e algorithm "$ALGORITHM" \ - -e filepath "$INFILE" -e store "$STORE" --ei quiet "$QUIET" | base64 -d + -e filepath "$INFILE" -e store "$STORE" --ei quiet "$QUIET" \ + --ei authenticationTimeout "$TIMEOUT" | base64 -d } generate_key () { From 44aabd344a1543af67d485e01f0e359e021704a0 Mon Sep 17 00:00:00 2001 From: EduardDurech <39579228+EduardDurech@users.noreply.github.com> Date: Sat, 22 Oct 2022 11:52:28 +0200 Subject: [PATCH 3/3] Encrypt & Decrypt do not require algorithm --- scripts/termux-keystore.in | 34 ++++++++++++++++++---------------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/scripts/termux-keystore.in b/scripts/termux-keystore.in index 641e2d1..2599c48 100644 --- a/scripts/termux-keystore.in +++ b/scripts/termux-keystore.in @@ -12,8 +12,8 @@ show_usage () { echo " generate [alias] [-bcilq] [-a alg] [-s size] [-p purposes] [-u validity]" echo " sign " echo " verify " - echo " encrypt [-q] [-p path] [-s pref] [-t timeout]" - echo " decrypt [-q] [-p path] [-s pref] [-t timeout]" + echo " encrypt [-a alg] [-q] [-p path] [-s pref] [-t timeout]" + echo " decrypt [-a alg] [-q] [-p path] [-s pref] [-t timeout]" echo echo "list: List either the keys stored inside the keystore or data in shared preferences." echo " -s Shared preferences. Shows shared preferences. [Omit to show keys]" @@ -67,8 +67,8 @@ show_usage () { echo "shared preferences with a user-supplied name. Output is of the form" echo "[IV.length][IV][Encrypted Data] (IV omitted if IV.length is 0)." echo " alias Alias of the key to use for encrypting." - echo " algorithm Algorithm to use in the form 'ALG/MODE/PADDING'. This should match the" - echo " algorithm of the key." + echo " -a alg Algorithm to use in the form 'ALG/MODE/PADDING'. This should match the" + echo " algorithm of the key. If unspecified, uses key's first instance." echo " -q Quiet flag, silences encrypted data output." echo " -p path Path of input file. Name of filepath containing data to be encrypted." echo " -s pref Shared preference. Name of shared preference to store encrypted data." @@ -80,8 +80,8 @@ show_usage () { echo "stdin (in that precedence) and the decrypted data can be output to stdout. Input is" echo "expected in the form [IV.length][IV][Encrypted Data] (IV omitted if IV.length is 0)." echo " alias Alias of the key to use for decrypting." - echo " algorithm Algorithm to use in the form 'ALG/MODE/PADDING'. This should match the" - echo " algorithm of the key." + echo " -a alg Algorithm to use in the form 'ALG/MODE/PADDING'. This should match the" + echo " algorithm of the key. If unspecified, uses key's first instance." echo " -q Quiet flag, silences decrypted data output." echo " -p path Path of input file. Name of filepath containing data to be decrypted." echo " -s pref Shared preference. Name of shared preference containing data to be" @@ -143,14 +143,15 @@ verify_data () { } encrypt_data () { - if [ $# -lt 2 ]; then - echo "$SCRIPTNAME decrypt: alias and algorithm required" + if [ $# -lt 1 ]; then + echo "$SCRIPTNAME encrypt: alias required" exit 1 fi - ALIAS=$1; ALGORITHM=$2; shift 2 - INFILE=-1; STORE=-1; TIMEOUT=-1; QUIET=0; - while getopts p:s:t:q NAME; do + ALIAS=$1; shift 1 + ALGORITHM=-1; INFILE=-1; STORE=-1; TIMEOUT=-1; QUIET=0; + while getopts a:p:s:t:q NAME; do case "$NAME" in + a) ALGORITHM=$OPTARG ;; p) INFILE=$(realpath "$OPTARG") ;; s) STORE=$OPTARG ;; t) TIMEOUT=$OPTARG ;; @@ -167,14 +168,15 @@ encrypt_data () { } decrypt_data () { - if [ $# -lt 2 ]; then - echo "$SCRIPTNAME decrypt: alias and algorithm required" + if [ $# -lt 1 ]; then + echo "$SCRIPTNAME decrypt: alias required" exit 1 fi - ALIAS=$1; ALGORITHM=$2; shift 2 - INFILE=-1; STORE=-1; TIMEOUT=-1; QUIET=0; - while getopts p:s:t:q NAME; do + ALIAS=$1; shift 1 + ALGORITHM=-1; INFILE=-1; STORE=-1; TIMEOUT=-1; QUIET=0; + while getopts a:p:s:t:q NAME; do case "$NAME" in + a) ALGORITHM=$OPTARG ;; p) INFILE=$(realpath "$OPTARG") ;; s) STORE=$OPTARG ;; t) TIMEOUT=$OPTARG ;;