base64 -d decodes, but says invalid input

11,929

Solution 1

If you do the reverse, you'll note that the string isn't complete:

$ echo '{"foo":"bar","baz":"bat"}' | base64
eyJmb28iOiJiYXIiLCJiYXoiOiJiYXQifQo=

$ echo "eyJmb28iOiJiYXIiLCJiYXoiOiJiYXQifQo=" | base64 -di
{"foo":"bar","baz":"bat"}

Extracts of Why does base64 encoding require padding if the input length is not divisible by 3?

What are Padding Characters?

Padding characters help satisfy length requirements and carry no meaning.

However, padding is useful in situations where base64 encoded strings are concatenated in such a way that the lengths of the individual sequences are lost, as might happen, for example, in a very simple network protocol.

If unpadded strings are concatenated, it's impossible to recover the original data because information about the number of odd bytes at the end of each individual sequence is lost. However, if padded sequences are used, there's no ambiguity, and the sequence as a whole can be decoded correctly.

Solution 2

The command-line tool is picky about the presence of padding characters. That string is 34 characters long, so there should be two = signs as padding at the end.

$ echo "eyJmb28iOiJiYXIiLCJiYXoiOiJiYXQifQ==" | base64 -di; echo
{"foo":"bar","baz":"bat"}

Solution 3

GNU's base64 -d requires proper padding (input length must be a multiple of 4). Other base64 decoders may be smarter and not require padding (e.g. Mac/BSD base64 -D does not require padding).

Here's a bash command that can automatically pad the base64 string properly. Then you won't get the "invalid input" error.

str="eyJmb28iOiJiYXIiLCJiYXoiOiJiYXQifQ"

echo "$str"==== | fold -w 4 | sed '$ d' | tr -d '\n' | base64 --decode

Explanation:

  • echo "$str"==== appends 4 equal signs
  • fold -w 4 split every 4 characters into separate lines
  • sed '$ d' deletes the last line (the extraneous padding)
  • tr -d '\n' joins all lines
Share:
11,929

Related videos on Youtube

shwoseph
Author by

shwoseph

Updated on September 18, 2022

Comments

  • shwoseph
    shwoseph over 1 year

    Does anybody know why this is happening and how to fix it?

    me@box:~$ echo "eyJmb28iOiJiYXIiLCJiYXoiOiJiYXQifQ" | base64 -di
    {"foo":"bar","baz":"bat"}base64: invalid input
    
    
    • john doe
      john doe over 3 years
      I have this happen on Windows 10 when I install the GNU base64 binary there, I simply ignore it and copy my decoded output and utilize it.
    • Billy left SE for Codidact
      Billy left SE for Codidact over 3 years
      Mine says invalid input too! aW52YWxpZCBpbnB1dAo=
  • shwoseph
    shwoseph over 3 years
    Thanks! I really wish that error message had been a little more helpful.
  • ilkkachu
    ilkkachu over 3 years
    Note that the string you used here is slightly different than the original, as echo adds a trailing newline. The original string without it would be correctly padded as ...ifQ==. In this case, both versions do require padding though.
  • Grump
    Grump over 3 years
    echo -n '{"foo":"bar","baz":"bat"}' | base64 eyJmb28iOiJiYXIiLCJiYXoiOiJiYXQifQ==
  • dave_thompson_085
    dave_thompson_085 over 2 years
    Or str=$str===; echo ${str:0:${#str}&-4}. PS you wrote bash64 where you meant base64.
  • wisbucky
    wisbucky over 2 years
    @dave_thompson_085 Thanks for the catch! Fixed the typo.
  • DevWouter
    DevWouter about 2 years
    Keep in mind the "input length" referred to is in bytes. If referring to the number of characters, the length should be divisible by 4.
  • Admin
    Admin almost 2 years
    Thank you! I was looking for a way to fix the padding in bash.
  • Admin
    Admin almost 2 years
  • Admin
    Admin almost 2 years
    You are quite obviously passing data that is only partially base64-encoded to base64 -d. This does provide useful input to the current question. If you have a new question (like "why does this appear to work?"), then consider asking a new question.
  • Admin
    Admin almost 2 years
    Basically you’re just saying that you have the same behavior as what the OP is reporting.  This does not really answer the question.  If you have a different question, you can ask it by clicking Ask Question.  To get notified when this question gets new answers, you can follow this question.  Once you have enough reputation, you can also add a bounty to draw more attention to this question. – From Review