From 4ceb300a75844e41884fc924955ba4cdf81b6895 Mon Sep 17 00:00:00 2001 From: RD42 <42702181+dashr9230@users.noreply.github.com> Date: Sun, 4 Feb 2024 19:23:08 +0800 Subject: [PATCH] [saco/server/bot] Add and match RakNet SHA1 --- bot/bot.vcproj | 6 + raknet/SHA1.cpp | 326 +++++++++++++++++++++++++++++++++++++++++++ raknet/SHA1.h | 85 +++++++++++ saco/saco.vcproj | 6 + server/server.vcproj | 6 + 5 files changed, 429 insertions(+) create mode 100644 raknet/SHA1.cpp create mode 100644 raknet/SHA1.h diff --git a/bot/bot.vcproj b/bot/bot.vcproj index d3034cd..28a6d62 100644 --- a/bot/bot.vcproj +++ b/bot/bot.vcproj @@ -237,6 +237,12 @@ + + + + diff --git a/raknet/SHA1.cpp b/raknet/SHA1.cpp new file mode 100644 index 0000000..2cc9228 --- /dev/null +++ b/raknet/SHA1.cpp @@ -0,0 +1,326 @@ +/** +* @brief SHA-1 Hash key computation +* +* 100% free public domain implementation of the SHA-1 +* algorithm by Dominik Reichl +* +* +* === Test Vectors (from FIPS PUB 180-1) === +* +* "abc" +* A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +* +* "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +* 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +* +* A million repetitions of "a" +* 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F +*/ + + +#include "SHA1.h" +#include + + +CSHA1::CSHA1() +{ + Reset(); +} + +CSHA1::~CSHA1() +{ + Reset(); +} + + +void CSHA1::Reset() +{ + // SHA1 initialization constants + m_state[ 0 ] = 0x67452301; + m_state[ 1 ] = 0xEFCDAB89; + m_state[ 2 ] = 0x98BADCFE; + m_state[ 3 ] = 0x10325476; + m_state[ 4 ] = 0xC3D2E1F0; + + m_count[ 0 ] = 0; + m_count[ 1 ] = 0; +} + +void CSHA1::Transform( unsigned int state[ 5 ], unsigned char buffer[ 64 ] ) +{ + unsigned int a = 0, b = 0, c = 0, d = 0, e = 0; + + SHA1_WORKSPACE_BLOCK* block; + // static unsigned char workspace[64]; + block = ( SHA1_WORKSPACE_BLOCK * ) workspace; + memcpy( block, buffer, 64 ); + + // Copy state[] to working vars + a = state[ 0 ]; + b = state[ 1 ]; + c = state[ 2 ]; + d = state[ 3 ]; + e = state[ 4 ]; + + // 4 rounds of 20 operations each. Loop unrolled. + R0( a, b, c, d, e, 0 ); + R0( e, a, b, c, d, 1 ); + R0( d, e, a, b, c, 2 ); + R0( c, d, e, a, b, 3 ); + R0( b, c, d, e, a, 4 ); + R0( a, b, c, d, e, 5 ); + R0( e, a, b, c, d, 6 ); + R0( d, e, a, b, c, 7 ); + R0( c, d, e, a, b, 8 ); + R0( b, c, d, e, a, 9 ); + R0( a, b, c, d, e, 10 ); + R0( e, a, b, c, d, 11 ); + R0( d, e, a, b, c, 12 ); + R0( c, d, e, a, b, 13 ); + R0( b, c, d, e, a, 14 ); + R0( a, b, c, d, e, 15 ); + R1( e, a, b, c, d, 16 ); + R1( d, e, a, b, c, 17 ); + R1( c, d, e, a, b, 18 ); + R1( b, c, d, e, a, 19 ); + R2( a, b, c, d, e, 20 ); + R2( e, a, b, c, d, 21 ); + R2( d, e, a, b, c, 22 ); + R2( c, d, e, a, b, 23 ); + R2( b, c, d, e, a, 24 ); + R2( a, b, c, d, e, 25 ); + R2( e, a, b, c, d, 26 ); + R2( d, e, a, b, c, 27 ); + R2( c, d, e, a, b, 28 ); + R2( b, c, d, e, a, 29 ); + R2( a, b, c, d, e, 30 ); + R2( e, a, b, c, d, 31 ); + R2( d, e, a, b, c, 32 ); + R2( c, d, e, a, b, 33 ); + R2( b, c, d, e, a, 34 ); + R2( a, b, c, d, e, 35 ); + R2( e, a, b, c, d, 36 ); + R2( d, e, a, b, c, 37 ); + R2( c, d, e, a, b, 38 ); + R2( b, c, d, e, a, 39 ); + R3( a, b, c, d, e, 40 ); + R3( e, a, b, c, d, 41 ); + R3( d, e, a, b, c, 42 ); + R3( c, d, e, a, b, 43 ); + R3( b, c, d, e, a, 44 ); + R3( a, b, c, d, e, 45 ); + R3( e, a, b, c, d, 46 ); + R3( d, e, a, b, c, 47 ); + R3( c, d, e, a, b, 48 ); + R3( b, c, d, e, a, 49 ); + R3( a, b, c, d, e, 50 ); + R3( e, a, b, c, d, 51 ); + R3( d, e, a, b, c, 52 ); + R3( c, d, e, a, b, 53 ); + R3( b, c, d, e, a, 54 ); + R3( a, b, c, d, e, 55 ); + R3( e, a, b, c, d, 56 ); + R3( d, e, a, b, c, 57 ); + R3( c, d, e, a, b, 58 ); + R3( b, c, d, e, a, 59 ); + R4( a, b, c, d, e, 60 ); + R4( e, a, b, c, d, 61 ); + R4( d, e, a, b, c, 62 ); + R4( c, d, e, a, b, 63 ); + R4( b, c, d, e, a, 64 ); + R4( a, b, c, d, e, 65 ); + R4( e, a, b, c, d, 66 ); + R4( d, e, a, b, c, 67 ); + R4( c, d, e, a, b, 68 ); + R4( b, c, d, e, a, 69 ); + R4( a, b, c, d, e, 70 ); + R4( e, a, b, c, d, 71 ); + R4( d, e, a, b, c, 72 ); + R4( c, d, e, a, b, 73 ); + R4( b, c, d, e, a, 74 ); + R4( a, b, c, d, e, 75 ); + R4( e, a, b, c, d, 76 ); + R4( d, e, a, b, c, 77 ); + R4( c, d, e, a, b, 78 ); + R4( b, c, d, e, a, 79 ); + + // Add the working vars back into state[] + state[ 0 ] += a; + state[ 1 ] += b; + state[ 2 ] += c; + state[ 3 ] += d; + state[ 4 ] += e; + + // Wipe variables + a = 0; + b = 0; + c = 0; + d = 0; + e = 0; +} + +// Use this function to hash in binary data and strings +void CSHA1::Update( unsigned char* data, unsigned int len ) +{ + unsigned int i = 0, j = 0; + + j = ( m_count[ 0 ] >> 3 ) & 63; + + if ( ( m_count[ 0 ] += len << 3 ) < ( len << 3 ) ) + m_count[ 1 ] ++; + + m_count[ 1 ] += ( len >> 29 ); + + if ( ( j + len ) > 63 ) + { + memcpy( &m_buffer[ j ], data, ( i = 64 - j ) ); + Transform( m_state, m_buffer ); + + for ( ; i + 63 < len; i += 64 ) + { + Transform( m_state, &data[ i ] ); + } + + j = 0; + } + + else + i = 0; + + memcpy( &m_buffer[ j ], &data[ i ], len - i ); +} + +// Hash in file contents +bool CSHA1::HashFile( char *szFileName ) +{ + unsigned long ulFileSize = 0, ulRest = 0, ulBlocks = 0; + unsigned long i = 0; + unsigned char uData[ MAX_FILE_READ_BUFFER ]; + FILE *fIn = NULL; + + if ( ( fIn = fopen( szFileName, "rb" ) ) == NULL ) + return ( false ); + + fseek( fIn, 0, SEEK_END ); + + ulFileSize = ftell( fIn ); + + fseek( fIn, 0, SEEK_SET ); + + // This is faster + div_t temp; + + temp = div( ulFileSize, MAX_FILE_READ_BUFFER ); + + ulRest = temp.rem; + + ulBlocks = temp.quot; + + // ulRest = ulFileSize % MAX_FILE_READ_BUFFER; + // ulBlocks = ulFileSize / MAX_FILE_READ_BUFFER; + + for ( i = 0; i < ulBlocks; i++ ) + { + fread( uData, 1, MAX_FILE_READ_BUFFER, fIn ); + Update( uData, MAX_FILE_READ_BUFFER ); + } + + if ( ulRest != 0 ) + { + fread( uData, 1, ulRest, fIn ); + Update( uData, ulRest ); + } + + fclose( fIn ); + fIn = NULL; + + return ( true ); +} + +void CSHA1::Final() +{ + unsigned int i = 0, j = 0; + unsigned char finalcount[ 8 ] = + { + 0, 0, 0, 0, 0, 0, 0, 0 + }; + + for ( i = 0; i < 8; i++ ) + finalcount[ i ] = (unsigned char) ( ( m_count[ ( i >= 4 ? 0 : 1 ) ] + >> ( ( 3 - ( i & 3 ) ) * 8 ) ) & 255 ); // Endian independent + + Update( ( unsigned char * ) "\200", 1 ); + + while ( ( m_count[ 0 ] & 504 ) != 448 ) + Update( ( unsigned char * ) "\0", 1 ); + + Update( finalcount, 8 ); // Cause a SHA1Transform() + + for ( i = 0; i < 20; i++ ) + { + m_digest[ i ] = (unsigned char) ( ( m_state[ i >> 2 ] >> ( ( 3 - ( i & 3 ) ) * 8 ) ) & 255 ); + } + + // Wipe variables for security reasons + i = 0; + + j = 0; + + memset( m_buffer, 0, 64 ); + + memset( m_state, 0, 20 ); + + memset( m_count, 0, 8 ); + + memset( finalcount, 0, 8 ); + + Transform( m_state, m_buffer ); +} + +// Get the final hash as a pre-formatted string +void CSHA1::ReportHash( char *szReport, unsigned char uReportType ) +{ + unsigned char i = 0; + char szTemp[ 4 ]; + + if ( uReportType == REPORT_HEX ) + { + sprintf( szTemp, "%02X", m_digest[ 0 ] ); + strcat( szReport, szTemp ); + + for ( i = 1; i < 20; i++ ) + { + sprintf( szTemp, " %02X", m_digest[ i ] ); + strcat( szReport, szTemp ); + } + } + + else + if ( uReportType == REPORT_DIGIT ) + { + sprintf( szTemp, "%u", m_digest[ 0 ] ); + strcat( szReport, szTemp ); + + for ( i = 1; i < 20; i++ ) + { + sprintf( szTemp, " %u", m_digest[ i ] ); + strcat( szReport, szTemp ); + } + } + + else + strcpy( szReport, "Error: Unknown report type!" ); +} + +// Get the raw message digest +void CSHA1::GetHash( unsigned char *uDest ) +{ + memcpy( uDest, m_digest, 20 ); +} + +// Get the raw message digest +// Added by Kevin to be quicker +unsigned char * CSHA1::GetHash( void ) const +{ + return ( unsigned char * ) m_digest; +} diff --git a/raknet/SHA1.h b/raknet/SHA1.h new file mode 100644 index 0000000..907a7b5 --- /dev/null +++ b/raknet/SHA1.h @@ -0,0 +1,85 @@ +/// \brief \b [Internal] SHA-1 computation class +/// +/// 100% free public domain implementation of the SHA-1 +/// algorithm by Dominik Reichl +/// +/// +/// === Test Vectors (from FIPS PUB 180-1) === +/// +/// "abc" +/// A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D +/// +/// "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq" +/// 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1 +/// +/// A million repetitions of "a" +/// 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F + +#ifndef ___SHA1_H___ +#define ___SHA1_H___ + +#include // Needed for file access +#include // Needed for memset and memcpy +#include // Needed for strcat and strcpy +#include "Types.h" +#include "Export.h" + +#define MAX_FILE_READ_BUFFER 8000 + +#define SHA1_LENGTH 20 + +class RAK_DLL_EXPORT CSHA1 +{ + +public: + // Rotate x bits to the left + // #define ROL32(value, bits) (((value)<<(bits))|((value)>>(32-(bits)))) + +#ifdef LITTLE_ENDIAN +#define SHABLK0(i) (block->l[i] = (ROL32(block->l[i],24) & 0xFF00FF00) \ + | (ROL32(block->l[i],8) & 0x00FF00FF)) +#else +#define SHABLK0(i) (block->l[i]) +#endif + +#define SHABLK(i) (block->l[i&15] = ROL32(block->l[(i+13)&15] ^ block->l[(i+8)&15] \ + ^ block->l[(i+2)&15] ^ block->l[i&15],1)) + + // SHA-1 rounds +#define R0(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK0(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); } +#define R1(v,w,x,y,z,i) { z+=((w&(x^y))^y)+SHABLK(i)+0x5A827999+ROL32(v,5); w=ROL32(w,30); } +#define R2(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0x6ED9EBA1+ROL32(v,5); w=ROL32(w,30); } +#define R3(v,w,x,y,z,i) { z+=(((w|x)&y)|(w&x))+SHABLK(i)+0x8F1BBCDC+ROL32(v,5); w=ROL32(w,30); } +#define R4(v,w,x,y,z,i) { z+=(w^x^y)+SHABLK(i)+0xCA62C1D6+ROL32(v,5); w=ROL32(w,30); } + + typedef union { + unsigned char c[ 64 ]; + unsigned int l[ 16 ]; + } SHA1_WORKSPACE_BLOCK; + /* Two different formats for ReportHash(...) + */ + enum { REPORT_HEX = 0, + REPORT_DIGIT = 1}; + + CSHA1(); + virtual ~CSHA1(); + + unsigned int m_state[ 5 ]; + unsigned int m_count[ 2 ]; + unsigned char m_buffer[ 64 ]; + unsigned char m_digest[ 20 ]; + void Reset(); + void Update( unsigned char* data, unsigned int len ); + bool HashFile( char *szFileName ); + void Final(); + void ReportHash( char *szReport, unsigned char uReportType = REPORT_HEX ); + void GetHash( unsigned char *uDest ); + unsigned char * GetHash( void ) const; + +private: + void Transform( unsigned int state[ 5 ], unsigned char buffer[ 64 ] ); + unsigned char workspace[ 64 ]; +}; + +#endif // ___SHA1_H___ + diff --git a/saco/saco.vcproj b/saco/saco.vcproj index b90c1ae..cb8638a 100644 --- a/saco/saco.vcproj +++ b/saco/saco.vcproj @@ -356,6 +356,12 @@ + + + + diff --git a/server/server.vcproj b/server/server.vcproj index 3a249d9..4fba585 100644 --- a/server/server.vcproj +++ b/server/server.vcproj @@ -214,6 +214,12 @@ + + + +