sha.cpp
/*
Copyright (c) 2006-2023 by Jakob Schröter <js@camaya.net>
This file is part of the gloox library. http://camaya.net/gloox
This software is distributed under a license. The full license
agreement can be found in the file LICENSE in this distribution.
This software may not be copied, modified, sold or distributed
other than expressed in the named license agreement.
This software is distributed without any warranty.
*/
#include "config.h"
#include "sha.h"
#include "gloox.h"
#include <cstdio>
namespace gloox
{
SHA::SHA()
{
init();
}
SHA::~SHA()
{
}
void SHA::init()
{
Length_Low = 0;
Length_High = 0;
Message_Block_Index = 0;
H[0] = 0x67452301;
H[1] = 0xEFCDAB89;
H[2] = 0x98BADCFE;
H[3] = 0x10325476;
H[4] = 0xC3D2E1F0;
m_finished = false;
m_corrupted = false;
}
void SHA::reset()
{
init();
}
const std::string SHA::hex()
{
if( m_corrupted )
return EmptyString;
if( !m_finished )
finalize();
char buf[41];
for( int i = 0; i < 20; ++i )
sprintf( buf + i * 2, "%02x", static_cast<unsigned char>( H[i >> 2] >> ( ( 3 - ( i & 3 ) ) << 3 ) ) );
return std::string( buf, 40 );
}
const std::string SHA::binary()
{
if( !m_finished )
finalize();
unsigned char digest[20];
for( int i = 0; i < 20; ++i )
digest[i] = static_cast<unsigned char>( H[i >> 2] >> ( ( 3 - ( i & 3 ) ) << 3 ) );
return std::string( reinterpret_cast<char*>( digest ), 20 );
}
void SHA::finalize()
{
if( !m_finished )
{
pad();
m_finished = true;
}
}
void SHA::feed( const unsigned char* data, unsigned length )
{
if( !length )
return;
if( m_finished || m_corrupted )
{
m_corrupted = true;
return;
}
while( length-- && !m_corrupted )
{
Message_Block[Message_Block_Index++] = ( *data & 0xFF );
Length_Low += 8;
Length_Low &= 0xFFFFFFFF;
if( Length_Low == 0 )
{
Length_High++;
Length_High &= 0xFFFFFFFF;
if( Length_High == 0 )
{
m_corrupted = true;
}
}
if( Message_Block_Index == 64 )
{
process();
}
++data;
}
}
void SHA::feed( const std::string& data )
{
feed( reinterpret_cast<const unsigned char*>( data.c_str() ), static_cast<int>( data.length() ) );
}
void SHA::process()
{
const unsigned K[] = { 0x5A827999,
0x6ED9EBA1,
0x8F1BBCDC,
0xCA62C1D6
};
int t;
unsigned temp;
unsigned W[80];
unsigned A, B, C, D, E;
for( t = 0; t < 16; t++ )
{
W[t] = static_cast<unsigned int>( Message_Block[t * 4] ) << 24;
W[t] |= static_cast<unsigned int>( Message_Block[t * 4 + 1] ) << 16;
W[t] |= static_cast<unsigned int>( Message_Block[t * 4 + 2] ) << 8;
W[t] |= static_cast<unsigned int>( Message_Block[t * 4 + 3] );
}
for( t = 16; t < 80; ++t )
{
W[t] = shift( 1, W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16] );
}
A = H[0];
B = H[1];
C = H[2];
D = H[3];
E = H[4];
for( t = 0; t < 20; ++t )
{
temp = shift( 5, A ) + ( ( B & C ) | ( ( ~B ) & D ) ) + E + W[t] + K[0];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = shift( 30, B );
B = A;
A = temp;
}
for( t = 20; t < 40; ++t )
{
temp = shift( 5, A ) + ( B ^ C ^ D ) + E + W[t] + K[1];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = shift( 30, B );
B = A;
A = temp;
}
for( t = 40; t < 60; ++t )
{
temp = shift( 5, A ) + ( ( B & C ) | ( B & D ) | ( C & D ) ) + E + W[t] + K[2];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = shift( 30, B );
B = A;
A = temp;
}
for( t = 60; t < 80; ++t )
{
temp = shift( 5, A ) + ( B ^ C ^ D ) + E + W[t] + K[3];
temp &= 0xFFFFFFFF;
E = D;
D = C;
C = shift( 30, B );
B = A;
A = temp;
}
H[0] = ( H[0] + A ) & 0xFFFFFFFF;
H[1] = ( H[1] + B ) & 0xFFFFFFFF;
H[2] = ( H[2] + C ) & 0xFFFFFFFF;
H[3] = ( H[3] + D ) & 0xFFFFFFFF;
H[4] = ( H[4] + E ) & 0xFFFFFFFF;
Message_Block_Index = 0;
}
void SHA::pad()
{
Message_Block[Message_Block_Index++] = 0x80;
if( Message_Block_Index > 56 )
{
while( Message_Block_Index < 64 )
{
Message_Block[Message_Block_Index++] = 0;
}
process();
}
while( Message_Block_Index < 56 )
{
Message_Block[Message_Block_Index++] = 0;
}
Message_Block[56] = static_cast<unsigned char>( ( Length_High >> 24 ) & 0xFF );
Message_Block[57] = static_cast<unsigned char>( ( Length_High >> 16 ) & 0xFF );
Message_Block[58] = static_cast<unsigned char>( ( Length_High >> 8 ) & 0xFF );
Message_Block[59] = static_cast<unsigned char>( ( Length_High ) & 0xFF );
Message_Block[60] = static_cast<unsigned char>( ( Length_Low >> 24 ) & 0xFF );
Message_Block[61] = static_cast<unsigned char>( ( Length_Low >> 16 ) & 0xFF );
Message_Block[62] = static_cast<unsigned char>( ( Length_Low >> 8 ) & 0xFF );
Message_Block[63] = static_cast<unsigned char>( ( Length_Low ) & 0xFF );
process();
}
unsigned SHA::shift( int bits, unsigned word )
{
return ( ( word << bits ) & 0xFFFFFFFF) | ( ( word & 0xFFFFFFFF ) >> ( 32-bits ) );
}
}
gloox::SHA::~SHA
virtual ~SHA()
Definition sha.cpp:28
gloox::SHA::finalize
void finalize()
Definition sha.cpp:80
gloox::SHA::SHA
SHA()
Definition sha.cpp:23
gloox::SHA::feed
void feed(const unsigned char *data, unsigned length)
Definition sha.cpp:89
gloox::SHA::binary
const std::string binary()
Definition sha.cpp:68
gloox::SHA::hex
const std::string hex()
Definition sha.cpp:53
gloox::SHA::reset
void reset()
Definition sha.cpp:48
gloox
The namespace for the gloox library.
Definition adhoc.cpp:28
gloox::EmptyString
const std::string EmptyString
Definition gloox.cpp:124