[erlang-questions] base64:decode fails on facebook base64 encoded strings

Michael Santos michael.santos@REDACTED
Thu Dec 29 14:58:35 CET 2011


On Thu, Dec 29, 2011 at 08:30:09AM +0400, Max Bourinov wrote:
> So Erlangers,
> 
> I wrote about this little bug in Facebook and I got an answer!
> 
> >>I believe the trailing = is an optional padding in base64 your code needs
> to accept base64 with and without trailing '=' characters. See last part of
> http://email.about.com/cs/standards/a/base64_encoding.htm
> 
> This is what they said. That is very interesting, I personally would not
> omit data from protocol specification, but it appears that if it possible.
> Anyway I didn't see anything about omitting here
> http://tools.ietf.org/html/rfc1421 or http://tools.ietf.org/html/rfc2045

There is something about dropping the padding in RFC 4648:

5.  Base 64 Encoding with URL and Filename Safe Alphabet

The pad character "=" is typically percent-encoded when used in an URI
[9], but if the data length is known implicitly, this can be avoided by
skipping the padding; see section 3.2.

> So, if you ever face such a loose implementation of base64 here is a
> snippet that might help you to deal with it:
> 
> -spec fb_decode_base64(Base64 :: list()) -> binary() | error.
> fb_decode_base64(Base64) when is_list(Base64) ->
>     try base64:decode(Base64)
>     catch
>         error:_ -> % could be missing =
>         	try base64:decode(Base64 ++ "=")
>         	catch
>         		error:_ -> % could be missing ==
>         			try base64:decode(Base64 ++ "==")
>         			catch
>         				error:_ -> % base64 is really wrong. we cannot fix it
>         					error
>         			end
>         	end
> 
>     end.

The length can be used to figure out the padding (not exactly the same
as your code, throws an exception on bad data rather than returning
an error):

-module(tt).
-export([fb_decode_base64/1]).

fb_decode_base64(Base64) when is_list(Base64) ->
    decode(list_to_binary(Base64)).

decode(Base64) when byte_size(Base64) rem 4 == 3 ->
    base64:decode(<<Base64/bytes, "=">>);
decode(Base64) when byte_size(Base64) rem 4 == 2 ->
    base64:decode(<<Base64/bytes, "==">>);
decode(Base64) ->
    base64:decode(Base64).



More information about the erlang-questions mailing list