00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "variant_topic_tools/MD5Sum.h"
00020
00021 namespace variant_topic_tools {
00022
00023
00024
00025
00026
00027 const MD5Sum::Digest MD5Sum::initialDigest = {
00028 0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476
00029 };
00030
00031 const boost::array<uint32_t, 64> MD5Sum::numBitRotations = {
00032 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22, 7, 12, 17, 22,
00033 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20, 5, 9, 14, 20,
00034 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23, 4, 11, 16, 23,
00035 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21, 6, 10, 15, 21
00036 };
00037
00038 const boost::array<uint32_t, 64> MD5Sum::constants = {
00039 0xd76aa478, 0xe8c7b756, 0x242070db, 0xc1bdceee,
00040 0xf57c0faf, 0x4787c62a, 0xa8304613, 0xfd469501,
00041 0x698098d8, 0x8b44f7af, 0xffff5bb1, 0x895cd7be,
00042 0x6b901122, 0xfd987193, 0xa679438e, 0x49b40821,
00043 0xf61e2562, 0xc040b340, 0x265e5a51, 0xe9b6c7aa,
00044 0xd62f105d, 0x02441453, 0xd8a1e681, 0xe7d3fbc8,
00045 0x21e1cde6, 0xc33707d6, 0xf4d50d87, 0x455a14ed,
00046 0xa9e3e905, 0xfcefa3f8, 0x676f02d9, 0x8d2a4c8a,
00047 0xfffa3942, 0x8771f681, 0x6d9d6122, 0xfde5380c,
00048 0xa4beea44, 0x4bdecfa9, 0xf6bb4b60, 0xbebfbc70,
00049 0x289b7ec6, 0xeaa127fa, 0xd4ef3085, 0x04881d05,
00050 0xd9d4d039, 0xe6db99e5, 0x1fa27cf8, 0xc4ac5665,
00051 0xf4292244, 0x432aff97, 0xab9423a7, 0xfc93a039,
00052 0x655b59c3, 0x8f0ccc92, 0xffeff47d, 0x85845dd1,
00053 0x6fa87e4f, 0xfe2ce6e0, 0xa3014314, 0x4e0811a1,
00054 0xf7537e82, 0xbd3af235, 0x2ad7d2bb, 0xeb86d391
00055 };
00056
00057 const MD5Sum::Block MD5Sum::padding = {
00058 0x00000080, 0x00000000, 0x00000000, 0x00000000,
00059 0x00000000, 0x00000000, 0x00000000, 0x00000000,
00060 0x00000000, 0x00000000, 0x00000000, 0x00000000,
00061 0x00000000, 0x00000000, 0x00000000, 0x00000000
00062 };
00063
00064
00065
00066
00067
00068 MD5Sum::MD5Sum(const std::string& text) {
00069 clear();
00070 update(text);
00071 }
00072
00073 MD5Sum::MD5Sum(const MD5Sum& src) :
00074 digest(src.digest),
00075 numDigestedBits(src.numDigestedBits),
00076 buffer(src.buffer) {
00077 }
00078
00079 MD5Sum::~MD5Sum() {
00080 }
00081
00082
00083
00084
00085
00086 size_t MD5Sum::getNumDigestedBits() const {
00087 const uint8_t* numDigestedBits = reinterpret_cast<const uint8_t*>(
00088 this->numDigestedBits.data());
00089 size_t i = this->numDigestedBits.size()*sizeof(uint32_t)-sizeof(size_t);
00090
00091 return *reinterpret_cast<const size_t*>(&numDigestedBits[i]);
00092 }
00093
00094 MD5Sum::Digest MD5Sum::getDigest() const {
00095 Digest digest(this->digest);
00096 Size numDigestedBits(this->numDigestedBits);
00097 Block buffer(this->buffer);
00098
00099 finalize(digest, numDigestedBits, buffer);
00100
00101 return digest;
00102 }
00103
00104
00105
00106
00107
00108 void MD5Sum::update(const std::string& text) {
00109 if (!text.empty())
00110 update(reinterpret_cast<const uint8_t*>(text.data()), text.length());
00111 }
00112
00113 void MD5Sum::update(const uint8_t* bytes, size_t numBytes) {
00114 update(digest, numDigestedBits, buffer, bytes, numBytes);
00115 }
00116
00117 void MD5Sum::clear() {
00118 digest = initialDigest;
00119
00120 numDigestedBits.fill(0);
00121 buffer.fill(0);
00122 }
00123
00124 void MD5Sum::write(std::ostream& stream) const {
00125 stream << toString();
00126 }
00127
00128 std::string MD5Sum::toString() const {
00129 Digest digest = getDigest();
00130
00131 char stringData[2*digest.size()*sizeof(uint32_t)+1];
00132 const uint8_t* digestData = reinterpret_cast<const uint8_t*>(
00133 digest.data());
00134
00135 for (size_t i = 0; i < digest.size()*sizeof(uint32_t); ++i)
00136 sprintf(&stringData[2*i], "%02x", digestData[i]);
00137 stringData[2*digest.size()*sizeof(uint32_t)] = 0;
00138
00139 return std::string(stringData);
00140 }
00141
00142 void MD5Sum::transform(const Block& block, Digest& digest) {
00143 uint32_t a = digest[0];
00144 uint32_t b = digest[1];
00145 uint32_t c = digest[2];
00146 uint32_t d = digest[3];
00147
00148 for (size_t i = 0; i < 64; ++i) {
00149 uint32_t f, g, h;
00150
00151 if (i < 16) {
00152 f = (b & c) | (~b & d);
00153 g = i;
00154 }
00155 else if (i < 32) {
00156 f = (b & d) | (c & ~d);
00157 g = (5*i+1) % 16;
00158 }
00159 else if (i < 48) {
00160 f = b ^ c ^ d;
00161 g = (3*i+5) % 16;
00162 }
00163 else if (i < 64) {
00164 f = c ^ (b | ~d);
00165 g = (7*i) % 16;
00166 }
00167
00168 h = d;
00169 d = c;
00170 c = b;
00171 b += rotateLeft(a+f+constants[i]+block[g], numBitRotations[i]);
00172 a = h;
00173 }
00174
00175 digest[0] += a;
00176 digest[1] += b;
00177 digest[2] += c;
00178 digest[3] += d;
00179 }
00180
00181 uint32_t MD5Sum::rotateLeft(uint32_t value, size_t numBits) {
00182 return (value << numBits)|(value >> (sizeof(uint32_t)*8-numBits));
00183 }
00184
00185 void MD5Sum::update(Digest& digest, Size& numDigestedBits, Block& buffer,
00186 const uint8_t* bytes, size_t numBytes) {
00187 size_t i = numDigestedBits[0]/8 % 64;
00188 size_t lengthOfFirstPart = 64-i;
00189 size_t j = 0;
00190
00191 if ((numDigestedBits[0] += (numBytes << 3)) < (numBytes << 3))
00192 ++numDigestedBits[1];
00193 numDigestedBits[1] += (numBytes >> 29);
00194
00195 if (numBytes >= lengthOfFirstPart) {
00196 std::copy(&bytes[0], &bytes[lengthOfFirstPart],
00197 &reinterpret_cast<uint8_t*>(buffer.data())[i]);
00198 transform(buffer, digest);
00199
00200 for (j = lengthOfFirstPart; j+64 <= numBytes; j += 64) {
00201 Block block;
00202
00203 std::copy(&bytes[j], &bytes[j+64], reinterpret_cast<uint8_t*>(
00204 block.data()));
00205 transform(block, digest);
00206 }
00207
00208 i = 0;
00209 }
00210 else
00211 j = 0;
00212
00213 std::copy(&bytes[j], &bytes[numBytes],
00214 &reinterpret_cast<uint8_t*>(buffer.data())[i]);
00215 }
00216
00217 void MD5Sum::finalize(Digest& digest, Size& numDigestedBits, Block& buffer) {
00218 Size finalNumDigestedBits(numDigestedBits);
00219 size_t i = numDigestedBits[0]/8 % 64;
00220 size_t paddedLength = (i < 56) ? 56-i : 120-i;
00221
00222 update(digest, numDigestedBits, buffer, reinterpret_cast<const uint8_t*>(
00223 padding.data()), paddedLength);
00224 update(digest, numDigestedBits, buffer, reinterpret_cast<const uint8_t*>(
00225 finalNumDigestedBits.data()), 8);
00226 }
00227
00228
00229
00230
00231
00232 MD5Sum& MD5Sum::operator<<(const std::string& text) {
00233 update(text);
00234 return *this;
00235 }
00236
00237 std::ostream& operator<<(std::ostream& stream, const MD5Sum& md5Sum) {
00238 md5Sum.write(stream);
00239 return stream;
00240 }
00241
00242 }