tito/src/base64.cpp

261 lines
5.0 KiB
C++

/*
* This file is a part of Tito - a cryptography library
* and is distributed under the 2-Clause BSD licence.
* Author: Tomasz Sowa <t.sowa@ttmath.org>
*/
/*
* Copyright (c) 2012-2022, Tomasz Sowa
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
*/
#include <string.h>
#include "base64.h"
namespace Tito
{
// 64 characters
const char * Base64::tabbase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
Base64::Base64()
{
padding = '=';
tabbase64_len = 64;
not_existing = 256; // first 8 bits are zero
require_padding_on_decoded_strings = true;
}
void Base64::SetPadding(char c)
{
for(size_t i=0 ; i<tabbase64_len ; ++i)
if( tabbase64[i] == c )
return;
padding = c;
}
void Base64::RequirePaddingOnDecodedStrings(bool require)
{
this->require_padding_on_decoded_strings = require;
}
void Base64::Convert3to4Pieces(const char * s, size_t len, unsigned int * tab4)
{
const unsigned char * tab3 = reinterpret_cast<const unsigned char*>(s);
tab4[0] = tab4[1] = tab4[2] = tab4[3] = 64;
if( len == 0 )
return;
tab4[0] = tab3[0] >> 2;
tab4[1] = (tab3[0] & 0x03) << 4;
if( len == 1 )
return;
tab4[1] = tab4[1] | ((tab3[1] & 0xf0) >> 4);
tab4[2] = (tab3[1] & 0x0f) << 2;
if( len == 2 )
return;
tab4[2] = (tab4[2]) | ((tab3[2] & 0xc0) >> 6);
tab4[3] = tab3[2] & 0x3f;
}
void Base64::ConvertFrom4to3Pieces(const unsigned int * tab4, unsigned int * tab3)
{
/*
tab4[0] and tab4[1] are always different from 'not_existing'
*/
tab3[0] = ((tab4[0] & 0x3f) << 2) | (( tab4[1] & 0x30 ) >> 4);
tab3[1] = tab3[2] = not_existing;
if( tab4[2] == not_existing )
return;
tab3[1] = ((tab4[1] & 0x0f) << 4) | (( tab4[2] & 0x3c ) >> 2);
if( tab4[3] == not_existing )
return;
tab3[2] = ((tab4[2] & 0x03) << 6) | (tab4[3] & 0x3f);
}
bool Base64::CharFromBase64(unsigned int from, unsigned int & to)
{
if( from>='A' && from<='Z' )
{
to = from-'A';
return true;
}
else
if( from>='a' && from<='z' )
{
to = from - 'a' + 'Z'-'A' + 1;
return true;
}
else
if( from>='0' && from<='9' )
{
to = from - '0' + 'Z'-'A' + 1 + 'z'-'a' + 1;
return true;
}
else
if( from == '+' )
{
to = tabbase64_len - 2;
return true;
}
else
if( from == '/' )
{
to = tabbase64_len - 1;
return true;
}
/*
such character does not exist in tabbase64 table
*/
return false;
}
void Base64::Save4PiecesToString(std::string & s, const unsigned int * tab4)
{
for(int i=0 ; i<4 ; ++i)
{
if( tab4[i] < tabbase64_len )
s += tabbase64[tab4[i]];
else
s += padding;
}
}
/*
*/
void Base64::Encode(const char * in, size_t len, std::string & out)
{
unsigned int tab4[4];
out.clear();
size_t new_size = len + len/3 + 3;
out.reserve(new_size);
for(size_t i=0 ; i < len ; i+=3)
{
Convert3to4Pieces(in+i, len-i, tab4);
Save4PiecesToString(out, tab4);
}
}
void Base64::Encode(const char * in, std::string & out)
{
size_t len = strlen(in);
Encode(in, len, out);
}
void Base64::Encode(const std::string & in, std::string & out)
{
Encode(in.c_str(), in.size(), out);
}
bool Base64::Decode(const char * in, size_t len, std::string & out)
{
return DecodeRaw(in, len, out);
}
bool Base64::Decode(const char * in, std::string & out)
{
size_t len = strlen(in);
return Decode(in, len, out);
}
bool Base64::Decode(const std::string & in, std::string & out)
{
return Decode(in.c_str(), in.size(), out);
}
bool Base64::Decode(const wchar_t * in, size_t len, std::string & out)
{
return DecodeRaw(in, len, out);
}
bool Base64::Decode(const wchar_t * in, std::string & out)
{
size_t len = wcslen(in);
return Decode(in, len, out);
}
bool Base64::Decode(const std::wstring & in, std::string & out)
{
return Decode(in.c_str(), in.size(), out);
}
} // namespace Tito