Henry
Henry

Reputation: 32885

How to add padding before decoding a base64 string?

ColdFusion's binaryDecode(input, 'base64') is picky because padding is mandatory.

What is the correct way to add padding with = to a base64 value?

1.) Ben Nadel uses:

value &= repeatString( "=", ( 4 - ( len( value ) % 4 ) ) );

2.) Arlo Carreon uses

<cfset res = Len(raw_str) % 4>
<cfif res eq 2>
     <cfset raw_str &= "==">
<cfelseif res eq 3>
     <cfset raw_str &= "=">
</cfif>

While they both seem to work, the 1st solution may return 1 to 4 ='s, while the 2nd solution may return 0, 1 or 2 ='s. Wikipedia on Base64 Padding seems to indicate that a valid base64 value should really have only 1 or 2 ='s.

1st solution seems to work with all base64 value lengths, but it may sometimes return 3 or 4 ='s which is kind of strange. Where as the 2nd solution may fail for base64 value that has remainder of 1. CF throws The input and output encodings are not same.

Upvotes: 6

Views: 10660

Answers (2)

Exo Flame
Exo Flame

Reputation: 147

Recently i was lookin at this

//START SAFE64
// map base64 to a url save chars  https://stackoverflow.com/a/40415059
const bsCharMap = {
    '+': '-',
    '/': '_',
    '=': '', // note we can safly drop this if we dont care about preseving length
}; // this-sythem-will_gen~~ ;  00~~ 000~ or 0000 dependant on byte length

const sbCharMap = {
    "-": "+"
    ,"_": "/"
}
//construct the regex so the code is defined in one place
const bsRegex = new RegExp(`[${Object.keys(bsCharMap).join()}]`, "g")
const sbRegex = new RegExp(`[${Object.keys(sbCharMap).join()}]`, "g")

function _btos(b64) {
    return  b64.replace(bsRegex, (match) => bsCharMap[match])
}
function _stob(s64) {
    let s = b64.replace(sbRegex, (match) => sbCharMap[match])
    while (s.length%4 !== 0) s += "=";
    return s
}

Note here _stob is using this to add padding back in dependent on length

update maybe for https://github.com/syonfox/skid

Upvotes: 1

Alex
Alex

Reputation: 7833

Padding is mandatory by specification (RFC 2045, 3548/4648).

Implementations MUST include appropriate pad characters at the end of encoded data unless the specification referring to this document explicitly states otherwise.

The correct way to fix missing padding is to append = until ( len(value) % 4 ) eq 0. This means a correctly padded Base64 string can only end:

  • without =
  • with =
  • with ==

The specification allows ("may") ignoring excessive padding.

If more than the allowed number of pad characters is found at the end of the string (e.g., a base 64 string terminated with "==="), the excess pad characters MAY also be ignored.


Can you elaborate what you mean by The input and output encodings are not same.? This sounds like an invalid Base64 encoded string. You may want to check what toBinary() returns for the input. It will probably tell you The parameter 1 of function ToBinary, which is now ... must be a base-64 encoded string, which is exactly the problem.

Upvotes: 9

Related Questions