3

I have the below .NET code to convert a string to Base64 encoding by first converting it to byte array. I tried different answers on Stack Overflow to convert the string in byte array and then use btoa() function for base64 encoding in JavaScript. But, I'm not getting the exact encoded value as shared below.

For string value,

BBFDC43D-4890-4558-BB89-50D802014A97

I need Base64 encoding as,

PcT9u5BIWEW7iVDYAgFKlw==

.NET code:

String str = "BBFDC43D-4890-4558-BB89-50D802014A97"
Guid guid = new Guid(str);
Console.WriteLine(guid);    // bbfdc43d-4890-4558-bb89-50d802014a97
Byte[] bytes = guid.ToByteArray();
Console.WriteLine(bytes);   // System.Byte[]
String s = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
Console.WriteLine(s);   // PcT9u5BIWEW7iVDYAgFKlw==

Currently, I tried with the below code, which is not producing the desired result:

function strToUtf8Bytes(str) {
  const utf8 = [];
  for (let ii = 0; ii < str.length; ii++) {
    let charCode = str.charCodeAt(ii);
    if (charCode < 0x80) utf8.push(charCode);
    else if (charCode < 0x800) {
      utf8.push(0xc0 | (charCode >> 6), 0x80 | (charCode & 0x3f));
    } else if (charCode < 0xd800 || charCode >= 0xe000) {
      utf8.push(0xe0 | (charCode >> 12), 0x80 | ((charCode >> 6) & 0x3f), 0x80 | (charCode & 0x3f));
    } else {
      ii++;
      // Surrogate pair:
      // UTF-16 encodes 0x10000-0x10FFFF by subtracting 0x10000 and
      // splitting the 20 bits of 0x0-0xFFFFF into two halves
      charCode = 0x10000 + (((charCode & 0x3ff) << 10) | (str.charCodeAt(ii) & 0x3ff));
      utf8.push(
        0xf0 | (charCode >> 18),
        0x80 | ((charCode >> 12) & 0x3f),
        0x80 | ((charCode >> 6) & 0x3f),
        0x80 | (charCode & 0x3f),
      );
    }
  }
  return utf8;
}

const str = "BBFDC43D-4890-4558-BB89-50D802014A97";
const strByteArr = strToUtf8Bytes(str);
const strBase64 = btoa(strByteArr);
// NjYsNjYsNzAsNjgsNjcsNTIsNTEsNjgsNDUsNTIsNTYsNTcsNDgsNDUsNTIsNTMsNTMsNTYsNDUsNjYsNjYsNTYsNTcsNDUsNTMsNDgsNjgsNTYsNDgsNTAsNDgsNDksNTIsNjUsNTcsNTU=
12
  • Could you also provide the JS code you use? Commented Mar 26, 2019 at 11:40
  • maybe dupplicate from: stackoverflow.com/questions/246801/… Commented Mar 26, 2019 at 11:45
  • This is not the duplicate of that question because I'm using btoa() to encode but I'm concerned about the byte array here. Commented Mar 26, 2019 at 11:51
  • 1
    Are you sure that PcT9u5BIWEW7iVDYAgFKlw== is the base64 representation of the string BBFDC43D-4890-4558-BB89-50D802014A97 Commented Mar 26, 2019 at 11:51
  • 1
    You should post your javascript code. And again, as I said before, your code is not converting that string to base64, it's taking that string as a bunch of hex values, converting it to base 10, and then encoding the resulting byte array to base 64 Commented Mar 26, 2019 at 11:59

3 Answers 3

4

Your problem is caused by the following:

  • btoa() is using ASCII encoding
  • guid.ToByteArray(); does not use ASCII encoding

If you modify your C# code like this:

String str = "BBFDC43D-4890-4558-BB89-50D802014A97";
//Guid guid = new Guid(str);
//Console.WriteLine(guid);
// bbfdc43d-4890-4558-bb89-50d802014a97
//Byte[] bytes = guid.ToByteArray();
byte[] bytes = System.Text.Encoding.ASCII.GetBytes(str);
//Console.WriteLine(bytes);   // System.Byte[]
String s = Convert.ToBase64String(bytes, Base64FormattingOptions.InsertLineBreaks);
Console.WriteLine(s);

You will get the following output:

QkJGREM0M0QtNDg5MC00NTU4LUJCODktNTBEODAyMDE0QTk3

Which will be the same string as the one returned from the btoa() function:

var rawString = "BBFDC43D-4890-4558-BB89-50D802014A97";
var b64encoded = btoa(rawString);
console.log(b64encoded);

Output:

QkJGREM0M0QtNDg5MC00NTU4LUJCODktNTBEODAyMDE0QTk3

UPDATE - Since you can't modify the C# code

You should adapt your Javascript code by combining Piotr's answer and this SO answer

function guidToBytes(guid) {
    var bytes = [];
    guid.split('-').map((number, index) => {
        var bytesInChar = index < 3 ? number.match(/.{1,2}/g).reverse() : number.match(/.{1,2}/g);
        bytesInChar.map((byte) => { bytes.push(parseInt(byte, 16)); })
    });
    return bytes;
}

function arrayBufferToBase64(buffer) {
    var binary = '';
    var bytes = new Uint8Array(buffer);
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode(bytes[i]);
    }
    return btoa(binary);
}

var str = "BBFDC43D-4890-4558-BB89-50D802014A97";
var guidBytes = guidToBytes(str);
var b64encoded = arrayBufferToBase64(guidBytes);
console.log(b64encoded);

Output:

PcT9u5BIWEW7iVDYAgFKlw==
Sign up to request clarification or add additional context in comments.

4 Comments

ASCII or UTF8 will make no difference here, since until codepoint 127 they are identical.
@marko I can't change the .NET code as it is a legacy code. I only have to replicate that in JS.
@HimanshuAggarwal I just updated the answer with the Javascript modifications you need to make.
I've been trying to reverse this to go backwards as needed but am unable to get there, any advice on converting back?
2

The problem with your code is representation of Guid. In C# code you are converting "BBFDC43D-4890-4558-BB89-50D802014A97" into UUID which is a 128-bit number. In JavaScript code, you are doing something else. You iterate through the string and calculate a byte array of a string. They are simply not equal. Now you have to options

  1. Implement proper guid conversion in JS (this may help: https://gist.github.com/daboxu/4f1dd0a254326ac2361f8e78f89e97ae)
  2. In C# calculate byte array in the same way as in JS

Comments

1

Your string is a hexadecimal value, which you use to create a GUID. Then you convert the GUID into a byte array with:

Byte[] bytes = guid.ToByteArray();

The GUID is a 16-byte value which can be represented as a hexadecimal value. When you convert this GUID into a byte array, you will get the 16 bytes of the value, not the byte representation of the hexadecimal value.

In the provided JavaScript function you are doing something else: You are converting the string directly to a byte array.

In C# you do the equivalent with an Encoding:

String str = "BBFDC43D-4890-4558-BB89-50D802014A97";
Byte[] bytes = Encoding.UTF8.GetBytes(str);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.