Is it safe to pass raw base64 encoded strings via GET parameters?
No, you would need to url-encode it, since base64 strings can contain the "+", "=" and "/" characters which could alter the meaning of your data - look like a sub-folder.
Valid base64 characters are below.
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
(['
instead of {["
). –
Icelander There are additional base64 specs. (See the table here for specifics ). But essentially you need 65 chars to encode: 26 lowercase + 26 uppercase + 10 digits = 62.
You need two more ['+', '/'] and a padding char '='. But none of them are url friendly, so just use different chars for them and you're set. The standard ones from the chart above are ['-', '_'], but you could use other chars as long as you decoded them the same, and didn't need to share with others.
I'd recommend just writing your own helpers. Like these from the comments on the php manual page for base64_encode:
function base64_url_encode($input) {
return strtr(base64_encode($input), '+/=', '-_.');
}
function base64_url_decode($input) {
return base64_decode(strtr($input, '-_.', '+/='));
}
urlencode
as suggested by rodrigo-silveira's answer. Creating two new functions to save few chars in url length, it's like entering in your house passing through the window instead of just using the door. –
Pry unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
–
Toilette ,
should be urlencoded to %2C
, I suggest using ._-
instead of -_,
like the only variant in en.wikipedia.org/wiki/Base64#Variants_summary_table that keeps the trailing = –
Laos .
which is then not considered a part of the URL by some mail clients. I still recommend the replacement proposed here, though, because some mail clients optimize //
to /
in URLs and also not accept trailing =
-signs as part of an URL. –
Pinery minus
and underline
(with equals
for pad), as Joe Flynn's answer describes. –
Mantelletta No, you would need to url-encode it, since base64 strings can contain the "+", "=" and "/" characters which could alter the meaning of your data - look like a sub-folder.
Valid base64 characters are below.
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=
(['
instead of {["
). –
Icelander @joeshmo Or instead of writing a helper function, you could just urlencode the base64 encoded string. This would do the exact same thing as your helper function, but without the need of two extra functions.
$str = 'Some String';
$encoded = urlencode( base64_encode( $str ) );
$decoded = base64_decode( urldecode( $encoded ) );
/
character if you pass it not as a GET parameter, but as a path in the URL. It will change your path if you don't replace /
with something else on both sides. –
Harlie url = URLEncoder.encode(Base64.getEncoder().encodeToString(value), StandardCharsets.UTF_8)
Base64.getDecoder().decode(URLDecoder.decode(code, StandardCharsets.UTF_8))
–
Emperor +
. See Jeffory Beckers' answer for the details. –
Mantelletta Introductory Note I'm inclined to post a few clarifications since some of the answers here were a little misleading (if not incorrect).
The answer is NO, you cannot simply pass a base64 encoded parameter within a URL query string since plus signs are converted to a SPACE inside the $_GET global array. In other words, if you sent test.php?myVar=stringwith+sign to
//test.php
print $_GET['myVar'];
the result would be:
stringwith sign
The easy way to solve this is to simply urlencode()
your base64 string before adding it to the query string to escape the +, =, and / characters to %## codes.
For instance, urlencode("stringwith+sign")
returns stringwith%2Bsign
When you process the action, PHP takes care of decoding the query string automatically when it populates the $_GET global. For example, if I sent test.php?myVar=stringwith%2Bsign to
//test.php
print $_GET['myVar'];
the result would is:
stringwith+sign
You do not want to urldecode()
the returned $_GET string as +'s will be converted to spaces.
In other words if I sent the same test.php?myVar=stringwith%2Bsign to
//test.php
$string = urldecode($_GET['myVar']);
print $string;
the result is an unexpected:
stringwith sign
It would be safe to rawurldecode()
the input, however, it would be redundant and therefore unnecessary.
<br>
, so no need to type much HTML. I hope this helps, I edited your answer a little to even more improve it. –
Trondheim Yes and no.
The basic charset of base64 may in some cases collide with traditional conventions used in URLs. But many of base64 implementations allow you to change the charset to match URLs better or even come with one (like Python's urlsafe_b64encode()
).
Another issue you may be facing is the limit of URL length or rather — lack of such limit. Because standards do not specify any maximum length, browsers, servers, libraries and other software working with HTTP protocol may define its' own limits.
Its a base64url encode you can try out, its just extension of joeshmo's code above.
function base64url_encode($data) {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function base64url_decode($data) {
return base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}
Base64.getUrlEncoder().withoutPadding().encodeToString()
–
Michikomichon I don't think that this is safe because e.g. the "=" character is used in raw base 64 and is also used in differentiating the parameters from the values in an HTTP GET.
If you have sodium extension installed and need to encode binary data, you can use sodium_bin2base64
function which allows you to select url safe variant.
for example encoding can be done like that:
$string = sodium_bin2base64($binData, SODIUM_BASE64_VARIANT_URLSAFE);
and decoding:
$result = sodium_base642bin($base64String, SODIUM_BASE64_VARIANT_URLSAFE);
For more info about usage, check out php docs:
https://www.php.net/manual/en/function.sodium-bin2base64.php https://www.php.net/manual/en/function.sodium-base642bin.php
For url safe encode, like base64.urlsafe_b64encode(...)
in Python the code below, works to me for 100%
function base64UrlSafeEncode(string $input)
{
return str_replace(['+', '/'], ['-', '_'], base64_encode($input));
}
I know I'm 14 years too late, but one way to absolutely positively guarantee that you are getting alpha-numeric text (no punctuation, symbols, etc) would be to use these functions:
function hex_encode($input) {
return bin2hex($input);
}
function hex_decode($input) {
return pack("H*", $input);
}
You can pass your base64_encode()'d string through the hex_encode and get back something like this:
2821583e34f623d682f26684e5c27
I know it inflates the size of the string, but you're guaranteed not to have to worry about +, /, =, etc.
In theory, yes, as long as you don't exceed the maximum url and/oor query string length for the client or server.
In practice, things can get a bit trickier. For example, it can trigger an HttpRequestValidationException on ASP.NET if the value happens to contain an "on" and you leave in the trailing "==".
For those using .NET, they can utilize the Encode
and Decode
methods of Base64UrlEncoder
class which is found in package Microsoft.IdentityModel.Tokens v6.31.0
.
© 2022 - 2024 — McMap. All rights reserved.