polserver/pol-core/pol/crypt/md5.cpp
turleypol dbb25bdb62
Include and buildsystem cleanup (#45)
Include cleanup
Reworked buildsystem (Linux only)
Removed dynamic libs, Linux now again uses static linking (like windows)
2018-01-29 21:55:48 +01:00

303 lines
8.5 KiB
C++

#include <string.h>
#include "md5.h"
namespace Pol
{
namespace Crypt
{
// MD5 Definitions
#define T_MASK ( (unsigned int)~0 )
#define T1 ( T_MASK ^ 0x28955b87 )
#define T2 ( T_MASK ^ 0x173848a9 )
#define T3 0x242070db
#define T4 ( T_MASK ^ 0x3e423111 )
#define T5 ( T_MASK ^ 0x0a83f050 )
#define T6 0x4787c62a
#define T7 ( T_MASK ^ 0x57cfb9ec )
#define T8 ( T_MASK ^ 0x02b96afe )
#define T9 0x698098d8
#define T10 ( T_MASK ^ 0x74bb0850 )
#define T11 ( T_MASK ^ 0x0000a44e )
#define T12 ( T_MASK ^ 0x76a32841 )
#define T13 0x6b901122
#define T14 ( T_MASK ^ 0x02678e6c )
#define T15 ( T_MASK ^ 0x5986bc71 )
#define T16 0x49b40821
#define T17 ( T_MASK ^ 0x09e1da9d )
#define T18 ( T_MASK ^ 0x3fbf4cbf )
#define T19 0x265e5a51
#define T20 ( T_MASK ^ 0x16493855 )
#define T21 ( T_MASK ^ 0x29d0efa2 )
#define T22 0x02441453
#define T23 ( T_MASK ^ 0x275e197e )
#define T24 ( T_MASK ^ 0x182c0437 )
#define T25 0x21e1cde6
#define T26 ( T_MASK ^ 0x3cc8f829 )
#define T27 ( T_MASK ^ 0x0b2af278 )
#define T28 0x455a14ed
#define T29 ( T_MASK ^ 0x561c16fa )
#define T30 ( T_MASK ^ 0x03105c07 )
#define T31 0x676f02d9
#define T32 ( T_MASK ^ 0x72d5b375 )
#define T33 ( T_MASK ^ 0x0005c6bd )
#define T34 ( T_MASK ^ 0x788e097e )
#define T35 0x6d9d6122
#define T36 ( T_MASK ^ 0x021ac7f3 )
#define T37 ( T_MASK ^ 0x5b4115bb )
#define T38 0x4bdecfa9
#define T39 ( T_MASK ^ 0x0944b49f )
#define T40 ( T_MASK ^ 0x4140438f )
#define T41 0x289b7ec6
#define T42 ( T_MASK ^ 0x155ed805 )
#define T43 ( T_MASK ^ 0x2b10cf7a )
#define T44 0x04881d05
#define T45 ( T_MASK ^ 0x262b2fc6 )
#define T46 ( T_MASK ^ 0x1924661a )
#define T47 0x1fa27cf8
#define T48 ( T_MASK ^ 0x3b53a99a )
#define T49 ( T_MASK ^ 0x0bd6ddbb )
#define T50 0x432aff97
#define T51 ( T_MASK ^ 0x546bdc58 )
#define T52 ( T_MASK ^ 0x036c5fc6 )
#define T53 0x655b59c3
#define T54 ( T_MASK ^ 0x70f3336d )
#define T55 ( T_MASK ^ 0x00100b82 )
#define T56 ( T_MASK ^ 0x7a7ba22e )
#define T57 0x6fa87e4f
#define T58 ( T_MASK ^ 0x01d3191f )
#define T59 ( T_MASK ^ 0x5cfebceb )
#define T60 0x4e0811a1
#define T61 ( T_MASK ^ 0x08ac817d )
#define T62 ( T_MASK ^ 0x42c50dca )
#define T63 0x2ad7d2bb
#define T64 ( T_MASK ^ 0x14792c6e )
// Constructor / Destructor
MD5Crypt::MD5Crypt() : TableIdx( 0 )
{
memset( &Digest, 0, sizeof( Digest ) );
}
MD5Crypt::~MD5Crypt() {}
// Public Member Functions
void MD5Crypt::Init( unsigned char* Data, unsigned int Size )
{
md5_state tmpMd5;
TableIdx = 0;
start( &tmpMd5 );
append( &tmpMd5, (const unsigned char*)Data, Size );
finish( &tmpMd5, Digest );
}
void MD5Crypt::Encrypt( unsigned char* in, unsigned char* out, int len )
{
for ( int i = 0; i < len; i++ )
out[i] = in[i] ^ Digest[TableIdx++ % 16];
}
// Protected Member Functions
void MD5Crypt::process( md5_state* pms, const unsigned char* data )
{
unsigned int a = pms->abcd[0], b = pms->abcd[1], c = pms->abcd[2], d = pms->abcd[3];
unsigned int t = 0;
unsigned int X[16];
const unsigned char* xp = data;
for ( int i = 0; i < 16; ++i, xp += 4 )
X[i] = xp[0] + ( xp[1] << 8 ) + ( xp[2] << 16 ) + ( xp[3] << 24 );
#define ROTATE_LEFT( x, n ) ( ( ( x ) << ( n ) ) | ( ( x ) >> ( 32 - ( n ) ) ) )
// Round 1
// Let [abcd k s i] denote the operation
// a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s)
#define F( x, y, z ) ( ( ( x ) & ( y ) ) | ( ~( x ) & ( z ) ) )
#define SET( a, b, c, d, k, s, Ti ) \
t = a + F( b, c, d ) + X[k] + Ti; \
a = ROTATE_LEFT( t, s ) + b
// Do the following 16 operations
SET( a, b, c, d, 0, 7, T1 );
SET( d, a, b, c, 1, 12, T2 );
SET( c, d, a, b, 2, 17, T3 );
SET( b, c, d, a, 3, 22, T4 );
SET( a, b, c, d, 4, 7, T5 );
SET( d, a, b, c, 5, 12, T6 );
SET( c, d, a, b, 6, 17, T7 );
SET( b, c, d, a, 7, 22, T8 );
SET( a, b, c, d, 8, 7, T9 );
SET( d, a, b, c, 9, 12, T10 );
SET( c, d, a, b, 10, 17, T11 );
SET( b, c, d, a, 11, 22, T12 );
SET( a, b, c, d, 12, 7, T13 );
SET( d, a, b, c, 13, 12, T14 );
SET( c, d, a, b, 14, 17, T15 );
SET( b, c, d, a, 15, 22, T16 );
#undef SET
// Round 2
// Let [abcd k s i] denote the operation
// a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s)
#define G( x, y, z ) ( ( ( x ) & ( z ) ) | ( ( y ) & ~( z ) ) )
#define SET( a, b, c, d, k, s, Ti ) \
t = a + G( b, c, d ) + X[k] + Ti; \
a = ROTATE_LEFT( t, s ) + b
// Do the following 16 operations
SET( a, b, c, d, 1, 5, T17 );
SET( d, a, b, c, 6, 9, T18 );
SET( c, d, a, b, 11, 14, T19 );
SET( b, c, d, a, 0, 20, T20 );
SET( a, b, c, d, 5, 5, T21 );
SET( d, a, b, c, 10, 9, T22 );
SET( c, d, a, b, 15, 14, T23 );
SET( b, c, d, a, 4, 20, T24 );
SET( a, b, c, d, 9, 5, T25 );
SET( d, a, b, c, 14, 9, T26 );
SET( c, d, a, b, 3, 14, T27 );
SET( b, c, d, a, 8, 20, T28 );
SET( a, b, c, d, 13, 5, T29 );
SET( d, a, b, c, 2, 9, T30 );
SET( c, d, a, b, 7, 14, T31 );
SET( b, c, d, a, 12, 20, T32 );
#undef SET
// Round 3
// Let [abcd k s t] denote the operation
// a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s)
#define H( x, y, z ) ( ( x ) ^ ( y ) ^ ( z ) )
#define SET( a, b, c, d, k, s, Ti ) \
t = a + H( b, c, d ) + X[k] + Ti; \
a = ROTATE_LEFT( t, s ) + b
// Do the following 16 operations
SET( a, b, c, d, 5, 4, T33 );
SET( d, a, b, c, 8, 11, T34 );
SET( c, d, a, b, 11, 16, T35 );
SET( b, c, d, a, 14, 23, T36 );
SET( a, b, c, d, 1, 4, T37 );
SET( d, a, b, c, 4, 11, T38 );
SET( c, d, a, b, 7, 16, T39 );
SET( b, c, d, a, 10, 23, T40 );
SET( a, b, c, d, 13, 4, T41 );
SET( d, a, b, c, 0, 11, T42 );
SET( c, d, a, b, 3, 16, T43 );
SET( b, c, d, a, 6, 23, T44 );
SET( a, b, c, d, 9, 4, T45 );
SET( d, a, b, c, 12, 11, T46 );
SET( c, d, a, b, 15, 16, T47 );
SET( b, c, d, a, 2, 23, T48 );
#undef SET
// Round 4
// Let [abcd k s t] denote the operation
// a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s)
#define I( x, y, z ) ( ( y ) ^ ( ( x ) | ~( z ) ) )
#define SET( a, b, c, d, k, s, Ti ) \
t = a + I( b, c, d ) + X[k] + Ti; \
a = ROTATE_LEFT( t, s ) + b
// Do the following 16 operations
SET( a, b, c, d, 0, 6, T49 );
SET( d, a, b, c, 7, 10, T50 );
SET( c, d, a, b, 14, 15, T51 );
SET( b, c, d, a, 5, 21, T52 );
SET( a, b, c, d, 12, 6, T53 );
SET( d, a, b, c, 3, 10, T54 );
SET( c, d, a, b, 10, 15, T55 );
SET( b, c, d, a, 1, 21, T56 );
SET( a, b, c, d, 8, 6, T57 );
SET( d, a, b, c, 15, 10, T58 );
SET( c, d, a, b, 6, 15, T59 );
SET( b, c, d, a, 13, 21, T60 );
SET( a, b, c, d, 4, 6, T61 );
SET( d, a, b, c, 11, 10, T62 );
SET( c, d, a, b, 2, 15, T63 );
SET( b, c, d, a, 9, 21, T64 );
#undef SET
// Then perform the following additions (That is increment each
// of the four registers by the value it had before this block
// was started)
pms->abcd[0] += a;
pms->abcd[1] += b;
pms->abcd[2] += c;
pms->abcd[3] += d;
}
void MD5Crypt::start( md5_state* pms )
{
pms->count[0] = pms->count[1] = 0;
pms->abcd[0] = 0x67452301;
pms->abcd[1] = T_MASK ^ 0x10325476;
pms->abcd[2] = T_MASK ^ 0x67452301;
pms->abcd[3] = 0x10325476;
}
void MD5Crypt::append( md5_state* pms, const unsigned char* data, int nbytes )
{
const unsigned char* p = data;
unsigned int nbits = (unsigned int)( nbytes << 3 );
int left = nbytes, offset = ( pms->count[0] >> 3 ) & 63;
if ( nbytes <= 0 )
return;
// Update the message length
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if ( pms->count[0] < nbits )
pms->count[1]++;
// Process an initial partial block
if ( offset )
{
int copy = ( offset + nbytes > 64 ? 64 - offset : nbytes );
memcpy( pms->buf + offset, p, copy );
if ( offset + copy < 64 )
return;
p += copy;
left -= copy;
process( pms, pms->buf );
}
// Process full blocks
for ( ; left >= 64; p += 64, left -= 64 )
process( pms, p );
// Process a final partial block
if ( left )
{
if ( left > 63 )
left = 63;
memcpy( pms->buf, p, left );
}
}
void MD5Crypt::finish( md5_state* pms, unsigned char digest[16] )
{
static const unsigned char pad[64] = {0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
unsigned char data[8];
// Save the length before padding
for ( int i = 0; i < 8; ++i )
data[i] = (unsigned char)( pms->count[i >> 2] >> ( ( i & 3 ) << 3 ) );
// Pad to 56 bytes mod 64
append( pms, pad, ( ( 55 - ( pms->count[0] >> 3 ) ) & 63 ) + 1 );
// Append the length
append( pms, data, 8 );
for ( int i = 0; i < 16; ++i )
digest[i] = (unsigned char)( pms->abcd[i >> 2] >> ( ( i & 3 ) << 3 ) );
}
}
}