Bash OpenSSL is not equal to php openssl_encrypt value - bash

I am trying to reach the same value of encryption in bash as it is from php , with no success .
Here is my php script
$message ='{"coupon_key":"011205358365345679","location_id":"288","device_key":"test_1234"}';
$key = "password";
$iv = base64_decode("dU+AyWweQYhAlGKLaxoS9w==");
$base64_iv = base64_encode($iv);
$base64_ev = base64_encode($encrypted_value);
$encrypted_value = openssl_encrypt(
$message,
'AES-256-CBC',
$key,
OPENSSL_RAW_DATA|OPENSSL_NO_PADDING,
$iv
);
$encode = base64_encode($encrypted_value);
//Zi7UcBwqM+gKZC9iZPgF3UHBXLUg1+Age/1+kRIfcstYBgGfYm7N1qCIFnm6jGn4AGQph/Q6hKjR1hYBT0wkJv8c8qFrHHZNUuraMfSRH3s=
$mac = hash_hmac('sha256', $base64_iv . $encode, $key);
echo '{"iv":"'.$base64_iv.'","value":"'.$encode.'","mac":"'.$mac.'"}'."<br>";
//{"iv":"dU+AyWweQYhAlGKLaxoS9w==","value":"Zi7UcBwqM+gKZC9iZPgF3UHBXLUg1+Age/1+kRIfcstYBgGfYm7N1qCIFnm6jGn4AGQph/Q6hKjR1hYBT0wkJv8c8qFrHHZNUuraMfSRH3s=","mac":"97fb6f4226a917322c7361af1d9b2949ad96691c1fc1a7f1c8379c71ae19f356"}
$retString2 = base64_encode('{"iv":"'.$base64_iv.'","value":"'.$encode.'","mac":"'.$mac.'"}');
echo $retString2;
//eyJpdiI6ImRVK0F5V3dlUVloQWxHS0xheG9TOXc9PSIsInZhbHVlIjoiWmk3VWNCd3FNK2dLWkM5aVpQZ0YzVUhCWExVZzErQWdlLzEra1JJZmNzdFlCZ0dmWW03TjFxQ0lGbm02akduNEFHUXBoL1E2aEtqUjFoWUJUMHdrSnY4YzhxRnJISFpOVXVyYU1mU1JIM3M9IiwibWFjIjoiOTdmYjZmNDIyNmE5MTczMjJjNzM2MWFmMWQ5YjI5NDlhZDk2NjkxYzFmYzFhN2YxYzgzNzljNzFhZTE5ZjM1NiJ9
and here is my bash version
password="password";
passwordhex=$(echo "$password" | xxd -c 256 -ps) ;
# iv2=$(hexdump -n 16 -e '4/4 "%08X" 1 "\n"' /dev/random) ;
iv=$(printf 'dU+AyWweQYhAlGKLaxoS9w==' | base64 -d )
biv=$(printf "$iv" | base64) ;
hexiv=$(printf "$iv" | xxd -c 256 -ps) ;
eString=$(printf '{"coupon_key":"011205358365345678","location_id":"288","device_key":"test_1234"}');
tttw=$(printf "$eString" | openssl aes-256-cbc -e -nosalt -a -A -K "$passwordhex" -iv "$hexiv") ;
echo "$tttw" ;
printf "${biv}${tttw}" |openssl dgst -sha256 -hmac abc -macopt hexkey:"$passwordhex" | sed 's/^.* //';
macopt2=$(printf "${biv}${tttw}" |openssl dgst -sha256 -hmac abc -macopt hexkey:"$passwordhex" | sed 's/^.* //');
echo "$macopt2"
finalString="{'iv':'$biv','value':'$tttw','mac':'$macopt2'}";
echo "$finalString";
sendHash=$(printf "$finalString" | base64 -w 0)
echo "$sendHash"
Starting from
tttw=$(echo -n $eString | openssl aes-256-cbc -e -nosalt -a -A -K $passwordhex -iv $hexiv) ;
it goes wrong , because $tttw is returning then
bKG5quB9/YQUsmlFvDHq2H+AfNGQuDfVztyi0dd5hCY7hLfaACnjD8SWlwqy0yy4hXUZSA2YcTXej/xtMg9vqEpoO6CDw9hk7+tUcYOOV5aOdVBnSLowmEllHt0JfjdE
instead of Zi7UcBwqM+gKZC9iZPgF3UHBXLUg1+Age/1+kRIfcstYBgGfYm7N1qCIFnm6jGn4AGQph/Q6hKjR1hYBT0wkJv8c8qFrHHZNUuraMfSRH3s=
Can anybody maybe see what option is going wrong here?
Note1: I have updated the bash script to use prinf instead of echo -n
Note 2 : Seems on my newer machine I get "hex string is too short, padding with zero bytes to length" from the line
tttw=$(printf $eString | openssl aes-256-cbc -e -nosalt -a -A -K $passwordhex -iv $hexiv) ;

