Salizar Marxx
Salizar Marxx

Reputation: 933

Base 64 decode fails with invalid length

I'm attempt to convert a base64 string generated from javascript code using C# code, but I'm running into an invalid length message.

The string is MQA5ADIAMwA3ADgANwA6ADAA0

It should convert back to 1923787:0

I tried a number of online decoders and some of them worked but a couple failed with the same invalid length error. I'll not post links here, but needless to say they were able to convert it back to the expected string.

C# Decode

var t = "MQA5ADIAMwA3ADgANwA6ADAA0";
var x = Convert.FromBase64String(t);

Javascript encoder:

var encoder = function (mL) {
    if (!mL || mL === '') {
        return '';
    }
    var ei = [];
    var V;
    for (V = 0; V < mL.length; V++) {
        ei.push(mL.charCodeAt(V) % 256);
        ei.push(Math.floor(mL.charCodeAt(V) / 256));
    }
    ei.push(0);
    ei.push(0);
    var sf = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
    var gF = [],
        hO;
    for (V = 0; V < ei.length - 1; V += 3) {
        hO = ei[V] * 0x10000 + ei[V + 1] * 0x100 + ei[V + 2];
        gF.push(sf.charAt(Math.floor(hO / 0x40000)));
        gF.push(sf.charAt(Math.floor(hO / 0x1000) % 0x40));
        gF.push(sf.charAt(Math.floor(hO / 0x40) % 0x40));
        gF.push(sf.charAt(hO % 0x40));
    }
    var vr = Math.ceil(mL.length * 16 / 6);
    while (gF.length > vr) {
        gF.pop();
    }
    if ((gF.length % 4) === 3) {
        gF.push('1');
    } else if ((gF.length % 4) === 2) {
        gF.push('2');
    } else if ((gF.length % 4) === 0) {
        gF.push('0');
    }
    return gF.join('');
};

Upvotes: 0

Views: 1521

Answers (4)

Paul S.
Paul S.

Reputation: 66364

First, change your for which does the encode to

for (V = 0; V < ei.length - 3; V += 3) {

then instead of

var vr = Math.ceil(mL.length * 16 / 6);
while (gF.length > vr) {
    gF.pop();
}
if ((gF.length % 4) === 3) {
    gF.push('1');
} else if ((gF.length % 4) === 2) {
    gF.push('2');
} else if ((gF.length % 4) === 0) {
    gF.push('0');
}

do

switch (ei.length % 3) {
    case 0:
        break;
    case 1:
        gF[gF.length - 2] = '=';
    case 2:
        gF[gF.length - 1] = '=';
        break;
}

Now you'll get

encoder("1923787:0"); // "MQA5ADIAMwA3ADgANwA6ADA="

Which is valid Base64,

What's going on? Base64 uses = to designate the number of bytes we started with, in terms of how short we were from the next multiple of 3, so this swaps out the final characters (which were the zero symbol due to not having any bits) with those = signs.

The modification to the loop is to end the loop at the right place - you were overshooting with just - 1 because say you were at V >= ei.length - 3 but V < ei.length - 1, i.e. V = ei.length - 3 or V = ei.length - 2 you would enter the next iteration at V = ei.length or V = ei.length + 1, at which point ei[V], ei[V+1], ei[V+2] would be undefined

Upvotes: 2

Tim
Tim

Reputation: 15237

The correct Base64 encoding of your input string is "MQA5ADIAMwA3ADgANwA6ADAA" - without the trailing zero that you show. For some reason your javascript code is adding that zero. I'm not sure why. But that makes it an invalid string.

I'm guessing the padding, which should be '=' is being added as '0' by the javascript algorithm. Just a thought though.

Upvotes: 0

DavidG
DavidG

Reputation: 119116

Your encoding routine is putting an extra 0 on the end of the string, remove it and the decode will work (into a Unicode string)

Example code:

var original = "1923787:0";
var bytesFromOriginal = System.Text.Encoding.Unicode.GetBytes(original);
var base64string = Convert.ToBase64String(bytesFromOriginal);

base64string = "MQA5ADIAMwA3ADgANwA6ADAA";
var bytesFromEncodedString = Convert.FromBase64String(base64string);
var decodedString = System.Text.Encoding.Unicode.GetString(bytesFromEncodedString);

Upvotes: 0

Gaurav S
Gaurav S

Reputation: 1009

See if this helps.

string x = Encoding.UTF8.GetString(Convert.FromBase64String("MQA5ADIAMwA3ADgANwA6ADAA0"));

Link: How do I decode a base64 encoded string?

Upvotes: 0

Related Questions