MD5Sum.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002  * Copyright (C) 2014 by Ralf Kaestner                                        *
00003  * ralf.kaestner@gmail.com                                                    *
00004  *                                                                            *
00005  * This program is free software; you can redistribute it and/or modify       *
00006  * it under the terms of the Lesser GNU General Public License as published by*
00007  * the Free Software Foundation; either version 3 of the License, or          *
00008  * (at your option) any later version.                                        *
00009  *                                                                            *
00010  * This program is distributed in the hope that it will be useful,            *
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of             *
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the               *
00013  * Lesser GNU General Public License for more details.                        *
00014  *                                                                            *
00015  * You should have received a copy of the Lesser GNU General Public License   *
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.       *
00017  ******************************************************************************/
00018 
00019 #include "variant_topic_tools/MD5Sum.h"
00020 
00021 namespace variant_topic_tools {
00022 
00023 /*****************************************************************************/
00024 /* Static initializations                                                    */
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 /* Constructors and Destructor                                               */
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 /* Accessors                                                                 */
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 /* Methods                                                                   */
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 /* Operators                                                                 */
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 }


variant_topic_tools
Author(s): Ralf Kaestner
autogenerated on Tue Jul 9 2019 03:18:42