Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:13:13

0001 #include <iomanip>
0002 #include <sstream>
0003 
0004 #include "FWCore/Utilities/interface/EDMException.h"
0005 #include "FWCore/Utilities/interface/Digest.h"
0006 
0007 namespace cms {
0008   namespace {
0009     MD5Result const& invalidResult() {
0010       static const MD5Result val;
0011       return val;
0012     }
0013 
0014     char unhexify(char hexed) {
0015       switch (hexed) {
0016         case '0':
0017         case '1':
0018         case '2':
0019         case '3':
0020         case '4':
0021         case '5':
0022         case '6':
0023         case '7':
0024         case '8':
0025         case '9':
0026           return hexed - '0';
0027         case 'a':
0028         case 'b':
0029         case 'c':
0030         case 'd':
0031         case 'e':
0032         case 'f':
0033           return hexed - 'a' + 10;
0034         case 'A':
0035         case 'B':
0036         case 'C':
0037         case 'D':
0038         case 'E':
0039         case 'F':
0040           return hexed - 'A' + 10;
0041         default:
0042           throw edm::Exception(edm::errors::LogicError) << "Non-hex character in Hash "
0043                                                         << "Please report this to the core framework developers";
0044       }
0045       // We never get here; return put in place to calm the compiler's
0046       // anxieties.
0047       return '\0';
0048     }
0049   }  // namespace
0050 
0051   //--------------------------------------------------------------------
0052   //
0053   // MD5Result and associated free functions
0054   //
0055 
0056   void set_to_default(MD5Result& val) {
0057     val.bytes[0] = 0xd4;
0058     val.bytes[1] = 0x1d;
0059     val.bytes[2] = 0x8c;
0060     val.bytes[3] = 0xd9;
0061     val.bytes[4] = 0x8f;
0062     val.bytes[5] = 0x00;
0063     val.bytes[6] = 0xb2;
0064     val.bytes[7] = 0x04;
0065     val.bytes[8] = 0xe9;
0066     val.bytes[9] = 0x80;
0067     val.bytes[10] = 0x09;
0068     val.bytes[11] = 0x98;
0069     val.bytes[12] = 0xec;
0070     val.bytes[13] = 0xf8;
0071     val.bytes[14] = 0x42;
0072     val.bytes[15] = 0x7e;
0073   }
0074 
0075   MD5Result::MD5Result() { set_to_default(*this); }
0076 
0077   static const char* s_hexValues =
0078       "000102030405060708090a0b0c0d0e0f"
0079       "101112131415161718191a1b1c1d1e1f"
0080       "202122232425262728292a2b2c2d2e2f"
0081       "303132333435363738393a3b3c3d3e3f"
0082       "404142434445464748494a4b4c4d4e4f"
0083       "505152535455565758595a5b5c5d5e5f"
0084       "606162636465666768696a6b6c6d6e6f"
0085       "707172737475767778797a7b7c7d7e7f"
0086       "808182838485868788898a8b8c8d8e8f"
0087       "909192939495969798999a9b9c9d9e9f"
0088       "a0a1a2a3a4a5a6a7a8a9aaabacadaeaf"
0089       "b0b1b2b3b4b5b6b7b8b9babbbcbdbebf"
0090       "c0c1c2c3c4c5c6c7c8c9cacbcccdcecf"
0091       "d0d1d2d3d4d5d6d7d8d9dadbdcdddedf"
0092       "e0e1e2e3e4e5e6e7e8e9eaebecedeeef"
0093       "f0f1f2f3f4f5f6f7f8f9fafbfcfdfeff";
0094 
0095   std::string MD5Result::toString() const {
0096     std::array<char, 16 * 2> buf;
0097     char* pBuf = buf.begin();
0098     for (auto b : bytes) {
0099       const char* p = s_hexValues + 2 * b;
0100       *pBuf = *p;
0101       ++pBuf;
0102       ++p;
0103       *pBuf = *p;
0104       ++pBuf;
0105     }
0106     return std::string(buf.begin(), buf.end());
0107   }
0108 
0109   std::string MD5Result::compactForm() const {
0110     // This is somewhat dangerous, because the conversion of 'unsigned
0111     // char' to 'char' may be undefined if 'char' is a signed type
0112     // (4.7p3 in the Standard).
0113     const char* p = reinterpret_cast<const char*>(bytes.data());
0114     return std::string(p, p + bytes.size());
0115   }
0116 
0117   void MD5Result::fromHexifiedString(std::string const& hexy) {
0118     switch (hexy.size()) {
0119       case 0: {
0120         set_to_default(*this);
0121       } break;
0122       case 32: {
0123         std::string::const_iterator it = hexy.begin();
0124         for (size_t i = 0; i != 16; ++i) {
0125           // first nybble
0126           bytes[i] = (unhexify(*it++) << 4);
0127           // second nybble
0128           bytes[i] += (unhexify(*it++));
0129         }
0130       } break;
0131       default: {
0132         // Not really sure of what sort of exception to throw...
0133         throw edm::Exception(edm::errors::LogicError)
0134             << "String of illegal length: " << hexy.size() << " given to MD5Result::fromHexifiedString";
0135       }
0136     }
0137   }
0138 
0139   bool MD5Result::isValid() const { return (*this != invalidResult()); }
0140 
0141   bool operator==(MD5Result const& a, MD5Result const& b) {
0142     return std::equal(a.bytes.begin(), a.bytes.end(), b.bytes.begin());
0143   }
0144 
0145   bool operator<(MD5Result const& a, MD5Result const& b) {
0146     return std::lexicographical_compare(a.bytes.begin(), a.bytes.end(), b.bytes.begin(), b.bytes.end());
0147   }
0148 
0149   //--------------------------------------------------------------------
0150   //
0151   // Digest
0152   //
0153 
0154   Digest::Digest() : state_() { md5_init(&state_); }
0155 
0156   Digest::Digest(std::string const& s) : state_() {
0157     md5_init(&state_);
0158     this->append(s);
0159   }
0160 
0161   void Digest::append(std::string const& s) {
0162     const md5_byte_t* data = reinterpret_cast<const md5_byte_t*>(s.data());
0163     md5_append(&state_, const_cast<md5_byte_t*>(data), s.size());
0164   }
0165 
0166   void Digest::append(const char* s, size_t size) {
0167     const md5_byte_t* data = reinterpret_cast<const md5_byte_t*>(s);
0168     md5_append(&state_, const_cast<md5_byte_t*>(data), size);
0169   }
0170 
0171   MD5Result Digest::digest() {
0172     MD5Result aDigest;
0173     md5_finish(&state_, aDigest.bytes.data());
0174     return aDigest;
0175   }
0176 }  // namespace cms