1 /*****************************************************************************/ 2 // Copyright 2006-2007 Adobe Systems Incorporated 3 // All Rights Reserved. 4 // 5 // NOTICE: Adobe permits you to use, modify, and distribute this file in 6 // accordance with the terms of the Adobe license agreement accompanying it. 7 /*****************************************************************************/ 8 9 /* $Id: //mondo/dng_sdk_1_4/dng_sdk/source/dng_fingerprint.h#2 $ */ 10 /* $DateTime: 2012/07/11 10:36:56 $ */ 11 /* $Change: 838485 $ */ 12 /* $Author: tknoll $ */ 13 14 /** \file 15 * Fingerprint (cryptographic hashing) support for generating strong hashes of image 16 * data. 17 */ 18 19 /*****************************************************************************/ 20 21 #ifndef __dng_fingerprint__ 22 #define __dng_fingerprint__ 23 24 /*****************************************************************************/ 25 26 #include "dng_exceptions.h" 27 #include "dng_types.h" 28 #include "dng_stream.h" 29 30 #include <cstring> 31 32 /*****************************************************************************/ 33 34 /// \brief Container fingerprint (MD5 only at present). 35 36 class dng_fingerprint 37 { 38 39 public: 40 41 static const size_t kDNGFingerprintSize = 16; 42 43 uint8 data [kDNGFingerprintSize]; 44 45 public: 46 47 dng_fingerprint (); 48 49 /// Check if fingerprint is all zeros. 50 51 bool IsNull () const; 52 53 /// Same as IsNull but expresses intention of testing validity. 54 55 bool IsValid () const 56 { 57 return !IsNull (); 58 } 59 60 /// Set to all zeros, a value used to indicate an invalid fingerprint. 61 62 void Clear () 63 { 64 *this = dng_fingerprint (); 65 } 66 67 /// Test if two fingerprints are equal. 68 69 bool operator== (const dng_fingerprint &print) const; 70 71 /// Test if two fingerprints are not equal. 72 73 bool operator!= (const dng_fingerprint &print) const 74 { 75 return !(*this == print); 76 } 77 78 /// Produce a 32-bit hash value from fingerprint used for faster hashing of 79 /// fingerprints. 80 81 uint32 Collapse32 () const; 82 83 /// Convert fingerprint to UTF-8 string. 84 /// 85 /// \param resultStr The output array to which the UTF-8 encoding of the 86 /// fingerprint will be written. 87 88 void ToUtf8HexString (char resultStr [2 * kDNGFingerprintSize + 1]) const; 89 90 /// Convert UTF-8 string to fingerprint. Returns true on success, false on 91 /// failure. 92 /// 93 /// \param inputStr The input array from which the UTF-8 encoding of the 94 /// fingerprint will be read. 95 /// 96 /// \retval True indicates success. 97 98 bool FromUtf8HexString (const char inputStr [2 * kDNGFingerprintSize + 1]); 99 100 }; 101 102 /*****************************************************************************/ 103 104 /// \brief Utility to compare fingerprints (e.g., for sorting). 105 106 struct dng_fingerprint_less_than 107 { 108 109 /// Less-than comparison. 110 111 bool operator() (const dng_fingerprint &a, 112 const dng_fingerprint &b) const 113 { 114 115 return memcmp (a.data, 116 b.data, 117 sizeof (a.data)) < 0; 118 119 } 120 121 }; 122 123 /******************************************************************************/ 124 125 // Derived from the RSA Data Security, Inc. MD5 Message-Digest Algorithm. 126 127 // Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All 128 // rights reserved. 129 // 130 // License to copy and use this software is granted provided that it 131 // is identified as the "RSA Data Security, Inc. MD5 Message-Digest 132 // Algorithm" in all material mentioning or referencing this software 133 // or this function. 134 // 135 // License is also granted to make and use derivative works provided 136 // that such works are identified as "derived from the RSA Data 137 // Security, Inc. MD5 Message-Digest Algorithm" in all material 138 // mentioning or referencing the derived work. 139 // 140 // RSA Data Security, Inc. makes no representations concerning either 141 // the merchantability of this software or the suitability of this 142 // software for any particular purpose. It is provided "as is" 143 // without express or implied warranty of any kind. 144 // 145 // These notices must be retained in any copies of any part of this 146 // documentation and/or software. 147 148 /// \brief Class to hash binary data to a fingerprint using the MD5 Message-Digest 149 /// Algorithm. 150 151 class dng_md5_printer 152 { 153 154 public: 155 156 dng_md5_printer (); 157 158 virtual ~dng_md5_printer () 159 { 160 } 161 162 /// Reset the fingerprint. 163 164 void Reset (); 165 166 /// Append the data to the stream to be hashed. 167 /// \param data The data to be hashed. 168 /// \param inputLen The length of data, in bytes. 169 170 void Process (const void *data, 171 uint32 inputLen); 172 173 /// Append the string to the stream to be hashed. 174 /// \param text The string to be hashed. 175 176 void Process (const char *text) 177 { 178 179 Process (text, (uint32) strlen (text)); 180 181 } 182 183 /// Get the fingerprint (i.e., result of the hash). 184 185 const dng_fingerprint & Result (); 186 187 private: 188 189 static void Encode (uint8 *output, 190 const uint32 *input, 191 uint32 len); 192 193 static void Decode (uint32 *output, 194 const uint8 *input, 195 uint32 len); 196 197 // F, G, H and I are basic MD5 functions. 198 199 static inline uint32 F (uint32 x, 200 uint32 y, 201 uint32 z) 202 { 203 return (x & y) | (~x & z); 204 } 205 206 static inline uint32 G (uint32 x, 207 uint32 y, 208 uint32 z) 209 { 210 return (x & z) | (y & ~z); 211 } 212 213 static inline uint32 H (uint32 x, 214 uint32 y, 215 uint32 z) 216 { 217 return x ^ y ^ z; 218 } 219 220 static inline uint32 I (uint32 x, 221 uint32 y, 222 uint32 z) 223 { 224 return y ^ (x | ~z); 225 } 226 227 // FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. 228 229 #if defined(__clang__) && defined(__has_attribute) 230 #if __has_attribute(no_sanitize) 231 __attribute__((no_sanitize("unsigned-integer-overflow"))) 232 #endif 233 #endif 234 static inline void FF (uint32 &a, 235 uint32 b, 236 uint32 c, 237 uint32 d, 238 uint32 x, 239 uint32 s, 240 uint32 ac) 241 { 242 a += F (b, c, d) + x + ac; 243 a = (a << s) | (a >> (32 - s)); 244 a += b; 245 } 246 247 #if defined(__clang__) && defined(__has_attribute) 248 #if __has_attribute(no_sanitize) 249 __attribute__((no_sanitize("unsigned-integer-overflow"))) 250 #endif 251 #endif 252 static inline void GG (uint32 &a, 253 uint32 b, 254 uint32 c, 255 uint32 d, 256 uint32 x, 257 uint32 s, 258 uint32 ac) 259 { 260 a += G (b, c, d) + x + ac; 261 a = (a << s) | (a >> (32 - s)); 262 a += b; 263 } 264 265 #if defined(__clang__) && defined(__has_attribute) 266 #if __has_attribute(no_sanitize) 267 __attribute__((no_sanitize("unsigned-integer-overflow"))) 268 #endif 269 #endif 270 static inline void HH (uint32 &a, 271 uint32 b, 272 uint32 c, 273 uint32 d, 274 uint32 x, 275 uint32 s, 276 uint32 ac) 277 { 278 a += H (b, c, d) + x + ac; 279 a = (a << s) | (a >> (32 - s)); 280 a += b; 281 } 282 283 #if defined(__clang__) && defined(__has_attribute) 284 #if __has_attribute(no_sanitize) 285 __attribute__((no_sanitize("unsigned-integer-overflow"))) 286 #endif 287 #endif 288 static inline void II (uint32 &a, 289 uint32 b, 290 uint32 c, 291 uint32 d, 292 uint32 x, 293 uint32 s, 294 uint32 ac) 295 { 296 a += I (b, c, d) + x + ac; 297 a = (a << s) | (a >> (32 - s)); 298 a += b; 299 } 300 301 static void MD5Transform (uint32 state [4], 302 const uint8 block [64]); 303 304 private: 305 306 uint32 state [4]; 307 308 uint32 count [2]; 309 310 uint8 buffer [64]; 311 312 bool final; 313 314 dng_fingerprint result; 315 316 }; 317 318 /*****************************************************************************/ 319 320 /// \brief A dng_stream based interface to the MD5 printing logic. 321 322 class dng_md5_printer_stream : public dng_stream, dng_md5_printer 323 { 324 325 private: 326 327 uint64 fNextOffset; 328 329 public: 330 331 /// Create an empty MD5 printer stream. 332 333 dng_md5_printer_stream () 334 335 : fNextOffset (0) 336 337 { 338 } 339 340 virtual uint64 DoGetLength () 341 { 342 343 return fNextOffset; 344 345 } 346 347 virtual void DoRead (void * /* data */, 348 uint32 /* count */, 349 uint64 /* offset */) 350 { 351 352 ThrowProgramError (); 353 354 } 355 356 virtual void DoSetLength (uint64 length) 357 { 358 359 if (length != fNextOffset) 360 { 361 ThrowProgramError (); 362 } 363 364 } 365 366 virtual void DoWrite (const void *data, 367 uint32 count2, 368 uint64 offset) 369 { 370 371 if (offset != fNextOffset) 372 { 373 ThrowProgramError (); 374 } 375 376 Process (data, count2); 377 378 fNextOffset += count2; 379 380 } 381 382 const dng_fingerprint & Result () 383 { 384 385 Flush (); 386 387 return dng_md5_printer::Result (); 388 389 } 390 391 }; 392 393 /*****************************************************************************/ 394 395 #endif 396 397 /*****************************************************************************/ 398