Looks like the issue is near the very top:
passwordhex=$(echo "$password" | xxd -c 256 -ps) ;
So essentially the output of echo "$password" is password\n.
Using echo like this will append a line feed to the input for xxd which I assume you already know since the original script was packed with echo -n. I mentioned in the comments that printf is more portable. The accepted way to use printf with a variable is like this:
passwordhex=$(printf '%s' "$password" | xxd -c 256 -ps) ;
The reason for this is that if your variable has a format identifier (like %s), it would change the output unexpectedly. This would have also showed up on shellcheck.
With this one change, here is the output:
Zi7UcBwqM+gKZC9iZPgF3UHBXLUg1+Age/1+kRIfcssepjJ8+wUjTDAjPUMkGA+eF9EL284iD5UIzA+REyhMWLWbUJpPltHFk1+lhQyVlUXXVTw0FFV1G+iQfEWhbyg4
484123c33b54e446c61120112955cd15f3592f42e737c9fa24db266cdec954a2
484123c33b54e446c61120112955cd15f3592f42e737c9fa24db266cdec954a2
{'iv':'dU+AyWweQYhAlGKLaxoS9w==','value':'Zi7UcBwqM+gKZC9iZPgF3UHBXLUg1+Age/1+kRIfcssepjJ8+wUjTDAjPUMkGA+eF9EL284iD5UIzA+REyhMWLWbUJpPltHFk1+lhQyVlUXXVTw0FFV1G+iQfEWhbyg4','mac':'484123c33b54e446c61120112955cd15f3592f42e737c9fa24db266cdec954a2'}
eydpdic6J2RVK0F5V3dlUVloQWxHS0xheG9TOXc9PScsJ3ZhbHVlJzonWmk3VWNCd3FNK2dLWkM5aVpQZ0YzVUhCWExVZzErQWdlLzEra1JJZmNzc2Vwako4K3dValREQWpQVU1rR0ErZUY5RUwyODRpRDVVSXpBK1JFeWhNV0xXYlVKcFBsdEhGazErbGhReVZsVVhYVlR3MEZGVjFHK2lRZkVXaGJ5ZzQnLCdtYWMnOic0ODQxMjNjMzNiNTRlNDQ2YzYxMTIwMTEyOTU1Y2QxNWYzNTkyZjQyZTczN2M5ZmEyNGRiMjY2Y2RlYzk1NGEyJ30=

Related

Why is my key not found when sending a JWT assertion to Azure AD?

