Home > database >  Why do I seem to get different results from `base64`?
Why do I seem to get different results from `base64`?

Time:01-28

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.

  • Related