35 using small_t = G::Md5::small_t ;
36 using big_t = G::Md5::big_t ;
58 explicit digest(
const std::string & s ) ;
74 void add(
const block & ) ;
78 using aux_fn_t = big_t (*)(big_t, big_t, big_t) ;
79 enum class Permutation { ABCD , DABC , CDAB , BCDA } ;
80 using P = Permutation ;
84 void add(
const digest & ) ;
86 void calculate(
const block & ) ;
87 static big_t T( small_t i ) ;
88 static big_t rot32( small_t places , big_t n ) ;
89 void operator()(
const block & , aux_fn_t , Permutation , small_t , small_t , small_t ) ;
90 static big_t op(
const block & , aux_fn_t , big_t , big_t , big_t , big_t , small_t , small_t , small_t ) ;
91 void round1(
const block & ) ;
92 void round2(
const block & ) ;
93 void round3(
const block & ) ;
94 void round4(
const block & ) ;
95 static big_t F( big_t x , big_t y , big_t z ) ;
96 static big_t
G( big_t x , big_t y , big_t z ) ;
97 static big_t H( big_t x , big_t y , big_t z ) ;
98 static big_t I( big_t x , big_t y , big_t z ) ;
111 static std::string encode(
const digest_state & , big_t n ) ;
115 static digest_state decode(
const std::string & , small_t & ) ;
130 block(
const std::string & s , small_t block_offset , big_t end_value ) ;
146 static big_t end( small_t data_length ) ;
152 static small_t blocks( small_t data_length ) ;
158 big_t X( small_t )
const ;
165 void operator=(
const block & ) = delete ;
166 void operator=(
block && ) = delete ;
169 small_t x( small_t )
const ;
170 static small_t rounded( small_t n ) ;
173 const std::string & m_s ;
180G::Md5Imp::digest::digest() :
186G::Md5Imp::digest::digest(
const std::string & s ) :
190 small_t n = block::blocks( s.length() ) ;
191 for( small_t i = 0U ; i < n ; ++i )
193 block blk( s , i , block::end(s.length()) ) ;
198G::Md5Imp::digest::digest( digest_state d_in ) :
207void G::Md5Imp::digest::init()
215G::Md5Imp::digest::digest_state G::Md5Imp::digest::state()
const
218 small_t thirty_two = 32U ;
219 small_t sizeof_thirty_two_bits = 4U ;
220 if(
sizeof(mask) > sizeof_thirty_two_bits )
223 mask <<= thirty_two ;
225 digest_state result = { a & ~mask , b & ~mask , c & ~mask , d & ~mask } ;
229void G::Md5Imp::digest::add(
const block & blk )
231 digest old( *
this ) ;
239void G::Md5Imp::digest::add(
const digest & other )
247void G::Md5Imp::digest::round1(
const block & m )
250 r(m,F,P::ABCD, 0, 7, 1); r(m,F,P::DABC, 1,12, 2); r(m,F,P::CDAB, 2,17, 3); r(m,F,P::BCDA, 3,22, 4);
251 r(m,F,P::ABCD, 4, 7, 5); r(m,F,P::DABC, 5,12, 6); r(m,F,P::CDAB, 6,17, 7); r(m,F,P::BCDA, 7,22, 8);
252 r(m,F,P::ABCD, 8, 7, 9); r(m,F,P::DABC, 9,12,10); r(m,F,P::CDAB,10,17,11); r(m,F,P::BCDA,11,22,12);
253 r(m,F,P::ABCD,12, 7,13); r(m,F,P::DABC,13,12,14); r(m,F,P::CDAB,14,17,15); r(m,F,P::BCDA,15,22,16);
256void G::Md5Imp::digest::round2(
const block & m )
259 r(m,
G,P::ABCD, 1, 5,17); r(m,
G,P::DABC, 6, 9,18); r(m,
G,P::CDAB,11,14,19); r(m,
G,P::BCDA, 0,20,20);
260 r(m,
G,P::ABCD, 5, 5,21); r(m,
G,P::DABC,10, 9,22); r(m,
G,P::CDAB,15,14,23); r(m,
G,P::BCDA, 4,20,24);
261 r(m,
G,P::ABCD, 9, 5,25); r(m,
G,P::DABC,14, 9,26); r(m,
G,P::CDAB, 3,14,27); r(m,
G,P::BCDA, 8,20,28);
262 r(m,
G,P::ABCD,13, 5,29); r(m,
G,P::DABC, 2, 9,30); r(m,
G,P::CDAB, 7,14,31); r(m,
G,P::BCDA,12,20,32);
265void G::Md5Imp::digest::round3(
const block & m )
268 r(m,H,P::ABCD, 5, 4,33); r(m,H,P::DABC, 8,11,34); r(m,H,P::CDAB,11,16,35); r(m,H,P::BCDA,14,23,36);
269 r(m,H,P::ABCD, 1, 4,37); r(m,H,P::DABC, 4,11,38); r(m,H,P::CDAB, 7,16,39); r(m,H,P::BCDA,10,23,40);
270 r(m,H,P::ABCD,13, 4,41); r(m,H,P::DABC, 0,11,42); r(m,H,P::CDAB, 3,16,43); r(m,H,P::BCDA, 6,23,44);
271 r(m,H,P::ABCD, 9, 4,45); r(m,H,P::DABC,12,11,46); r(m,H,P::CDAB,15,16,47); r(m,H,P::BCDA, 2,23,48);
274void G::Md5Imp::digest::round4(
const block & m )
277 r(m,I,P::ABCD, 0, 6,49); r(m,I,P::DABC, 7,10,50); r(m,I,P::CDAB,14,15,51); r(m,I,P::BCDA, 5,21,52);
278 r(m,I,P::ABCD,12, 6,53); r(m,I,P::DABC, 3,10,54); r(m,I,P::CDAB,10,15,55); r(m,I,P::BCDA, 1,21,56);
279 r(m,I,P::ABCD, 8, 6,57); r(m,I,P::DABC,15,10,58); r(m,I,P::CDAB, 6,15,59); r(m,I,P::BCDA,13,21,60);
280 r(m,I,P::ABCD, 4, 6,61); r(m,I,P::DABC,11,10,62); r(m,I,P::CDAB, 2,15,63); r(m,I,P::BCDA, 9,21,64);
283void G::Md5Imp::digest::operator()(
const block & m , aux_fn_t aux , Permutation p ,
284 small_t k , small_t s , small_t i )
286 if( p == P::ABCD ) a = op( m , aux , a , b , c , d , k , s , i ) ;
287 if( p == P::DABC ) d = op( m , aux , d , a , b , c , k , s , i ) ;
288 if( p == P::CDAB ) c = op( m , aux , c , d , a , b , k , s , i ) ;
289 if( p == P::BCDA ) b = op( m , aux , b , c , d , a , k , s , i ) ;
292G::Md5Imp::big_t G::Md5Imp::digest::op(
const block & m , aux_fn_t aux , big_t a , big_t b , big_t c , big_t d ,
293 small_t k , small_t s , small_t i )
295 return b + rot32( s , ( a + (*aux)( b , c , d ) + m.X(k) + T(i) ) ) ;
298G::Md5Imp::big_t G::Md5Imp::digest::rot32( small_t places , big_t n )
301 big_t overflow_mask = ( big_t(1U) << places ) - big_t(1U) ;
302 big_t overflow = ( n >> ( small_t(32U) - places ) ) ;
303 return ( n << places ) | ( overflow & overflow_mask ) ;
306G::Md5Imp::big_t G::Md5Imp::digest::F( big_t x , big_t y , big_t z )
308 return ( x & y ) | ( ~x & z ) ;
311G::Md5Imp::big_t G::Md5Imp::digest::G( big_t x , big_t y , big_t z )
313 return ( x & z ) | ( y & ~z ) ;
316G::Md5Imp::big_t G::Md5Imp::digest::H( big_t x , big_t y , big_t z )
321G::Md5Imp::big_t G::Md5Imp::digest::I( big_t x , big_t y , big_t z )
323 return y ^ ( x | ~z ) ;
326G::Md5Imp::big_t G::Md5Imp::digest::T( small_t i )
330 static std::array<big_t,64U> t_map {{
395 G_ASSERT( i > 0 && i <= t_map.size() ) ;
401std::string G::Md5Imp::format::encode(
const digest_state & state )
403 const std::array<big_t,4U> state_array {{ state.a , state.b , state.c , state.d }} ;
407std::string G::Md5Imp::format::encode(
const digest_state & state , big_t n )
409 const std::array<big_t,4U> state_array {{ state.a , state.b , state.c , state.d }} ;
415 std::array<big_t,4U> state_array {{ 0 , 0 , 0 , 0 }} ;
417 digest_state result = { 0 , 0 , 0 , 0 } ;
418 result.a = state_array[0] ;
419 result.b = state_array[1] ;
420 result.c = state_array[2] ;
421 result.d = state_array[3] ;
427G::Md5Imp::block::block(
const std::string & s , small_t block_in , big_t end_value ) :
430 m_end_value(end_value)
434G::Md5Imp::big_t G::Md5Imp::block::end( small_t length )
436 big_t result = length ;
441G::Md5Imp::small_t G::Md5Imp::block::rounded( small_t raw_byte_count )
443 small_t n = raw_byte_count + 64U ;
444 return n - ( ( raw_byte_count + 8U ) % 64U ) ;
447G::Md5Imp::small_t G::Md5Imp::block::blocks( small_t raw_byte_count )
449 small_t byte_count = rounded(raw_byte_count) + 8U ;
450 return byte_count / 64UL ;
453G::Md5Imp::big_t G::Md5Imp::block::X( small_t dword_index )
const
455 small_t byte_index = ( m_block * 64U ) + ( dword_index * 4U ) ;
456 big_t result = x( byte_index + 3U ) ;
457 result <<= 8U ; result += x( byte_index + 2U ) ;
458 result <<= 8U ; result += x( byte_index + 1U ) ;
459 result <<= 8U ; result += x( byte_index + 0U ) ;
463G::Md5Imp::small_t G::Md5Imp::block::x( small_t i )
const
465 small_t length = m_s.length() ;
468 return static_cast<unsigned char>(m_s[i]) ;
470 else if( i < rounded(length) )
472 return i == length ? 128U : 0U ;
476 small_t byte_shift = i - rounded(length) ;
477 if( byte_shift >=
sizeof(big_t) )
483 small_t bit_shift = byte_shift * 8U ;
485 big_t end_value = m_end_value >> bit_shift ;
486 return static_cast<small_t
>( end_value & 0xffUL ) ;
494 m_d(Md5Imp::digest().state())
499 m_d(Md5Imp::
format::decode(str_state,m_n))
501 G_ASSERT( str_state.size() == (
valuesize()+4U) ) ;
506 G_ASSERT( Md5Imp::format::encode(m_d,m_n).size() == (valuesize()+4U) ) ;
507 return Md5Imp::format::encode( m_d , m_n ) ;
515 m_n += data.length() ;
516 while( m_s.length() >= 64U )
520 m_s.erase( 0U , 64U ) ;
532 return Md5Imp::format::encode( m_d ) ;
538 return Md5Imp::format::encode( dd.state() ) ;
541std::string
G::Md5::digest(
const std::string & input_1 ,
const std::string & input_2 )
549std::string
G::Md5::digest2(
const std::string & input_1 ,
const std::string & input_2 )
551 return digest( input_1 , input_2 ) ;
558 G_ASSERT( input.size() == blocksize() ) ;
559 return x.
state().substr(0U,valuesize()) ;
564 if( state_pair.size() != 32U )
565 throw InvalidState() ;
567 std::string _64(
"\x40\0\0\0" , 4U ) ;
568 std::string state_i = state_pair.substr( 0U , state_pair.size()/2 ) + _64 ;
569 std::string state_o = state_pair.substr( state_pair.size()/2 ) + _64 ;
static std::string encode(const uint_type *)
Returns the hash state as an N-character string of non-printing characters.
static void decode(const std::string &s, uint_type *values_out, size_type &size_out)
Converts an encode()d string back into a hash state of N/4 integers and a data size returned by refer...
A helper class used by the Md5Imp::digest implementation to represent a 64-character data block.
A class that calculates an md5 digest from one or more 64-byte blocks of data using the algorithm des...
MD5 message digest class.
static std::string postdigest(const std::string &state_pair, const std::string &message)
A convenience function that returns the value() from an outer digest that is initialised with the sec...
static std::size_t blocksize()
Returns the block size in bytes (64).
static std::string predigest(const std::string &padded_key)
A convenience function that add()s the given string of length blocksize() (typically a padded key) an...
static std::string digest2(const std::string &input_1, const std::string &input_2)
A non-overloaded name for the digest() overload taking two parameters.
static std::string digest(const std::string &input)
A convenience function that returns a digest from one input.
void add(const std::string &data)
Adds more data.
std::string value()
Returns the hash value as a 16-character string.
static std::size_t statesize()
Returns the size of the state() string (20).
static std::size_t valuesize()
Returns the value() size in bytes (16).
Md5()
Default constructor.
std::string state() const
Returns the current intermediate state as a 20 character string, although this requires the size of t...
Holds the four parts of the md5 state.