Files
2026-06-01 12:46:52 +02:00

354 lines
10 KiB
C++

#include <map>
#include "../../include/cipher/XEncrypt.h"
#include "../../include/cipher/XZlibEncoder.h"
#include "../../include/cipher/SimpleCipher.h"
#include "../../include/toolkit/safe_function.h"
XEncrypt::XEncryptImpl * XEncrypt::getImpl( _ENCRYPT_TYPE eType )
{
static std::map< _ENCRYPT_TYPE, XEncryptImpl * > s_mapImpl;
static bool bInit = false;
if( !bInit )
{
bInit = true;
static XEncryptNone instXEncryptNone;
static XEncryptZlib instXEncryptZlib;
static XEncryptZlib64 instXEncryptZlib64;
static XEncryptZlibWithSimpleCipher instXEncryptZlibWithSimpleCipher2;
s_mapImpl[ ET_NONE ] = &instXEncryptNone;
s_mapImpl[ ET_ZLIB ] = &instXEncryptZlib;
s_mapImpl[ ET_ZLIB64 ] = &instXEncryptZlib64;
s_mapImpl[ ET_ZLIB_WITH_SIMPLE_CIPHER ] = &instXEncryptZlibWithSimpleCipher2;
}
if( s_mapImpl.find( eType ) == s_mapImpl.end() )
{
assert( 0 );
return s_mapImpl[ ET_NONE ];
}
return s_mapImpl[ eType ];
}
bool XEncrypt::Encrypt( _ENCRYPT_TYPE eType, const char * pszFmtTag, const unsigned int nVersion, const void * pSource, size_t nSourceLength, std::vector< BYTE > & vResult )
{
return getImpl( eType )->Encrypt( pszFmtTag, nVersion, static_cast< const BYTE * >( pSource ), nSourceLength, vResult );
}
bool XEncrypt::Decrypt( _ENCRYPT_TYPE eType, const char * pszFmtTag, const unsigned int nVersion, const void * pSource, size_t nSourceLength, std::vector< BYTE > & vResult )
{
return getImpl( eType )->Decrypt( pszFmtTag, nVersion, static_cast< const BYTE * >( pSource ), nSourceLength, vResult );
}
// XEncryptNone
bool XEncrypt::XEncryptNone::Encrypt( const char * pszFmtTag, const unsigned int nVersion, const BYTE * pSource, size_t nSourceLength, std::vector< BYTE > & vResult )
{
vResult.clear();
vResult.insert( vResult.end(), pSource, pSource + nSourceLength );
return true;
}
bool XEncrypt::XEncryptNone::Decrypt( const char * pszFmtTag, const unsigned int nVersion, const BYTE * pSource, size_t nSourceLength, std::vector< BYTE > & vResult )
{
vResult.clear();
vResult.insert( vResult.end(), pSource, pSource + nSourceLength );
return true;
}
// XEncryptZlib
bool XEncrypt::XEncryptZlib::Encrypt( const char * pszFmtTag, const unsigned int nVersion, const BYTE * pSource, size_t nSourceLength, std::vector< BYTE > & vResult )
{
size_t nFmtTagLength = strlen( pszFmtTag );
if( nFmtTagLength > 8 )
{
assert( 0 );
return false;
}
Header header;
header.nVersion = nVersion;
header.nOriginalLength = static_cast< unsigned int >( nSourceLength );
// The required buffer for compression size is calculated as described on http://www.zlib.net/manual.html#compress.
header.nCompressedLength = ( nSourceLength ) ? static_cast< unsigned int >( 1.001 * ( nSourceLength + 12 ) + 1 ) : 0;
size_t nEncodedLength = nFmtTagLength + sizeof( Header ) + header.nCompressedLength;
std::vector< BYTE > vBuffer( nEncodedLength );
BYTE * pBuffer = &vBuffer.front();
if( nSourceLength )
{
size_t nWrittenLength = 0;
if( XZlibEncoder::Encode( pSource, nSourceLength, pBuffer + nFmtTagLength + sizeof( Header ), nEncodedLength - nFmtTagLength - sizeof( Header ), &nWrittenLength ) )
{
assert( 0 );
return false;
}
if( nWrittenLength > header.nCompressedLength )
{
assert( 0 );
return false;
}
header.nCompressedLength = unsigned int( nWrittenLength );
nEncodedLength = nFmtTagLength + sizeof( Header ) + nWrittenLength;
vBuffer.resize( nEncodedLength );
// Preventing pBuffer to be invalid by reallocation by resize()
pBuffer = &vBuffer.front();
}
assert( nEncodedLength == header.nCompressedLength + sizeof( Header ) + nFmtTagLength && nEncodedLength == vBuffer.size() );
// Writing header
s_memcpy( pBuffer, vBuffer.size(), pszFmtTag, nFmtTagLength );
s_memcpy( pBuffer + nFmtTagLength, vBuffer.size() - nFmtTagLength, &header, sizeof( Header ) );
vResult.swap( vBuffer );
return true;
}
bool XEncrypt::XEncryptZlib::Decrypt( const char * pszFmtTag, const unsigned int nVersion, const BYTE * pSource, size_t nSourceLength, std::vector< BYTE > & vResult )
{
if( !IsValidFormat( pszFmtTag, nVersion, pSource, nSourceLength ) )
return false;
size_t nFmtTagLength = strlen( pszFmtTag );
if( nSourceLength < nFmtTagLength + sizeof( Header ) )
{
assert( 0 );
return false;
}
const Header * pHeader = reinterpret_cast< const Header * >( pSource + nFmtTagLength );
if( pHeader->nCompressedLength > nSourceLength - nFmtTagLength - sizeof( Header ) )
{
assert( 0 );
return false;
}
// An empty valid file
if( nSourceLength == nFmtTagLength + sizeof( Header ) )
{
vResult.clear();
return true;
}
// Invalid nOriginalLength information
if( !pHeader->nOriginalLength )
{
assert( 0 );
return false;
}
std::vector< BYTE > vBuffer( pHeader->nOriginalLength );
size_t nDecodedLength = 0;
if( XZlibEncoder::Decode( pSource + nFmtTagLength + sizeof( Header ), pHeader->nCompressedLength, &vBuffer.front(), vBuffer.size(), &nDecodedLength ) )
{
assert( 0 );
return false;
}
if( nDecodedLength != pHeader->nOriginalLength )
{
assert( 0 );
return false;
}
vResult.swap( vBuffer );
return true;
}
// XEncryptZlib64
bool XEncrypt::XEncryptZlib64::Encrypt( const char * pszFmtTag, const unsigned int nVersion, const BYTE * pSource, size_t nSourceLength, std::vector< BYTE > & vResult )
{
size_t nFmtTagLength = strlen( pszFmtTag );
if( nFmtTagLength > 8 )
{
assert( 0 );
return false;
}
Header header;
header.nVersion = nVersion;
header.nOriginalLength = static_cast< unsigned int >( nSourceLength );
// The required buffer for compression size is calculated as described on http://www.zlib.net/manual.html#compress.
header.nCompressedLength = ( nSourceLength ) ? static_cast< unsigned int >( 1.001 * ( nSourceLength + 12 ) + 1 ) : 0;
size_t nEncodedLength = nFmtTagLength + sizeof( Header ) + static_cast< size_t >( header.nCompressedLength );
std::vector< BYTE > vBuffer( nEncodedLength );
BYTE * pBuffer = &vBuffer.front();
if( nSourceLength )
{
size_t nWrittenLength = 0;
if( XZlibEncoder::Encode( pSource, nSourceLength, pBuffer + nFmtTagLength + sizeof( Header ), nEncodedLength - nFmtTagLength - sizeof( Header ), &nWrittenLength ) )
{
assert( 0 );
return false;
}
if( nWrittenLength > header.nCompressedLength )
{
assert( 0 );
return false;
}
header.nCompressedLength = nWrittenLength;
nEncodedLength = nFmtTagLength + sizeof( Header ) + nWrittenLength;
vBuffer.resize( nEncodedLength );
// Preventing pBuffer to be invalid by reallocation by resize()
pBuffer = &vBuffer.front();
}
assert( nEncodedLength == header.nCompressedLength + sizeof( Header ) + nFmtTagLength && nEncodedLength == vBuffer.size() );
// Writing header
s_memcpy( pBuffer, vBuffer.size(), pszFmtTag, nFmtTagLength );
s_memcpy( pBuffer + nFmtTagLength, vBuffer.size() - nFmtTagLength, &header, sizeof( Header ) );
vResult.swap( vBuffer );
return true;
}
bool XEncrypt::XEncryptZlib64::Decrypt( const char * pszFmtTag, const unsigned int nVersion, const BYTE * pSource, size_t nSourceLength, std::vector< BYTE > & vResult )
{
if( !IsValidFormat( pszFmtTag, nVersion, pSource, nSourceLength ) )
return false;
size_t nFmtTagLength = strlen( pszFmtTag );
if( nSourceLength < nFmtTagLength + sizeof( Header ) )
{
assert( 0 );
return false;
}
const Header * pHeader = reinterpret_cast< const Header * >( pSource + nFmtTagLength );
if( pHeader->nCompressedLength > nSourceLength - nFmtTagLength - sizeof( Header ) )
{
assert( 0 );
return false;
}
// An empty valid file
if( nSourceLength == nFmtTagLength + sizeof( Header ) )
{
vResult.clear();
return true;
}
std::vector< BYTE > vBuffer( static_cast< size_t >( pHeader->nOriginalLength ) );
size_t nDecodedLength = 0;
if( XZlibEncoder::Decode( pSource + nFmtTagLength + sizeof( Header ), static_cast< size_t >( pHeader->nCompressedLength ), &vBuffer.front(), vBuffer.size(), &nDecodedLength ) )
{
assert( 0 );
return false;
}
if( nDecodedLength != pHeader->nOriginalLength )
{
assert( 0 );
return false;
}
vResult.swap( vBuffer );
return true;
}
// XEncryptZlibWithSimpleCipher
bool XEncrypt::XEncryptZlibWithSimpleCipher::Encrypt( const char * pszFmtTag, const unsigned int nVersion, const BYTE * pSource, size_t nSourceLength, std::vector< BYTE > & vResult )
{
size_t nFmtTagLength = strlen( pszFmtTag );
if( nFmtTagLength > 8 )
{
assert( 0 );
return false;
}
// The required buffer for compression size is calculated as described on http://www.zlib.net/manual.html#compress.
std::vector< BYTE > vBuffer( ( nSourceLength ) ? static_cast< size_t >( 1.001 * ( nSourceLength + 12 ) + 1 ) : 0 );
BYTE * pBuffer = &vBuffer.front();
if( nSourceLength )
{
size_t nWrittenLength = 0;
if( XZlibEncoder::Encode( pSource, nSourceLength, pBuffer, vBuffer.size(), &nWrittenLength ) )
{
assert( 0 );
return false;
}
if( nWrittenLength > vBuffer.size() )
{
assert( 0 );
return false;
}
vBuffer.resize( nWrittenLength );
// Preventing pBuffer to be invalid by reallocation by resize()
pBuffer = &vBuffer.front();
}
std::vector< BYTE > vOutput;
SimpleCipher::Encrypt( nSourceLength, vBuffer, vOutput );
vResult.clear();
vResult.resize( nFmtTagLength + sizeof( unsigned int ) );
s_memcpy( &vResult.front(), vResult.size(), pszFmtTag, nFmtTagLength );
s_memcpy( &vResult.front() + nFmtTagLength, vResult.size() - nFmtTagLength, &nVersion, sizeof( unsigned int ) );
vResult.insert( vResult.end(), vOutput.begin(), vOutput.end() );
return true;
}
bool XEncrypt::XEncryptZlibWithSimpleCipher::Decrypt( const char * pszFmtTag, const unsigned int nVersion, const BYTE * pSource, size_t nSourceLength, std::vector< BYTE > & vResult )
{
if( !IsValidFormat( pszFmtTag, nVersion, pSource, nSourceLength ) )
return false;
size_t nFmtTagLength = strlen( pszFmtTag );
size_t nEncryptedLength = nSourceLength - nFmtTagLength - sizeof( unsigned int );
// An empty valid file
if( !nEncryptedLength )
{
vResult.clear();
return true;
}
std::vector< BYTE > vBuffer( nEncryptedLength - sizeof( unsigned int ) * 2 );
size_t nOriginalSize = 0;
// Fucking SimpleCipher -_ - Input and Ouput should be a container.
const std::vector< BYTE > vSource( pSource + nFmtTagLength + sizeof( unsigned int ), pSource + nSourceLength );
SimpleCipher::Decrypt( vSource, vBuffer, &nOriginalSize );
vResult.clear();
vResult.resize( nOriginalSize );
if( XZlibEncoder::Decode( &vBuffer.front(), vBuffer.size(), &vResult.front(), vResult.size(), &nOriginalSize ) )
{
assert( 0 );
vResult.clear();
return false;
}
if( nOriginalSize != vResult.size() )
{
assert( 0 );
vResult.clear();
return false;
}
return true;
}