I'm trying to write a bash script to get access tokens from Microsoft for my app registered in AD. I can't seem to get past this error though:
"error":"invalid_client","error_description":"AADSTS700027: The certificate with identifier used to sign the client assertion is not registered on application. [Reason - The key was not found., Thumbprint of key used by client: '356134 ...
The full gist can be found here: https://gist.github.com/smaring/3a3a6779a809beecc39624aada6e2b88
Here are some of the juicy bits ...
$ openssl pkcs12 -in <your-app>.pfx -out <your-app>.pem
$ openssl x509 -outform der -in <your-app>.pem -out ${PUBLIC_CERT_FILE}
$ openssl rsa -in <your-app>.pem -out ${PRIVATE_KEY_FILE}
x5t="$(sha1sum ${PUBLIC_CERT_FILE} | awk '{print $1;}' | openssl base64 | sed s/\+/-/g |sed 's/\//_/g' | sed -E s/=+$// )"
read -r -d '' HEADER <<EOF
{
"alg": "RS256",
"typ": "JWT",
"x5t": "${x5t}"
}
EOF
HEADER_NO_WHITESPACE=$(echo "${HEADER}" | sed ':a; N; s/[[:space:]]//g; ta')
BASE64_ENCODED_HEADER=$(echo ${HEADER_NO_WHITESPACE} | openssl base64 | sed s/\+/-/g |sed 's/\//_/g' | sed -E s/=+$// )
read -r -d '' PAYLOAD <<EOF
{
"aud": "https: //login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token",
"exp": ${exp},
"iss": "${CLIENT_ID}",
"jti": "${jti}",
"nbf": ${nbf},
"sub": "${CLIENT_ID}"
}
EOF
PAYLOAD_NO_WHITESPACE=$(echo "${PAYLOAD}" | sed ':a; N; s/[[:space:]]//g; ta')
BASE64_ENCODED_PAYLOAD=$(echo ${PAYLOAD_NO_WHITESPACE} | openssl base64 | sed s/\+/-/g |sed 's/\//_/g' | sed -E s/=+$// )
SIGNATURE=$( echo -n "${BASE64_ENCODED_HEADER}.${BASE64_ENCODED_PAYLOAD}" | \
openssl dgst -sha256 -binary -sign <(cat ${PRIVATE_KEY_FILE}) | \
openssl base64 | sed s/\+/-/g |sed 's/\//_/g' | sed -E s/=+$// )
CLIENT_ASSERTION="${BASE64_ENCODED_HEADER}.${BASE64_ENCODED_PAYLOAD}.${SIGNATURE}"
curl -s -X POST \
--header \"Content-Type: application/x-www-form-urlencoded\" \
-d \"\
scope=https%3A%2F%2Fgraph.microsoft.com%2F.default&\
grant_type=client_credentials&\
client_assertion_type=urn%3Aietf%3Aparams%3Aoauth%3Aclient-assertion-type%3Ajwt-bearer&\
client_id=${CLIENT_ID}&\
client_assertion=${CLIENT_ASSERTION}\" \
https://login.microsoftonline.com/${TENANT_ID}/oauth2/v2.0/token"
After getting a Java version of this working I figured out that I was not generating the thumbprint properly. The fix was this:
thumbprint=$(openssl x509 -in ${publicCertFile} -fingerprint -noout | awk '{split($0,a,"="); print a[2]}' )
thumbprintHex=$(echo -e "\\x${thumbprint}" | sed 's/:/\\x/g' )
thumbprintHexString=$(echo -e "${thumbprint}" | sed 's/://g' )
x5t=$(echo -ne "${thumbprintHex}" | openssl base64 | sed s/\+/-/g | sed 's/\//_/g' | sed -E s/=+$// )
I have updated the gist to the fully working bash script.
Construct a JWT assertion in bash using client-credential with cert to get an access token from Microsoft Azure Directory --> https://gist.github.com/smaring/3a3a6779a809beecc39624aada6e2b88

script error bash ( error:*** WARNING : deprecated key derivation used)

#!/bin/bash
# Decrypt function
function decrypt {
MzSaas7k=$(echo $hash | sed 's/988sn1/83unasa/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/4d298d/9999/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/3i8dqos82/873h4d/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/4n9Ls/20X/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/912oijs01/i7gg/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/k32jx0aa/n391s/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/nI72n/YzF1/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/82ns71n/2d49/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/JGcms1a/zIm12/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/MS9/4SIs/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/Ymxj00Ims/Uso18/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/sSi8Lm/Mit/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/9su2n/43n92ka/g')
Mzns7293sk=$(echo $MzSaas7k | sed 's/ggf3iunds/dn3i8/g')
MzSaas7k=$(echo $Mzns7293sk | sed 's/uBz/TT0K/g')
flag=$(echo $MzSaas7k | base64 -d | openssl enc -aes-128-cbc -a -d -salt -pass pass:$salt)
}
# Variables
var="9M"
salt=""
hash="VTJGc2RHVmtYMTl2ZnYyNTdUeERVRnBtQWVGNmFWWVUySG1wTXNmRi9rQT0K"
# Base64 Encoding Example:
# $ echo "Some Text" | base64
for i in {1..28}
do
var=$(echo $var | base64)
if [[ $i == 28 ]]
then
salt=$(echo $var | wc -c)
fi
done
# Check if $salt is empty
if [[ ! -z "$salt" ]]
then
decrypt
echo $flag
else
exit 1
fi
error:*** WARNING : deprecated key derivation used.
Using -iter or -pbkdf2 would be better.
bad decrypt
140546881238400:error:06065064:digital envelope routines:EVP_DecryptFinal_ex:bad decrypt:../crypto/evp/evp_enc.c:610:
the exercise: Create a "For" loop that encodes the variable "var" 28 times in "base64". The number of characters in the 28th hash is the value that must be assigned to the "salt" variable.
code made by me :
for i in {1..28}
do
var=$(echo $var | base64)
if [[ $i == 28 ]]
then
salt=$(echo $var | wc -c)
fi
done
Here is the solution in case you are stuck. Make sure to delete “salt” in the #Variables tab. We will set the salt in the loop.
#Variables
var="9M"
hash="VTJGc2RHVmtYMTl2ZnYyNTdUeERVRnBtQWVGNmFWWVUySG1wTXNmRi9rQT0K"
# Base64 Encoding Example:
# $ echo "Some Text" | base64
# <- For-Loop here
for ((i = 0 ; i < 28 ; i++)); do
echo "Try number $i"
var=$(echo $var | base64)
echo $var | wc -c
salt=$(echo $var | wc -c)
done
It should be right, but I had to make a workaround too.
This might do the trick:
salt=$((${#var}+1))
# ${#var} counts the length and you have to add 1 to make the exercise work.
This way it'll still show you the warning, but if you copy the last line, that'll be your answer.

How to convert JSON Web Key Set (JWKS) public keys to PEM file using BASH?

Let's say you use AWS and you want to use ID based authentication using Cognito.
Then aws provides you with a public key you can verify the cognito payload with.
Let's also assume you don't want or cannot use any fancy libraries like jose since you are locked in a highly constrained environment.
The way to go is a BASH script that would make good old Brian Kernighan
proud.
You have to understand the encoding first.
Base64Url needs to be translated to Base64.
This is achieved using padding characters =
If the number of characters is divisible by 4 you don't need padding.
This relates to the binary digit representation.
Once that is taken care of you can translate Base64 to binary.
But how do I convert a JWKS/JWT to a PEM file this using BASH and BASH-programs only?
This is the solution I came up with following the officual documentation and sources listed below.
https://aws.amazon.com/premiumsupport/knowledge-center/decode-verify-cognito-json-token/
Please adapt input url or use json token directly and make sure you have jq installed.
Descriptive help is given in the function as comments.
Tested successfully on Ubuntu 18.04 and AmazonLinux2 (CentOS) as of 2020-04-28
#!/usr/bin/env bash
set -e
# FUNCTIONS
decodeBase64UrlUInt() { #input:base64UrlUnsignedInteger
local binaryDigits paddedStr
case $(( ${#1} % 4 )) in
2) paddedStr="$1==" ;;
3) paddedStr="$1=" ;;
*) paddedStr="$1" ;;
esac
binaryDigits=$( \
echo -n "$paddedStr" \
| tr '_-' '/+' \
| openssl enc -d -a -A \
| xxd -b -g 0 \
| cut -d ' ' -f 2 \
| paste -s -d '' \
)
echo "ibase=2; obase=A; $binaryDigits" | bc
# openssl enc:encoding; -d=decrypt; -a=-base64; -A=singleLineBuffer
# xxd "make-hexdump": -b=bits; -g=groupsize
# cut -d=delimiter; -f=field
# paste -s=serial|singleFile; -d=delimiter
}
base64UrlToHex() { #input:base64UrlString
local hexStr paddedStr
case $(( ${#1} % 4 )) in
2) paddedStr="$1==" ;;
3) paddedStr="$1=" ;;
*) paddedStr="$1" ;;
esac
hexStr=$( \
echo -n "$paddedStr" \
| tr '_-' '/+' \
| base64 -d \
| xxd -p -u \
| tr -d '\n' \
)
echo "$hexStr"
# base64 -d=decode
# xxd -p=-plain=continuousHexDump; -u=upperCase
# tr -d=delete
}
asn1Conf() { #input:hexStrPlainUpperCase
local e="$1"
local n="$2"
echo "
asn1 = SEQUENCE:pubkeyinfo
[pubkeyinfo]
algorithm = SEQUENCE:rsa_alg
pubkey = BITWRAP,SEQUENCE:rsapubkey
[rsa_alg]
algorithm = OID:rsaEncryption
parameter = NULL
[rsapubkey]
n = INTEGER:0x$n
e = INTEGER:0x$e
" | sed '/^$/d ; s/^ *//g' \
| openssl asn1parse \
-genconf /dev/stdin \
-out /dev/stdout \
| openssl rsa \
-pubin \
-inform DER \
-outform PEM \
-in /dev/stdin \
-out /dev/
# sed /^$/d=removeEmptyLines; /^ */=removeLeadingSpaces
}
main() {
local e n hexArr
local jwksUrl="$1"
local jwkJson=$(curl -sSSL $jwksUrl)
local kidList=$(jq -r '.keys[].kid' <<< "$jwkJson")
for keyId in $kidList; do
n=$(jq -r ".keys[] | select(.kid == \"$keyId\") | .n" <<< "$jwkJson")
e=$(jq -r ".keys[] | select(.kid == \"$keyId\") | .e" <<< "$jwkJson")
echo -e "\n$keyId"
# decodeBase64UrlUInt "$e"
# decodeBase64UrlUInt "$n"
asn1Conf $(base64UrlToHex "$e") $(base64UrlToHex "$n")
done
}
# MAIN
main 'https://cognito-idp.{region}.amazonaws.com/{userPoolId}/.well-known/jwks.json'
exit 0
Special thanks to:
Yury Oparin
https://www.yuryoparin.com/2014/05/base64url-in-bash.html
Cédric Deltheil
https://github.com/Moodstocks/moodstocks-api-clients/blob/master/bash/base64url.sh
Alvis Tang
https://gist.github.com/alvis/89007e96f7958f2686036d4276d28e47
Here are some options:
Either ignore base64 -d complaining of truncated input:
<<<'SGVsbG8geW91Cg' base64 -d 2>/dev/null ||:
Or fix the base64 padding with Bash before decoding:
base64URL='SGVsbG8geW91Cg'
printf -v pad_space '%*s' $((${#base64URL}%4)) ''
padded_base64="$base64URL${pad_space// /=}"
<<<"$padded_base64" base64 -d

AES (aes-cbc-256) encryption/decryption with openssl expected output truncated

I wrote a script. Please pardon that I am not an expert in scripting.
Upon deciphering, the results gotten truncated.
[Message in text]: 0123456789abcdefghijklmnopqrstuvwxyz
message_input in hex: 303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a0a
key: 788a1ca0bf1ab80f092841aabd77793f
hex string is too short, padding with zero bytes to length
c19f83afc1160ce81b0fc9906d513693386ccdd313b0f2884c698411441054e8
ciphered text: c19f83afc1160ce81b0fc9906d513693386ccdd313b0f2884c698411441054e8
IV: 7ecd3d63a8b74bb2f80d71a1c9d43359
deciphering ...
hex string is too short, padding with zero bytes to length
key: 788a1ca0bf1ab80f092841aabd77793f
iv: 7ecd3d63a8b74bb2f80d71a1c9d43359
answer: 30313233343536373839616263646566
Deciphered Message in hex: 30313233343536373839616263646566
deciphered text: 0123456789abcdef
The recovered deciphered text: 0123456789abcdef, ghijklmnopqrstuvwxyz gets truncated. This is supposed to be AES-CBC. Is there an option I did not turn on?
Here is the ciphering:
IV=$(openssl rand -hex 16)
get_key_for_ciphering; # key_for_ciphering gets populated
message_input=$(echo -n "${message_input//[[:space:]]/}") # remove spaces
echo "message_input in hex: "$message_input
echo "key": $key_for_ciphering;
ANS=$(echo "0: $message_input" | xxd -r | openssl enc -aes-256-cbc -iv $IV -K "$key_for_ciphering" | xxd -p)
ANS=$(echo -n "${ANS//[[:space:]]/}") # remove spaces
Here is the deciphering (message_input=$ANS):
get_key_for_ciphering; # key_for_ciphering gets populated
ANS=$(echo "0: $message_input" | xxd -r | openssl enc -aes-256-cbc -d -nopad -nosalt -K "$key_for_ciphering" -iv $IV | xxd -p) # -nopad -nosalt
Focusing in your question, the problem is in the xxd command. When converting a hex string to binary with xxd -r, you have to use the -p to tell xxd that is a plain hex string (no line breaks).
When converting back to hex with xxd -p, line breaks are added every 32 bytes. Unfortunately, xxd doesn't provide a flag to not include line breaks (you could use -c to set the number of columns, but it's limited to a max number). There are many option to remove line breaks, but one is appending a | tr -d '\n' to your command, as shown in the example below.
IV=$(openssl rand -hex 16)
key_for_ciphering=$(openssl rand -hex 16)
message_input="303132333435363738396162636465666768696a6b6c6d6e6f707172737475767778797a0a"
message_input=$(echo -n "${message_input//[[:space:]]/}") # remove spaces
echo "Message: $message_input"
echo "Key: $key_for_ciphering"
echo "IV: $IV"
ANS=$(echo "0: $message_input" | xxd -r -p | openssl enc -aes-256-cbc -iv $IV -K "$key_for_ciphering" | xxd -p | tr -d '\n')
ANS=$(echo -n "${ANS//[[:space:]]/}") # remove spaces
echo "Encrypted: $ANS"
ANS=$(echo "0: $ANS" | xxd -r -p | openssl enc -aes-256-cbc -d -nopad -nosalt -K "$key_for_ciphering" -iv $IV | xxd -p | tr -d '\n')
echo "Decrypted: $ANS"
---- Edit: ----
Doesn't work, as shell-parameters cannot contain binary zero. Possible fix with filters:
#!/bin/bash
tohex () {
perl -e 'binmode STDIN; while (<STDIN>) { print unpack "H*",$_; }'
}
fromhex () {
perl -e 'binmode STDIN; while (<STDIN>) { print pack "H*",$_; }'
}
binInput='0123456789abcdefghijklmnopqrstuvwxyz'
hexIV="$(openssl rand -hex 16)"
hexKey='788a1ca0bf1ab80f092841aabd77793f'
hexCipher="$(printf '%s' "$binInput" |\
openssl enc -aes-256-cbc -nosalt -iv "$hexIV" -K "$hexKey" | tohex)"
binResult="$(printf '%s' "$hexCipher" | fromhex |\
openssl enc -aes-256-cbc -d -iv "$hexIV" -K "$hexKey")"
if [ "$binInput" = "$binResult" ]; then echo OK;
fi
---- Original: ----
I think your problem lies in hexadecimal conversion. Try using perl pack/unpack:
tohex () {
perl -e 'print unpack "H*", "$ARGV[0]"' "$1"
}
fromhex () {
perl -e 'print pack "H*", "$ARGV[0]"' "$1"
}
message='0123456789abcdefghijklmnopqrstuvwxzy §"+!%/=()'
message_hex=$(tohex "$message")
message_cmp=$(fromhex "$message_hex")
if [ "$message" = "$message_cmp" ]; then echo OK; fi

OpenSSL decrypt AES 256bit (base64) encrypted password - wrong final block length

I am trying to decrypt aes-256-cdc encoded password using OpenSSL
#!/usr/bin/env bash
ak=BgL0cPoZQ4wZWOWl5mXBhlMsNbbZL2zvsWZXjuGy4Iw=
iv=cGEvcGWzE8t7CS3wbeoUFQ==
pass=RCQm23YHOCg3nxOl7CcQ7w==
#change format from base64 into hex
AES_KEY=$(echo "${ak}" | openssl base64 -d | xxd -p |tr -d '\n')
AES_IV=$(echo "${iv}" | openssl base64 -d | xxd -p)
ENCODED_PASSWORD=$(echo "${pass}" | openssl base64 -d | xxd -p)
echo "AES_KEY ${AES_KEY}"
echo "AES_IV ${AES_IV}"
echo "ENCODED_PASSWORD ${ENCODED_PASSWORD}"
#set password file
echo "${ENCODED_PASSWORD}" > in.txt
#decode password
openssl enc -nosalt -aes-256-cbc -d -iv ${AES_IV} -K ${AES_KEY} -in in.txt
this results in error message
AES_KEY 0602f470fa19438c1958e5a5e665c186532c35b6d92f6cefb166578ee1b2e08c
AES_IV 70612f7065b313cb7b092df06dea1415
ENCODED_PASSWORD 53b7adff6e85baedfa9dab80109ad67d
▒▒▒▒▒▒`$;▒▒▒▒%▒O▒Q▒▒▒S▒▒<7 7
bad decrypt
32624:error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length:evp_enc.c:518:
0602f470fa19438c1958e5a5e665c186532c35b6d92f6cefb166578ee1b2
e08c
I think that the problem is aes-key (ak) which has a newline char in it, which I am trying to remove with
|tr -d '\n'
a password should decode as
password
No, what's wrong is the encoding of in.txt. It should not be text at all, it should be binary.
In principle you would not get this error either if you'd use echo -n suppressing the final end-of-line within the ciphertext. The decryption would however still fail as it expects binary instead of an encoded binary value.
You may want to change the name of in.txt to in.bin if you want to keep a file. You should also be able to simply pipe the ciphertext into openssl using the standard input (stdin). In that case you may want to encode it first to store it in a shell variable and then decode before piping it to openssl to decrypt it.
For binary, use cat instead of echo.
If your $pass is long (more than 32 chars maybe), be sure to use openssl -A option, the reason is documented in the openssl manual.
With -A option, for encryption, the base64 encoded string will not be splitted in segments; For decryption, whole line is read to be decoded using base64.
Code example:
plaintxt='hello world"
pass=$(echo ${plaintxt} | openssl enc -aes-128-cbc -a -K ${AES_KEY} -iv ${AES_IV} -A )
echo "decoded password is: "
echo ${pass} | openssl enc -aes-128-cbc -d -a -K ${AES_KEY} -iv ${AES_IV} -A
this works as expected:
#!/usr/bin/env bash
#base64 encoded aes key, iv and password
ak=BgL0cPoZQ4wZWOWl5mXBhlMsNbbZL2zvsWZXjuGy4Iw=
iv=cGEvcGWzE8t7CS3wbeoUFQ==
pass=OfOXO+ruKFTCsBwGHynXwA==
#change format from base64 into hex, for openssl to consume, xxd -p -c32 is taking care of wrapping of the new lines
AES_KEY=$(echo ${ak} | openssl base64 -d | xxd -p -c32)
AES_IV=$(echo ${iv} | openssl base64 -d | xxd -p -c32)
echo "AES_KEY ${ak}"
echo "AES_IV ${iv}"
echo "encoded password ${pass}"
echo "decoded password is: "
echo ${pass} | openssl enc -aes-256-cbc -d -a -K ${AES_KEY} -iv ${AES_IV}
explanation:
openssl enc -aes-256-cbc -d
decode using aes-256-cbc algo
-a
in our case, it means that openssl will accept base64 encoded password
-K
aes key
-iv
aes iv

Resources