I need to use base64 encoded credentials for an API call. From a web UI interface for the API I have gotten the credentials in base64 encoded form. For the sake of showing my issue I have saved the credentials to a file creds
and the base64 encoded credentials from the web ui in a file creds64
.
Then, running the script below:
#!/bin/bash
CREDS=$(cat creds)
BASE64_CREDS=$(cat creds64)
if [[ $CREDS == $(base64 -d creds64) ]]; then
echo "the original credentials were the same as the decoded base64 credentials"
else
echo "the original credentials were NOT the same as the decoded base64 credentials"
fi
if [[ $(base64 creds) == $BASE64_CREDS ]]; then
echo "the encoded original credentials were the same as the base64 credentials"
else
echo "the encoded original credentials were NOT the same as the base64 credentials"
fi
The resulting output is
the original credentials were the same as the decoded base64 credentials
the encoded original credentials were NOT the same as the base64 credentials
I don't understand how the base64 decoded credentials can equal the "plain" credentials, but comparing the result of base64 creds
with the already encoded credentials can be not equal.
What am I misunderstanding here?
CodePudding user response:
If the raw binary data contains null bytes, the shell basically cannot handle it. Compare
bash$ var=$'\0hello'
bash$ echo "$var"
bash$
The lack of quoting is also problematic; see When to wrap quotes around a shell variable
Keeping the data in a variable is unnecessary anyway. The following should work robustly regardless of any null characters.
if base64 -d creds64 | cmp - creds; then
:
Finally, as Robby Cornelissen notes in a comment, the base64
command probably adds line breaks to keep the lines in the output below 80 characters. Your web client's result might not have line breaks at all, or could have them at a different line width.
You can fix this by trimming any newlines anywhere:
if [[ "$(base64 creds | tr -d '\n') = "$(tr -d '\n' <creds64)" ]]; then
:
The use of [[
is a Bashism, so not portable to POSIX sh
. You can switch to [
instead if you need portability. Somewhat similarly, cmp
might not support specifying -
to mean standard input on all platforms; Bash lets you use /dev/stdin
instead, or /dev/fd/0
on some platforms.