/* * This file is a part of Tito - a cryptography library * and is distributed under the 2-Clause BSD licence. * Author: Tomasz Sowa */ /* * 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 #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 ; irequire_padding_on_decoded_strings = require; } void Base64::Convert3to4Pieces(const char * s, size_t len, unsigned int * tab4) { const unsigned char * tab3 = reinterpret_cast(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