312 lines
6.1 KiB
C++
312 lines
6.1 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) 2018, 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 "base32.h"
|
|
|
|
|
|
namespace Tito
|
|
{
|
|
|
|
|
|
// 64 characters
|
|
const char * Base32::tabbase32 = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
|
|
|
|
|
|
|
|
Base32::Base32()
|
|
{
|
|
padding = '=';
|
|
tabbase32_len = 32;
|
|
not_existing = 256; // first 8 bits are zero
|
|
}
|
|
|
|
|
|
|
|
void Base32::SetPadding(char c)
|
|
{
|
|
for(size_t i=0 ; i<tabbase32_len ; ++i)
|
|
if( tabbase32[i] == c )
|
|
return;
|
|
|
|
padding = c;
|
|
}
|
|
|
|
|
|
void Base32::Convert5to8Pieces(const char * s, size_t len, unsigned int * tab8)
|
|
{
|
|
const unsigned char * tab5 = reinterpret_cast<const unsigned char*>(s);
|
|
|
|
for(size_t i=0 ; i<8 ; ++i)
|
|
tab8[i] = 32;
|
|
|
|
if( len == 0 )
|
|
return;
|
|
|
|
tab8[0] = tab5[0] >> 3;
|
|
tab8[1] = (tab5[0] & 0x07) << 2;
|
|
|
|
if( len == 1 )
|
|
return;
|
|
|
|
tab8[1] = tab8[1] | ((tab5[1] & 0xc0) >> 6);
|
|
tab8[2] = (tab5[1] >> 1) & 0x1f;
|
|
tab8[3] = (tab5[1] & 0x01) << 4;
|
|
|
|
if( len == 2 )
|
|
return;
|
|
|
|
tab8[3] = tab8[3] | ((tab5[2] & 0xf0) >> 4);
|
|
tab8[4] = ((tab5[2] & 0x0f) << 1);
|
|
|
|
if( len == 3 )
|
|
return;
|
|
|
|
tab8[4] = tab8[4] | (tab5[3] & 0x80) >> 7;
|
|
tab8[5] = (tab5[3] >> 2) & 0x1f;
|
|
tab8[6] = (tab5[3] & 0x03) << 3;
|
|
|
|
if( len == 4 )
|
|
return;
|
|
|
|
tab8[6] = tab8[6] | ((tab5[4] & 0xe0) >> 5);
|
|
tab8[7] = tab5[4] & 0x1f;
|
|
}
|
|
|
|
|
|
|
|
void Base32::ConvertFrom8to5Pieces(const unsigned int * tab8, unsigned int * tab5)
|
|
{
|
|
/*
|
|
tab8[0] and tab8[1] are always different from 'not_existing'
|
|
*/
|
|
|
|
for(size_t i=0 ; i<5 ; ++i)
|
|
tab5[i] = not_existing;
|
|
|
|
tab5[0] = ((tab8[0] & 0x1f) << 3) | ((tab8[1] & 0x1c) >> 2);
|
|
|
|
// in order to exist tab5[1] a tab8[2] and tab8[3] should exist
|
|
if( tab8[2] == not_existing )
|
|
return;
|
|
|
|
if( tab8[3] == not_existing )
|
|
return; // IMPROVE ME this is an error, cannot be such a string as input base32
|
|
|
|
tab5[1] = (tab8[1] & 0x03) << 6;
|
|
tab5[1] = tab5[1] | ((tab8[2] & 0x1f) << 1);
|
|
tab5[1] = tab5[1] | ((tab8[3] & 0x10) >> 4);
|
|
|
|
// in order to exist tab5[2] a tab8[4] should exist
|
|
if( tab8[4] == not_existing )
|
|
return;
|
|
|
|
tab5[2] = (tab8[3] & 0x0f) << 4;
|
|
tab5[2] = tab5[2] | ((tab8[4] & 0x1e) >> 1);
|
|
|
|
// in order to exist tab5[3] a tab8[5] and tab8[6] should exist
|
|
if( tab8[5] == not_existing )
|
|
return;
|
|
|
|
if( tab8[6] == not_existing )
|
|
return; // IMPROVE ME this is an error, cannot be such a string as input base32
|
|
|
|
tab5[3] = (tab8[4] & 0x01) << 7;
|
|
tab5[3] = tab5[3] | ((tab8[5] & 0x1f) << 2);
|
|
tab5[3] = tab5[3] | ((tab8[6] & 0x18) >> 3);
|
|
|
|
if( tab8[7] == not_existing )
|
|
return;
|
|
|
|
tab5[4] = (tab8[6] & 0x07) << 5;
|
|
tab5[4] = tab5[4] | (tab8[7] & 0x1f);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
bool Base32::CharFromBase32(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';
|
|
return true;
|
|
}
|
|
else
|
|
if( from>='2' && from<='7' )
|
|
{
|
|
to = from - '2' + 'Z'-'A' + 1;
|
|
return true;
|
|
}
|
|
|
|
/*
|
|
such character does not exist in tabbase32 table
|
|
*/
|
|
return false;
|
|
}
|
|
|
|
|
|
|
|
bool Base32::Make8pieces(const char * s, unsigned int * tab8)
|
|
{
|
|
for(size_t i=0 ; i<8 ; ++i)
|
|
{
|
|
if( s[i] == padding )
|
|
tab8[i] = not_existing;
|
|
else
|
|
if( !CharFromBase32(s[i], tab8[i]) )
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
|
|
void Base32::Save8PiecesToString(std::string & s, const unsigned int * tab8)
|
|
{
|
|
for(int i=0 ; i<8 ; ++i)
|
|
{
|
|
if( tab8[i] < tabbase32_len )
|
|
s += tabbase32[tab8[i]];
|
|
else
|
|
s += padding;
|
|
}
|
|
}
|
|
|
|
|
|
|
|
void Base32::Save5PiecesToString(std::string & s, const unsigned int * tab5)
|
|
{
|
|
for(int i=0 ; i<5 ; ++i)
|
|
{
|
|
if( tab5[i] != not_existing )
|
|
s += tab5[i];
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
*/
|
|
void Base32::Encode(const char * in, size_t len, std::string & out)
|
|
{
|
|
unsigned int tab8[8];
|
|
|
|
out.clear();
|
|
size_t new_size = len + (size_t)((double)(len) * (5.0/8.0)) + 8;
|
|
out.reserve(new_size);
|
|
|
|
for(size_t i=0 ; i < len ; i+=5)
|
|
{
|
|
Convert5to8Pieces(in+i, len-i, tab8);
|
|
Save8PiecesToString(out, tab8);
|
|
}
|
|
}
|
|
|
|
|
|
void Base32::Encode(const char * in, std::string & out)
|
|
{
|
|
size_t len = strlen(in);
|
|
Encode(in, len, out);
|
|
}
|
|
|
|
|
|
void Base32::Encode(const std::string & in, std::string & out)
|
|
{
|
|
Encode(in.c_str(), in.size(), out);
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool Base32::Decode(const char * in, size_t len, std::string & out)
|
|
{
|
|
unsigned int tab5[5];
|
|
unsigned int tab8[8];
|
|
|
|
out.clear();
|
|
|
|
if( len % 8 != 0 )
|
|
return false;
|
|
|
|
size_t new_size = len - (size_t)((double)(len) * (5.0/8.0)) + 5;
|
|
|
|
if( new_size > 0 )
|
|
out.reserve(new_size);
|
|
|
|
for(size_t i=0 ; i<len ; i+=8)
|
|
{
|
|
if( !Make8pieces(in+i, tab8) )
|
|
return false;
|
|
|
|
ConvertFrom8to5Pieces(tab8, tab5);
|
|
Save5PiecesToString(out, tab5);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool Base32::Decode(const char * in, std::string & out)
|
|
{
|
|
size_t len = strlen(in);
|
|
return Decode(in, len, out);
|
|
}
|
|
|
|
|
|
bool Base32::Decode(const std::string & in, std::string & out)
|
|
{
|
|
return Decode(in.c_str(), in.size(), out);
|
|
}
|
|
|
|
|
|
|
|
|
|
} // namespace Tito
|
|
|
|
|
|
|