Using
javascript
The most correct approach to check if a given
{String}
was encoded in base64 on the front end is enveloping in a block
try\catch
the return of the
atob()
compared to the encoded return itself since the
VM
of
javascript
of the browser will already throw an exception in case of failure.
Some examples here of the StackOverflow (Portuguese, English) community say that the following approach is most correct:
function isBase64(str) {
try {
return atob(str) ? true : false
} catch(e) {
return false
}
}
However this approach is incorrect because the following example would return a false-positive :
isBase64('jgjhgj hg') // true
When in fact the return of the above example using atob()
would be:
console.log(atob('jgjhgj hg')) // "á8'"
The most correct front-end approach
The correct one would be to "encode" the "decode" and compares the entry like this:
function isBase64(str) {
try {
return btoa(atob(str)) === str ? true : false
} catch(e) {
return false
}
}
isBase64('jgjhgj hg') // false
On the backend (NodeJs)
There are no native functions in NodeJS as btoa()
or atob()
so it is very common to use third-party modules or use Buffer
to achieve the same result
It's important to note that not all third-party libraries report exceptions or make a comparison against the entry, so it's easy to get false positives .
The following example uses Buffer
to encode and decode in addition to checking against the entry:
function atob(str) {
return new Buffer(str, 'base64').toString('binary');
}
function btoa(str) {
let buffer;
if ( str instanceof Buffer ) {
buffer = str
} else {
buffer = new Buffer(str.toString(), 'binary')
}
return buffer.toString('base64')
}
function isBase64(str) {
try {
return btoa(atob(str)) === str ? true : false
} catch(ex) {
false
}
}
Testing you can see that you do not report false positives :
console.log(isBase64('SGVsbG8gV29ybGQh')) // true
console.log(isBase64('jgjhgj hg')) // false
Using RegExp (opinionated)
If it is not possible to believe that the input (source) of {String}
is actually encoded (and therefore the need for verification), the use of RegExp
should not always be understood as "the best option" example expresses this question:
function isBase64(str) {
return /^([A-Za-z0-9+/]{4})*([A-Za-z0-9+/]{4}|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{2}==)$/.test(str)
}
isBase64('SGVsbG8gV29ybGQh') // true
isBase64('jgjhgj hg') // false
isBase64("regexnaofunciona") // true
isBase64("hoje") // true
isBase64("errado+tanto+faz") // true
The above expression is unsuccessful because it validates any {String}
with length of 4 or multiple of 4.
Note that if it is not possible to state that the {String}
of entry was actually encoded in base64 there is no guarantee that RegExp
above does not validate it thus forming a "false-positive" .