/* * 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. * */ #ifndef headerfile_tito_base64 #define headerfile_tito_base64 #include namespace Tito { class Base64 { public: Base64(); /* * padding character * default '='; */ void SetPadding(char c); /* * if false then allow the strings passed to Decode(...) methods to now have the trailing padding characters ('=') * default: true */ void RequirePaddingOnDecodedStrings(bool require); void Encode(const char * in, size_t len, std::string & out); void Encode(const char * in, std::string & out); void Encode(const std::string & in, std::string & out); bool Decode(const char * in, size_t len, std::string & out); bool Decode(const char * in, std::string & out); bool Decode(const std::string & in, std::string & out); bool Decode(const wchar_t * in, size_t len, std::string & out); bool Decode(const wchar_t * in, std::string & out); bool Decode(const std::wstring & in, std::string & out); private: static const char * tabbase64; size_t tabbase64_len; char padding; unsigned int not_existing; bool require_padding_on_decoded_strings; void Convert3to4Pieces(const char * s, size_t len, unsigned int * tab4); void ConvertFrom4to3Pieces(const unsigned int * tab4, unsigned int * tab3); bool CharFromBase64(unsigned int from, unsigned int & to); void Save4PiecesToString(std::string & s, const unsigned int * tab4); template bool Make4pieces(const CharType * s, size_t len, unsigned int * tab4); template void Save3PiecesToString(const unsigned int * tab3, StringType & s); template bool DecodeRaw(const CharType * in, size_t len, StringType & out); }; template bool Base64::Make4pieces(const CharType * s, size_t len, unsigned int * tab4) { for(size_t i=0 ; i<4 ; ++i) { if( i >= len || s[i] == padding ) tab4[i] = not_existing; else if( !CharFromBase64(static_cast(s[i]), tab4[i]) ) return false; } return true; } template void Base64::Save3PiecesToString(const unsigned int * tab3, StringType & s) { for(int i=0 ; i<3 ; ++i) { if( tab3[i] != not_existing ) s += tab3[i]; } } template bool Base64::DecodeRaw(const CharType * in, size_t len, StringType & out) { unsigned int tab3[3]; unsigned int tab4[4]; out.clear(); size_t new_size = len - len/3 + 3; out.reserve(new_size); if( require_padding_on_decoded_strings && len % 4 != 0 ) return false; while( len > 0 ) { if( !Make4pieces(in, len, tab4) ) return false; ConvertFrom4to3Pieces(tab4, tab3); Save3PiecesToString(tab3, out); in += 4; len = (len >= 4) ? len - 4 : 0; } return true; } } // namespace Tito #endif