Base64 normalization in PHP
By default PHP provides base64_encode and base64_decode functions to support only the main Base64 standard. Therefore, if you want to support additional standards, you must “extend” these functions. For example, you cannot use
base64_decode to decode a screenshot downloaded from Google PageSpeed API. This is due to the fact that Google uses a modified standard named Base64URL. The same is true and vice versa, because some services may accept only specific “standards”. Therefore, to avoid errors, you must normalize Base64 value before decoding or after encoding.
Usually you have to replace 62-63 index characters and in such cases the
strtr function is your best friend. For example, to normalize a Base64URL value to Base64 use the following:
<?php $url = 'PDw_Pz8-Pg'; $b64 = strtr($url, '-_', '+/'); // $url becomes "PDw/Pz8+Pg" echo base64_decode($b64, true); //-> "<<???>>"
Another useful function is
rtrim (in cases when the standard does not use a padding character):
<?php $b64 = base64_encode('<<???>>'); $nopad = rtrim($b64, '='); echo $b64; //-> "PDw/Pz8+Pg==" echo $nopad; //-> "PDw/Pz8+Pg"
When standard specifies another padding character, replace
= as follows:
<?php $b64 = base64_encode('<<???>>'); echo str_replace('=', '-', $b64); //-> "PDw/Pz8+Pg--"
If the standard requires a fixed encoded line-length, use the
chunk_split function. For example, the following will normalize Base64 value to comply with the requirements of RFC 1421:
<?php $b64 = base64_encode($data); $pem = chunk_split($b64, 64, "\r\n");
As you can see, most examples show how to encode the data, because to decode the Base64 is much easier. Most often you just need to use the
strtr function to replace 62-63 index characters. The trick is that
base64_decode ignores invalid characters from the Base64 value and will “forcefully” decode it. By the way, as a full example of normalization, check Base64URL implementation in PHP.