bashopenssl

openssl encryption and decryption issues in bash script


I have 2 Bash scripts. The first takes 2 strings as arguments and creates an env variable with the name of the 1st string and sets it's value to the value of the 2nd string encrypted with openssl (v3.4.2). The 2nd takes 1 string as an argument and outputs the decrypted value of the environment variable whose name is the value of the string passed as an argument.


setit.sh

#!/bin/bash

if [ $# -ne 2 ]; then
    echo "Usage: $0 <variable_name> <string_to_encrypt>"
    exit 1
fi

VAR_NAME=$1
STRING_TO_ENCRYPT=$2

# Generate a random salt and passphrase
SALT=$(openssl rand -hex 8)
PASSPHRASE=$(openssl rand -hex 12)

# Encrypt the string
ENCRYPTED=$(echo -n "$STRING_TO_ENCRYPT" | openssl enc -aes-256-cbc -a -salt -pbkdf2 -pass pass:"$PASSPHRASE" -S "$SALT")

# Combine salt, passphrase, and encrypted string
RESULT="${SALT}:${PASSPHRASE}:${ENCRYPTED}"

# Set the environment variable
export "$VAR_NAME=$RESULT"

echo "Environment variable $VAR_NAME has been set with the encrypted value."

Sample Usage source ./setit.sh MY_VAR secret_value


getit.sh

#!/bin/bash

if [ $# -ne 1 ]; then
    echo "Usage: $0 <variable_name>"
    exit 1
fi

VAR_NAME=$1

# Check if the environment variable exists
if [ -z "${!VAR_NAME}" ]; then
    echo "Error: Environment variable $VAR_NAME does not exist."
    exit 1
fi

# Get the value of the environment variable
ENCRYPTED_VALUE="${!VAR_NAME}\n"
echo "$VAR_NAME = $ENCRYPTED_VALUE"

# Extract salt, passphrase, and encrypted string
IFS=':' read -r SALT PASSPHRASE ENCRYPTED <<< "$ENCRYPTED_VALUE"

# Decrypt the string
DECRYPTED=$(echo -n "$ENCRYPTED" | openssl enc -aes-256-cbc -d -a -pbkdf2 -pass pass:"$PASSPHRASE" -S "$SALT")

# Check if decryption was successful
if [ $? -eq 0 ]; then
    echo "Decrypted value of $VAR_NAME:"
    echo "$DECRYPTED"
else
    echo "Error: Decryption failed. The encrypted value may be corrupted or tampered with."
    exit 1
fi

Sample Usage ./getit.sh MY_VAR

The first script seems to work as expected, but when I run the 2nd script to decrypt the value, I get the following error:

bad decrypt 0031185FF87F0000:error:1C80006B:Provider routines:ossl_cipher_generic_block_final:wrong final block length:providers/implementations/ciphers/ciphercommon.c:444: Error: Decryption failed. The encrypted value may be corrupted or tampered with.

The wrong final blocklength part tells me that it might be a padding issue, but i'm not entirely sure.


Solution

  • Two changes to make to getit.sh:

    The new code lines:

    ENCRYPTED_VALUE="${!VAR_NAME}"
    
    DECRYPTED=$(echo $ENCRYPTED" | openssl enc -aes-256-cbc -d -a -pbkdf2 -pass pass:"$PASSPHRASE" -S "$SALT")
    

    Taking for a test drive:

    $ ./getit.sh MY_VAR
    MY_VAR = 031280154d75151a:f52579d70b1439fbaa6d0fe3:03C8TtDzoByFsiyAsLdBkw==
    Decrypted value of MY_VAR:
    secret_value