base64 -d decodes, but says invalid input
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
Related videos on Youtube
shwoseph
Updated on September 18, 2022Comments
-
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 over 3 yearsI 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 over 3 yearsMine says invalid input too! aW52YWxpZCBpbnB1dAo=
-
-
shwoseph over 3 yearsThanks! I really wish that error message had been a little more helpful.
-
ilkkachu over 3 yearsNote 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 over 3 years
echo -n '{"foo":"bar","baz":"bat"}' | base64 eyJmb28iOiJiYXIiLCJiYXoiOiJiYXQifQ==
-
dave_thompson_085 over 2 yearsOr
str=$str===; echo ${str:0:${#str}&-4}
. PS you wrotebash64
where you meantbase64
. -
wisbucky over 2 years@dave_thompson_085 Thanks for the catch! Fixed the typo.
-
DevWouter about 2 yearsKeep 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 almost 2 yearsThank you! I was looking for a way to fix the padding in bash.
-
Admin almost 2 yearsPlease, don't post images of text
-
Admin almost 2 yearsYou 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 almost 2 yearsBasically 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