File indexing completed on 2025-01-19 03:54:58
0001 /*****************************************************************************/ 0002 // Copyright 2006-2019 Adobe Systems Incorporated 0003 // All Rights Reserved. 0004 // 0005 // NOTICE: Adobe permits you to use, modify, and distribute this file in 0006 // accordance with the terms of the Adobe license agreement accompanying it. 0007 /*****************************************************************************/ 0008 0009 /** \file 0010 * Fingerprint (cryptographic hashing) support for generating strong hashes of image 0011 * data. 0012 */ 0013 0014 /*****************************************************************************/ 0015 0016 #ifndef __dng_fingerprint__ 0017 #define __dng_fingerprint__ 0018 0019 /*****************************************************************************/ 0020 0021 #include "dng_exceptions.h" 0022 #include "dng_types.h" 0023 #include "dng_stream.h" 0024 0025 #include <cstring> 0026 0027 /*****************************************************************************/ 0028 0029 /// \brief Container fingerprint (MD5 only at present). 0030 0031 class dng_fingerprint 0032 { 0033 0034 public: 0035 0036 static const size_t kDNGFingerprintSize = 16; 0037 0038 uint8 data [kDNGFingerprintSize]; 0039 0040 public: 0041 0042 dng_fingerprint (); 0043 0044 dng_fingerprint (const char *hex); 0045 0046 /// Check if fingerprint is all zeros. 0047 0048 bool IsNull () const; 0049 0050 /// Same as IsNull but expresses intention of testing validity. 0051 0052 bool IsValid () const 0053 { 0054 return !IsNull (); 0055 } 0056 0057 /// Set to all zeros, a value used to indicate an invalid fingerprint. 0058 0059 void Clear () 0060 { 0061 *this = dng_fingerprint (); 0062 } 0063 0064 /// Test if two fingerprints are equal. 0065 0066 bool operator== (const dng_fingerprint &print) const; 0067 0068 /// Test if two fingerprints are not equal. 0069 0070 bool operator!= (const dng_fingerprint &print) const 0071 { 0072 return !(*this == print); 0073 } 0074 0075 /// Comparision test for fingerprints. 0076 0077 bool operator< (const dng_fingerprint &print) const; 0078 0079 /// Produce a 32-bit hash value from fingerprint used for faster hashing of 0080 /// fingerprints. 0081 0082 uint32 Collapse32 () const; 0083 0084 /// Convert fingerprint to UTF-8 string. 0085 /// 0086 /// \param resultStr The output array to which the UTF-8 encoding of the 0087 /// fingerprint will be written. 0088 0089 void ToUtf8HexString (char resultStr [2 * kDNGFingerprintSize + 1]) const; 0090 0091 /// Convert UTF-8 string to fingerprint. Returns true on success, false on 0092 /// failure. 0093 /// 0094 /// \param inputStr The input array from which the UTF-8 encoding of the 0095 /// fingerprint will be read. 0096 /// 0097 /// \retval True indicates success. 0098 0099 bool FromUtf8HexString (const char inputStr [2 * kDNGFingerprintSize + 1]); 0100 0101 }; 0102 0103 /*****************************************************************************/ 0104 0105 /// \brief Utility to compare fingerprints (e.g., for sorting). 0106 0107 struct dng_fingerprint_less_than 0108 { 0109 0110 /// Less-than comparison. 0111 0112 bool operator() (const dng_fingerprint &a, 0113 const dng_fingerprint &b) const 0114 { 0115 0116 return memcmp (a.data, 0117 b.data, 0118 sizeof (a.data)) < 0; 0119 0120 } 0121 0122 }; 0123 0124 /******************************************************************************/ 0125 0126 /// \brief Utility to hash fingerprints (e.g., for hashtables). 0127 0128 struct dng_fingerprint_hash 0129 { 0130 0131 /// Hash function. 0132 0133 size_t operator () (const dng_fingerprint &digest) const 0134 { 0135 0136 return (size_t) digest.Collapse32 (); 0137 0138 } 0139 0140 }; 0141 0142 /******************************************************************************/ 0143 0144 // Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. 0145 0146 // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 0147 // rights reserved. 0148 // 0149 // License to copy and use this software is granted provided that it 0150 // is identified as the "RSA Data Security, Inc. MD5 Message-Digest 0151 // Algorithm" in all material mentioning or referencing this software 0152 // or this function. 0153 // 0154 // License is also granted to make and use derivative works provided 0155 // that such works are identified as "derived from the RSA Data 0156 // Security, Inc. MD5 Message-Digest Algorithm" in all material 0157 // mentioning or referencing the derived work. 0158 // 0159 // RSA Data Security, Inc. makes no representations concerning either 0160 // the merchantability of this software or the suitability of this 0161 // software for any particular purpose. It is provided "as is" 0162 // without express or implied warranty of any kind. 0163 // 0164 // These notices must be retained in any copies of any part of this 0165 // documentation and/or software. 0166 0167 /// \brief Class to hash binary data to a fingerprint using the MD5 Message-Digest 0168 /// Algorithm. 0169 0170 class dng_md5_printer 0171 { 0172 0173 public: 0174 0175 dng_md5_printer (); 0176 0177 virtual ~dng_md5_printer () 0178 { 0179 } 0180 0181 /// Reset the fingerprint. 0182 0183 void Reset (); 0184 0185 /// Append the data to the stream to be hashed. 0186 /// \param data The data to be hashed. 0187 /// \param inputLen The length of data, in bytes. 0188 0189 void Process (const void *data, 0190 uint32 inputLen); 0191 0192 /// Append the string to the stream to be hashed. 0193 /// \param text The string to be hashed. 0194 0195 void Process (const char *text) 0196 { 0197 0198 Process (text, (uint32) strlen (text)); 0199 0200 } 0201 0202 /// Get the fingerprint (i.e., result of the hash). 0203 0204 const dng_fingerprint & Result (); 0205 0206 private: 0207 0208 static void Encode (uint8 *output, 0209 const uint32 *input, 0210 uint32 len); 0211 0212 static void Decode (uint32 *output, 0213 const uint8 *input, 0214 uint32 len); 0215 0216 // F, G, H and I are basic MD5 functions. 0217 0218 static inline uint32 F (uint32 x, 0219 uint32 y, 0220 uint32 z) 0221 { 0222 return (x & y) | (~x & z); 0223 } 0224 0225 static inline uint32 G (uint32 x, 0226 uint32 y, 0227 uint32 z) 0228 { 0229 return (x & z) | (y & ~z); 0230 } 0231 0232 static inline uint32 H (uint32 x, 0233 uint32 y, 0234 uint32 z) 0235 { 0236 return x ^ y ^ z; 0237 } 0238 0239 static inline uint32 I (uint32 x, 0240 uint32 y, 0241 uint32 z) 0242 { 0243 return y ^ (x | ~z); 0244 } 0245 0246 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 0247 0248 DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow") 0249 static inline void FF (uint32 &a, 0250 uint32 b, 0251 uint32 c, 0252 uint32 d, 0253 uint32 x, 0254 uint32 s, 0255 uint32 ac) 0256 { 0257 a += F (b, c, d) + x + ac; 0258 a = (a << s) | (a >> (32 - s)); 0259 a += b; 0260 } 0261 0262 DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow") 0263 static inline void GG (uint32 &a, 0264 uint32 b, 0265 uint32 c, 0266 uint32 d, 0267 uint32 x, 0268 uint32 s, 0269 uint32 ac) 0270 { 0271 a += G (b, c, d) + x + ac; 0272 a = (a << s) | (a >> (32 - s)); 0273 a += b; 0274 } 0275 0276 DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow") 0277 static inline void HH (uint32 &a, 0278 uint32 b, 0279 uint32 c, 0280 uint32 d, 0281 uint32 x, 0282 uint32 s, 0283 uint32 ac) 0284 { 0285 a += H (b, c, d) + x + ac; 0286 a = (a << s) | (a >> (32 - s)); 0287 a += b; 0288 } 0289 0290 DNG_ATTRIB_NO_SANITIZE("unsigned-integer-overflow") 0291 static inline void II (uint32 &a, 0292 uint32 b, 0293 uint32 c, 0294 uint32 d, 0295 uint32 x, 0296 uint32 s, 0297 uint32 ac) 0298 { 0299 a += I (b, c, d) + x + ac; 0300 a = (a << s) | (a >> (32 - s)); 0301 a += b; 0302 } 0303 0304 static void MD5Transform (uint32 state [4], 0305 const uint8 block [64]); 0306 0307 private: 0308 0309 uint32 state [4]; 0310 0311 uint32 count [2]; 0312 0313 uint8 buffer [64]; 0314 0315 bool final; 0316 0317 dng_fingerprint result; 0318 0319 }; 0320 0321 /*****************************************************************************/ 0322 0323 /// \brief A dng_stream based interface to the MD5 printing logic. 0324 0325 class dng_md5_printer_stream : public dng_stream, dng_md5_printer 0326 { 0327 0328 private: 0329 0330 uint64 fNextOffset; 0331 0332 public: 0333 0334 /// Create an empty MD5 printer stream. 0335 0336 dng_md5_printer_stream () 0337 0338 : fNextOffset (0) 0339 0340 { 0341 } 0342 0343 virtual uint64 DoGetLength () 0344 { 0345 0346 return fNextOffset; 0347 0348 } 0349 0350 virtual void DoRead (void * /* data */, 0351 uint32 /* count */, 0352 uint64 /* offset */) 0353 { 0354 0355 ThrowProgramError (); 0356 0357 } 0358 0359 virtual void DoSetLength (uint64 length) 0360 { 0361 0362 if (length != fNextOffset) 0363 { 0364 ThrowProgramError (); 0365 } 0366 0367 } 0368 0369 virtual void DoWrite (const void *data, 0370 uint32 count2, 0371 uint64 offset) 0372 { 0373 0374 if (offset != fNextOffset) 0375 { 0376 ThrowProgramError (); 0377 } 0378 0379 Process (data, count2); 0380 0381 fNextOffset += count2; 0382 0383 } 0384 0385 const dng_fingerprint & Result () 0386 { 0387 0388 Flush (); 0389 0390 return dng_md5_printer::Result (); 0391 0392 } 0393 0394 }; 0395 0396 /*****************************************************************************/ 0397 0398 #endif 0399 0400 /*****************************************************************************/