36 void init( md5_state_t & )
39 void update( md5_state_t & context ,
const std::string & input )
41 context.add( input ) ;
43 std::string
final( 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 )
70 ( *p ==
'0' ) ? 0U : (
71 ( *p ==
'1' ) ? 1U : (
72 ( *p ==
'2' ) ? 2U : (
73 ( *p ==
'3' ) ? 3U : (
74 ( *p ==
'4' ) ? 4U : (
75 ( *p ==
'5' ) ? 5U : (
76 ( *p ==
'6' ) ? 6U : (
77 ( *p ==
'7' ) ? 7U : (
78 ( *p ==
'8' ) ? 8U : (
79 ( *p ==
'9' ) ? 9U : 10U ))))))))) ;
80 if( n == 10U )
throw G::Md5::Error( s ) ;
81 if( limited && (result+n) < result )
throw G::Md5::Error( s ) ;
86 void readIn( md5_state_t & context ,
G::Strings & s )
88 big_t a = toUnsigned( s.front() ) ; s.pop_front() ;
89 big_t b = toUnsigned( s.front() ) ; s.pop_front() ;
90 big_t c = toUnsigned( s.front() ) ; s.pop_front() ;
91 big_t d = toUnsigned( s.front() ) ; s.pop_front() ;
92 state_type state = { a , b , c , d } ;
94 context = md5_state_t( state , magic_number ) ;
98 std::string G::Md5::xor_(
const std::string & s1 ,
const std::string & s2 )
100 G_ASSERT( s1.length() == s2.length() ) ;
101 std::string::const_iterator p1 = s1.begin() ;
102 std::string::const_iterator p2 = s2.begin() ;
104 for( ; p1 != s1.end() ; ++p1 , ++p2 )
106 unsigned char c1 =
static_cast<unsigned char>(*p1) ;
107 unsigned char c2 =
static_cast<unsigned char>(*p2) ;
108 unsigned char c =
static_cast<unsigned char>( c1 ^ c2 ) ;
109 result.append( 1U , static_cast<char>(c) ) ;
114 std::string G::Md5::key64( std::string k )
116 const size_t B = 64U ;
120 k.append( std::string(B-k.length(),
'\0') ) ;
125 std::string G::Md5::ipad()
127 const size_t B = 64U ;
128 return std::string( B ,
'\066' ) ;
131 std::string G::Md5::opad()
133 const size_t B = 64U ;
134 return std::string( B ,
'\134' ) ;
139 std::string k64 = key64( k ) ;
140 return mask( k64 , ipad() ) +
"." + mask( k64 , opad() ) ;
143 std::string
G::Md5::mask(
const std::string & k64 ,
const std::string & pad )
145 md5_state_t context ;
147 update( context , xor_(k64,pad) ) ;
148 return writeOut( context ) ;
155 if( part_list.size() != 8U )
156 throw InvalidMaskedKey( masked_key ) ;
158 md5_state_t inner_context ;
159 md5_state_t outer_context ;
160 readIn( inner_context , part_list ) ;
161 readIn( outer_context , part_list ) ;
162 update( inner_context , input ) ;
163 update( outer_context ,
final(inner_context) ) ;
164 return final( outer_context ) ;
167 std::string
G::Md5::hmac(
const std::string & k ,
const std::string & input )
169 std::string k64 = key64( k ) ;
170 return digest( xor_(k64,opad()) , digest(xor_(k64,ipad()),input) ) ;
175 return digest( input , NULL ) ;
178 std::string
G::Md5::digest(
const std::string & input_1 ,
const std::string & input_2 )
180 return digest( input_1 , &input_2 ) ;
183 std::string
G::Md5::digest(
const std::string & input_1 ,
const std::string * input_2 )
185 md5_state_t context ;
187 update( context , input_1 ) ;
188 if( input_2 != NULL )
189 update( context , *input_2 ) ;
190 return final( context ) ;
198 const char * hex =
"0123456789abcdef" ;
199 const size_t n = input.length() ;
200 for(
size_t i = 0U ; i < n ; i++ )
202 unsigned char c =
static_cast<unsigned char>(input.at(i)) ;
203 result.append( 1U , hex[(c>>4U)&0x0F] ) ;
204 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::list< std::string > Strings
A std::list of std::strings.
static void splitIntoTokens(const std::string &in, Strings &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)
Masks an HMAC key so that it can be stored more safely.
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.