0

I'm trying to turn a string of a JWT token signature into a uint8array.

lX_aBSgGVYWd2FL6elRHoPJ2nab0IkmmX600cwZPCyK_SazZ-pzBUGDDQ0clthPVAtoS7roHg14xpEJlcSJUZBA7VTlPiDCOrkie_Hmulj765qS44t3kxAYduLhNQ-VN

The expected outcome should be the following with the size of 96 (base64url encoding)

[149, 127, 218, 5, 40, 6, 85, 133, 157, 216, 82, 250, 122, 84, 71, 160, 242, 118, 157, 166, 244, 34, 73, 166, 95, 173, 52, 115, 6, 79, 11, 34, 191, 73, 172, 217, 250, 156, 193, 80, 96, 195, 67, 71, 37, 182, 19, 213, 2, 218, 18, 238, 186, 7, 131, 94, 49, 164, 66, 101, 113, 34, 84, 100, 16, 59, 85, 57, 79, 136, 48, 142, 174, 72, 158, 252, 121, 174, 150, 62, 250, 230, 164, 184, 226, 221, 228, 196, 6, 29, 184, 184, 77, 67, 229, 77]

But I coudn't reverse engineer this I kept getting a size of 64 instead

[103, 10, 34, 6, 104, 125, 101, 234, 5, 23, 143, 198, 138, 228, 164, 134, 170, 116, 240, 159, 82, 223, 58, 73, 9, 49, 70, 51, 52, 229, 241, 5, 45, 146, 219, 135, 53, 177, 148, 181, 210, 164, 145, 59, 99, 95, 35, 46, 212, 62, 247, 142, 115, 234, 186, 88, 173, 148, 16, 157, 235, 29, 62, 93

Here's my function that was originally used for base16 and I'm now try to modify this to work for base64url

        const convert = (str) => {
            const segmented = str.match(/.{1,2}/g);
            const arr = segmented.map((segment, i) => {
                const powers = [16,1]; 
                const alphabets = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; 
                const two_bits = segment.split(''); 

                const result_arr = two_bits.map((hex, i) => {
                    const decimal = alphabets.indexOf(hex);
                    const sum_of_power = powers[i] * decimal;
                    return sum_of_power;
                });

                const result = result.reduce((a, b) => a + b);

                return result;
            });

            return new Uint8Array(arr);

        };

Any help would be appreciated!

A.C
  • 13
  • 1
  • 8

1 Answers1

0

Here's the base64url decode code, taken from my jose universal javascript module which I suggest you use for any and all JOSE functionality instead of writing your own.

const decodeBase64 = (encoded) => {
    return new Uint8Array(atob(encoded)
        .split('')
        .map((c) => c.charCodeAt(0)));
};

const decode = (input) => {
    try {
        return decodeBase64(input.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, ''));
    }
    catch (_a) {
        throw new TypeError('The input to be decoded is not correctly encoded.');
    }
};

decode('lX_aBSgGVYWd2FL6elRHoPJ2nab0IkmmX600cwZPCyK_SazZ-pzBUGDDQ0clthPVAtoS7roHg14xpEJlcSJUZBA7VTlPiDCOrkie_Hmulj765qS44t3kxAYduLhNQ-VN')

enter image description here

  • Thank you so much! Can I ask why do we need to replace these characters? input.replace(/-/g, '+').replace(/_/g, '/').replace(/\s/g, '')? What is this process called which I can look into it myself more deeply? – A.C Jan 10 '22 at 13:33
  • It's changing base64url back to regular base64 (albeit without the padding) so that it can be passed to `atob`. –  Jan 10 '22 at 13:51