Search code examples
c++base64nul

C++: How to encode a std::string into base64 without losing NUL character


I am working on getting someone else's code up and running. The code is written in C++. The part that is failing is when it converts a std::string to base64:

std::string tmp = "\0";
tmp.append(strUserName);
tmp.append("\0");
tmp.append(strPassword);
tmp = base64_encode(tmp.c_str(), tmp.length());

where base64 is:

std::string base64_encode(char const* bytes_to_encode, unsigned int in_len) {
    std::string ret;
    int i = 0;
    int j = 0;
    unsigned char char_array_3[3];
    unsigned char char_array_4[4];

    while (in_len--) {
        char_array_3[i++] = *(bytes_to_encode++);
        if (i == 3) {
            char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
            char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
            char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
            char_array_4[3] = char_array_3[2] & 0x3f;

            for(i = 0; (i <4) ; i++)
                ret += base64_chars[char_array_4[i]];
            i = 0;
        }
    }

    if (i)
    {
        for(j = i; j < 3; j++)
            char_array_3[j] = '\0';

        char_array_4[0] = (char_array_3[0] & 0xfc) >> 2;
        char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4);
        char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6);
        char_array_4[3] = char_array_3[2] & 0x3f;

        for (j = 0; (j < i + 1); j++)
            ret += base64_chars[char_array_4[j]];

        while((i++ < 3))
            ret += '=';

    }

    return ret;

}

It uses the 'tmp' string to make a call to a server and it's imperative that the base64 string has the two NUL characters embedded within it (before strUserName and before strPassword). However, it seems that since the code is passing tmp as a c_str(), the NUL characters are being stripped. Is there a good solution for this? Thanks.

Update I guess I should add that the code includes "#include <asm/errno.h>" which I googled for and didn't find compatibility for macOS so I just commented it out.. Not sure if that is making things not work but I doubt it. Full disclosure.


Solution

  • std::string tmp = "\0"; and tmp.append("\0"); don't add any '\0' characters to tmp. The versions of std::string::string and std::string::append that take a const char* take a NUL-terminated C-style string, so they stop as soon as they see a NUL character.

    To actually add a NUL character to your string, you'll need to use the constructor and append methods that take a length along with a const char*, or the versions that take a count and a char:

    std::string tmp("\0", 1);
    tmp.append(strUserName);
    tmp.append("\0", 1);
    tmp.append(strPassword);
    tmp = base64_encode(tmp.c_str(), tmp.length());