36 void init( md5_state_t & )
39 void update( md5_state_t & context ,
const std::string & input )
41 context.add( input ) ;
43 std::string finish( md5_state_t & context )
46 return format::raw( context.state().d ) ;
48 std::string writeOut(
const md5_state_t & context )
50 G_ASSERT( context.state().s.length() == 0U ) ;
51 G_ASSERT( context.state().n == 64U ) ;
52 std::ostringstream ss ;
54 context.state().d.a <<
"." <<
55 context.state().d.b <<
"." <<
56 context.state().d.c <<
"." <<
60 big_t toUnsigned(
const std::string & s ,
bool limited =
true )
64 if( s.empty() )
throw G::Md5::Error( s ) ;
66 for( std::string::const_iterator p = s.begin() ; p != s.end() ; ++p )
69 if( *p < '0' || *p >
'9' )
throw G::Md5::Error( s ) ;
70 const unsigned int n =
static_cast<unsigned int>(*p) -
static_cast<unsigned int>(
'0') ;
71 if( limited && (result+n) < result )
throw G::Md5::Error( s ) ;
76 G::StringArray::iterator readIn( md5_state_t & context , G::StringArray::iterator p )
78 big_t a = toUnsigned( *p++ ) ;
79 big_t b = toUnsigned( *p++ ) ;
80 big_t c = toUnsigned( *p++ ) ;
81 big_t d = toUnsigned( *p++ ) ;
82 state_type state = { a , b , c , d } ;
84 context = md5_state_t( state , magic_number ) ;
89 std::string G::Md5::xor_(
const std::string & s1 ,
const std::string & s2 )
91 G_ASSERT( s1.length() == s2.length() ) ;
92 std::string::const_iterator p1 = s1.begin() ;
93 std::string::const_iterator p2 = s2.begin() ;
95 result.reserve( s1.length() ) ;
96 for( ; p1 != s1.end() ; ++p1 , ++p2 )
98 unsigned char c1 =
static_cast<unsigned char>(*p1) ;
99 unsigned char c2 =
static_cast<unsigned char>(*p2) ;
100 unsigned char c =
static_cast<unsigned char>( c1 ^ c2 ) ;
101 result.append( 1U , static_cast<char>(c) ) ;
106 std::string G::Md5::key64( std::string k )
108 const size_t B = 64U ;
112 k.append( std::string(B-k.length(),
'\0') ) ;
113 G_ASSERT( k.length() == B ) ;
117 std::string G::Md5::ipad()
119 const size_t B = 64U ;
120 return std::string( B ,
'\066' ) ;
123 std::string G::Md5::opad()
125 const size_t B = 64U ;
126 return std::string( B ,
'\134' ) ;
131 std::string k64 = key64( k ) ;
132 return mask( k64 , ipad() ) +
"." + mask( k64 , opad() ) ;
135 std::string
G::Md5::mask(
const std::string & k64 ,
const std::string & pad )
137 md5_state_t context ;
139 update( context , xor_(k64,pad) ) ;
140 return writeOut( context ) ;
146 part_list.reserve( 8U ) ;
148 if( part_list.size() != 8U )
149 throw InvalidMaskedKey( masked_key ) ;
151 md5_state_t inner_context ;
152 md5_state_t outer_context ;
153 readIn( outer_context , readIn( inner_context , part_list.begin() ) ) ;
154 update( inner_context , input ) ;
155 update( outer_context , finish(inner_context) ) ;
156 return finish( outer_context ) ;
159 std::string
G::Md5::hmac(
const std::string & k ,
const std::string & input )
161 std::string k64 = key64( k ) ;
162 return digest( xor_(k64,opad()) , digest(xor_(k64,ipad()),input) ) ;
167 return digest( input ,
nullptr ) ;
170 std::string
G::Md5::digest(
const std::string & input_1 ,
const std::string & input_2 )
172 return digest( input_1 , &input_2 ) ;
175 std::string
G::Md5::digest(
const std::string & input_1 ,
const std::string * input_2 )
177 md5_state_t context ;
179 update( context , input_1 ) ;
180 if( input_2 !=
nullptr )
181 update( context , *input_2 ) ;
182 return finish( context ) ;
187 G_ASSERT( input.length() == 16U ) ;
190 const char * hex =
"0123456789abcdef" ;
191 const size_t n = input.length() ;
192 for(
size_t i = 0U ; i < n ; i++ )
194 unsigned char c =
static_cast<unsigned char>(input.at(i)) ;
195 result.append( 1U , hex[(c>>4U)&0x0F] ) ;
196 result.append( 1U , hex[(c>>0U)&0x0F] ) ;
A class that calculates an md5 digest from a data stream using the algorithm described by RFC 1321...
An overload discriminator for G::Md5::hmac()
size_type big_t
To hold at least 32 bits, maybe more. Try unsigned long on small systems.
size_type small_t
To hold at least a size_t. Must fit in a big_t.
std::vector< std::string > StringArray
A std::vector of std::strings.
static void splitIntoTokens(const std::string &in, StringArray &out, const std::string &ws)
Splits the string into 'ws'-delimited tokens.
static std::string hmac(const std::string &key, const std::string &input)
Computes a Hashed Message Authentication Code using MD5 as the hash function.
Holds the md5 algorithm state. Used by md5::digest.
static std::string mask(const std::string &key)
Computes a masked key for hmac() from the given shared key, returning a printable string...
static std::string digest(const std::string &input)
Creates an MD5 digest.
static std::string printable(const std::string &input)
Converts a binary string into a printable form, using a lowercase hexadecimal encoding.