Page 1 of 1

Base64 encode/decode, c++ w. std::string

Posted: Thu Feb 11, 2010 4:15 pm
by Kroki
Hello Users of The Chaos Rift, some of you may already know me from irc ;-)

I just signed up and wanted to contribute something,
This little code I wrote awhile back, might be interesting for someone.

Base64 is a standardized MIME content transfer encoding,
it can turn 8bit data into 7bit thus allowing to e.g. transfer binary data (attachments) over smtp.

Base64 is used in:
SMTP-Auth
SMTP Attachments
HTTP Basic Auth
and so on

The code is licensed under this MIT-license:

Code: Select all

/*
        Copyright (c) 2009/2010 Kroki

        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:

        The above copyright notice and this permission notice shall be included in
        all copies or substantial portions of the Software.

        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
        THE SOFTWARE.*/
required headers:

Code: Select all

#include <string>
the functions:

Code: Select all

/*Note: this code doesn't insert line breaks into the output,
              neither does it decode(ignore) them properly */
void Base64Encode(const std::string msg, std::string &destination)
{
    std::string in = "aaa", //lets us work with the first 3 bytes
                out = "aaaa"; // -"- 4 bytes

    const char b64chars[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";

    unsigned int    msgsize        = msg.size(),
                    processbytes   = 3,
                    fillbytes      = 3-msgsize%3 == 3 ? 0 : 3-msgsize%3;

    destination.clear();
    destination.reserve((msgsize)*4/3+1);

    for(unsigned int i = 0; processbytes == 3; i += processbytes)
    {
        if(msgsize - i < 3)
        {
            processbytes = msgsize - i;
            if(!processbytes)
                break;
        }

        in = msg.substr(i, processbytes);

        out[0] = (in[0]>>2)&63;
        out[1] = ((in[0]<<4)&63) + ((in[1]>>4)&15);
        out[2] = ((in[1]<<2)&60) + ((in[2]>>6)&3);
        out[3] = (in[2]&63);

        for(unsigned int j = 0; j < processbytes+1; j++)
        {
            out[j] = b64chars[(unsigned char)out[j]];
        }

        destination.append(out.substr(0, processbytes+1));
    }

    for(unsigned int i = 0; i < fillbytes; i++)
    {
        destination.append("=");
    }
    return;
}

bool Base64Decode(std::string msg, std::string &destination)
{
    std::string in = "aaaa", //lets us work with the first 4 bytes
                out = "aaa"; // -"- 3 bytes


    unsigned int    msgsize        = msg.size(),
                    processbytes   = 4,
                    fillbytes      = 0;

    destination.clear();
    destination.reserve((msgsize)/4/3+1);

    if(msgsize%4 != 0)
    {
        return false;
    }

    for(unsigned int i = msgsize-1; i > msgsize-3; i--)
    {
        if(msg[i] == '=')
            fillbytes++;
        else
            break;
    }

    for(unsigned int i = 0; processbytes == 4; i += processbytes)
    {
        if(msgsize - i - fillbytes < 4)
        {
            processbytes = msgsize - i - fillbytes;
            if(!processbytes)
                break;
        }

        in = msg.substr(i, processbytes);

        for(unsigned int j = 0; j < processbytes; j++)
        {
            if(in[j] >= 'A' and in[j] <= 'Z')
                in[j] -= 'A';
            else if(in[j] >= 'a' and in[j] <= 'z')
                in[j] -= 'a'-26;
            else if(in[j] >= '0' and in[j] <= '9')
                in[j] -= '0'-52;
            else if(in[j] == '+')
                in[j] = 62;
            else if(in[j] == '/')
                in[j] = 63;
            else if(in[j] == '=')
                in[j] = 0;
            else
                return false;
        }

        out[0] = ((in[0]<<2)&252) + ((in[1]>>4)&3);
        out[1] = ((in[1]<<4)&240) + ((in[2]>>2)&15);
        out[2] = ((in[2]<<6)&192) + ((in[3])&63);

        destination.append(out.substr(0, processbytes-1));
    }
    return true;
}
Usage: pretty self explaining :)

greetz Kroki.