/* RFC 1321 compliante MD% implementation * * little-endian optimizations but works on all byte orderings * */ #include #include #include #include #include "debug.h" //see md5_t.pl to understand T values #include "md5_t.h" //initial values of digest #define A0 0x01234567 #define B0 0x89abcdef #define C0 0xfedcba98 #define D0 0x76543210 //auxiliary functions static inline uint32_t rotate_left(const uint32_t &x, const unsigned int n) { return ((x<>(32-n))); } static inline uint32_t F(const uint32_t &x,const uint32_t &y,const uint32_t &z) { return ( (x&y) | ((~(x))&z) ); } static inline uint32_t G(const uint32_t &x,const uint32_t &y,const uint32_t &z) { return ( (x&z) | (y&(~z)) ); } static inline uint32_t H(const uint32_t &x,const uint32_t &y,const uint32_t &z) { return ( (x) ^ (y) ^ (z) ); } static inline uint32_t I(const uint32_t &x,const uint32_t &y,const uint32_t &z) { return ( y ^ (x | (~z)) ); } static const size_t block_size = 16 * /*4 byte words*/ 4; namespace xstream{ namespace digest{ //this is where the actual digest work is made //buf should be 32*16 bytes long static void process_chunk( uint32_t& AA, uint32_t& BB, uint32_t& CC, uint32_t& DD, char* _buf) { LOG("md5::process_chunk (A,B,C,D) = ("<(_buf); #if ARCH_LITTLE_ENDIAN //on some systems this can be tricky due to allignment issues //some compiler flags may solve that //if it doesn' work ok, try configure without ARCH_LITTLE_ENDIAN uint32_t* wbuf = reinterpret_cast(buf); #else uint32_t wbuf[block_size/4]; //word buffer //we have to copy the words by a byte ordering agnostic procedure for(unsigned int i=0,j=0; i>=8; } } std::ostream& operator<<(std::ostream& o, const struct md5::result& r) { std::ios::fmtflags orig = o.flags(); o.setf(std::ios::hex, std::ios::basefield); print_hex(o, r.a); print_hex(o, r.b); print_hex(o, r.c); print_hex(o, r.d); o.flags(orig); return o; } }//namespace digest }//namespace xstream