CernVM-FS  2.9.0
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
hash.h
Go to the documentation of this file.
1 
12 #ifndef CVMFS_HASH_H_
13 #define CVMFS_HASH_H_
14 
15 #include <stdint.h>
16 
17 #include <cassert>
18 #include <cctype>
19 #include <cstdlib>
20 #include <cstring>
21 #include <string>
22 
23 #include "logging.h"
24 #include "prng.h"
25 #include "smalloc.h"
26 
27 #ifdef CVMFS_NAMESPACE_GUARD
28 namespace CVMFS_NAMESPACE_GUARD {
29 #endif
30 
31 namespace shash {
32 
39 enum Algorithms {
40  kMd5 = 0,
43  kShake128, // with 160 output bits
45 };
46 
51 const char kSuffixNone = 0;
52 const char kSuffixCatalog = 'C';
53 const char kSuffixHistory = 'H';
54 const char kSuffixMicroCatalog = 'L'; // currently unused
55 const char kSuffixPartial = 'P';
56 const char kSuffixTemporary = 'T';
57 const char kSuffixCertificate = 'X';
58 const char kSuffixMetainfo = 'M';
59 
60 
67 const unsigned kDigestSizes[] =
68  {16, 20, 20, 20, 20};
69 // Md5 Sha1 Rmd160 Shake128 Any
70 const unsigned kMaxDigestSize = 20;
71 
75 const unsigned kMaxContextSize = 256;
76 
83 extern const char *kAlgorithmIds[];
84 const unsigned kAlgorithmIdSizes[] =
85  {0, 0, 7, 9, 0};
86 // Md5 Sha1 -rmd160 -shake128 Any
87 const unsigned kMaxAlgorithmIdentifierSize = 9;
88 
93 const unsigned kBlockSizes[] =
94  {64, 64, 64, 168};
95 // Md5 Sha1 Rmd160 Shake128
96 
101 struct HexPtr {
102  const std::string *str;
103  explicit HexPtr(const std::string &s) { str = &s; }
104  bool IsValid() const;
105 };
106 
107 struct AsciiPtr {
108  const std::string *str;
109  explicit AsciiPtr(const std::string &s) { str = &s; }
110 };
111 
112 typedef char Suffix;
113 
120 template<unsigned digest_size_, Algorithms algorithm_>
121 struct Digest {
122  unsigned char digest[digest_size_];
125 
126  class Hex {
127  public:
129  digest_(*digest),
130  hash_length_(2 * kDigestSizes[digest_.algorithm]),
131  algo_id_length_(kAlgorithmIdSizes[digest_.algorithm]) {}
132 
133  unsigned int length() const { return hash_length_ + algo_id_length_; }
134 
135  char operator[](const unsigned int position) const {
136  assert(position < length());
137  return (position < hash_length_)
138  ? GetHashChar(position)
139  : GetAlgorithmIdentifierChar(position);
140  }
141 
142  protected:
143  char GetHashChar(const unsigned int position) const {
144  assert(position < hash_length_);
145  const char digit = (position % 2 == 0)
146  ? digest_.digest[position / 2] / 16
147  : digest_.digest[position / 2] % 16;
148  return ToHex(digit);
149  }
150 
151  char GetAlgorithmIdentifierChar(const unsigned int position) const {
152  assert(position >= hash_length_);
153  return kAlgorithmIds[digest_.algorithm][position - hash_length_];
154  }
155 
156  char ToHex(const char c) const { return c + ((c <= 9) ? '0' : 'a' - 10); }
157 
158  private:
160  const unsigned int hash_length_;
161  const unsigned int algo_id_length_;
162  };
163 
164  unsigned GetDigestSize() const { return kDigestSizes[algorithm]; }
165  unsigned GetHexSize() const {
167  }
168 
169  Digest() :
170  algorithm(algorithm_), suffix(kSuffixNone)
171  {
172  SetNull();
173  }
174 
175  explicit Digest(const Algorithms a, const HexPtr hex, const char s = 0) :
176  algorithm(a), suffix(s)
177  {
178  assert((algorithm_ == kAny) || (a == algorithm_));
179  const unsigned char_size = 2*kDigestSizes[a];
180 
181  const std::string *str = hex.str;
182  const unsigned length = str->length();
183  assert(length >= char_size); // A suffix won't hurt
184 
185  for (unsigned i = 0; i < char_size; i += 2) {
186  this->digest[i/2] =
187  ((*str)[i] <= '9' ? (*str)[i] -'0' : (*str)[i] - 'a' + 10)*16 +
188  ((*str)[i+1] <= '9' ? (*str)[i+1] - '0' : (*str)[i+1] - 'a' + 10);
189  }
190  }
191 
193  const unsigned char *digest_buffer,
194  const Suffix s = kSuffixNone) :
195  algorithm(a), suffix(s)
196  {
197  memcpy(digest, digest_buffer, kDigestSizes[a]);
198  }
199 
204  void Randomize() {
205  Prng prng;
206  prng.InitLocaltime();
207  Randomize(&prng);
208  }
209 
216  void Randomize(const uint64_t seed) {
217  Prng prng;
218  prng.InitSeed(seed);
219  Randomize(&prng);
220  }
221 
228  void Randomize(Prng *prng) {
229  const unsigned bytes = GetDigestSize();
230  for (unsigned i = 0; i < bytes; ++i) {
231  digest[i] = prng->Next(256);
232  }
233  }
234 
235  bool HasSuffix() const { return suffix != kSuffixNone; }
236  void set_suffix(const Suffix s) { suffix = s; }
237 
245  std::string ToString(const bool with_suffix = false) const {
246  Hex hex(this);
247  const bool use_suffix = with_suffix && HasSuffix();
248  const unsigned string_length = hex.length() + use_suffix;
249  std::string result(string_length, 0);
250 
251  for (unsigned int i = 0; i < hex.length(); ++i) {
252  result[i] = hex[i];
253  }
254 
255  if (use_suffix) {
256  result[string_length - 1] = suffix;
257  }
258 
259  assert(result.length() == string_length);
260  return result;
261  }
262 
271  std::string ToFingerprint(const bool with_suffix = false) const {
272  Hex hex(this);
273  const bool use_suffix = with_suffix && HasSuffix();
274  const unsigned string_length =
275  hex.length() + kDigestSizes[algorithm] - 1 + use_suffix;
276  std::string result(string_length, 0);
277 
278  unsigned l = hex.length();
279  for (unsigned int hex_i = 0, result_i = 0; hex_i < l; ++hex_i, ++result_i) {
280  result[result_i] = toupper(hex[hex_i]);
281  if ((hex_i < 2 * kDigestSizes[algorithm] - 1) && (hex_i % 2 == 1)) {
282  result[++result_i] = ':';
283  }
284  }
285 
286  if (use_suffix) {
287  result[string_length - 1] = suffix;
288  }
289 
290  assert(result.length() == string_length);
291  return result;
292  }
293 
300  std::string ToStringWithSuffix() const {
301  return ToString(true);
302  }
303 
312  std::string MakePath() const {
313  return MakePathExplicit(1, 2, suffix);
314  }
315 
321  std::string MakeAlternativePath() const {
322  return ".cvmfsalt-" + ToStringWithSuffix();
323  }
324 
331  std::string MakePathWithoutSuffix() const {
332  return MakePathExplicit(1, 2, kSuffixNone);
333  }
334 
347  std::string MakePathExplicit(const unsigned dir_levels,
348  const unsigned digits_per_level,
349  const Suffix hash_suffix = kSuffixNone) const {
350  Hex hex(this);
351 
352  // figure out how big the output string needs to be
353  const bool use_suffix = (hash_suffix != kSuffixNone);
354  const unsigned string_length = hex.length() + dir_levels + use_suffix;
355  std::string result;
356  result.resize(string_length);
357 
358  // build hexified hash and path delimiters
359  unsigned i = 0;
360  unsigned pos = 0;
361  for (; i < hex.length(); ++i) {
362  if (i > 0 && (i % digits_per_level == 0)
363  && (i / digits_per_level <= dir_levels)) {
364  result[pos++] = '/';
365  }
366  result[pos++] = hex[i];
367  }
368 
369  // (optionally) add hash hint suffix
370  if (use_suffix) {
371  result[pos++] = hash_suffix;
372  }
373 
374  assert(i == hex.length());
375  assert(pos == string_length);
376  return result;
377  }
378 
379  bool IsNull() const {
380  for (unsigned i = 0; i < kDigestSizes[algorithm]; ++i)
381  if (digest[i] != 0)
382  return false;
383  return true;
384  }
385 
386 
387  void SetNull() {
388  memset(digest, 0, digest_size_);
389  }
390 
391 
393  if (this->algorithm != other.algorithm)
394  return false;
395  for (unsigned i = 0; i < kDigestSizes[algorithm]; ++i)
396  if (this->digest[i] != other.digest[i])
397  return false;
398  return true;
399  }
400 
402  return !(*this == other);
403  }
404 
405  bool operator <(const Digest<digest_size_, algorithm_> &other) const {
406  if (this->algorithm != other.algorithm)
407  return (this->algorithm < other.algorithm);
408  for (unsigned i = 0; i < kDigestSizes[algorithm]; ++i) {
409  if (this->digest[i] > other.digest[i])
410  return false;
411  if (this->digest[i] < other.digest[i])
412  return true;
413  }
414  return false;
415  }
416 
417  bool operator >(const Digest<digest_size_, algorithm_> &other) const {
418  if (this->algorithm != other.algorithm)
419  return (this->algorithm > other.algorithm);
420  for (unsigned i = 0; i < kDigestSizes[algorithm]; ++i) {
421  if (this->digest[i] < other.digest[i])
422  return false;
423  if (this->digest[i] > other.digest[i])
424  return true;
425  }
426  return false;
427  }
428 };
429 
430 
431 struct Md5 : public Digest<16, kMd5> {
432  Md5() : Digest<16, kMd5>() { }
433  explicit Md5(const AsciiPtr ascii);
434  explicit Md5(const HexPtr hex) : Digest<16, kMd5>(kMd5, hex) { }
435  Md5(const char *chars, const unsigned length);
436 
440  Md5(const uint64_t lo, const uint64_t hi);
441  void ToIntPair(uint64_t *lo, uint64_t *hi) const;
442 };
443 
444 struct Sha1 : public Digest<20, kSha1> { };
445 struct Rmd160 : public Digest<20, kRmd160> { };
446 struct Shake128 : public Digest<20, kShake128> { };
447 
453 struct Any : public Digest<kMaxDigestSize, kAny> {
455 
456  explicit Any(const Algorithms a,
457  const char s = kSuffixNone) :
458  Digest<kMaxDigestSize, kAny>() { algorithm = a; suffix = s; }
459 
460  Any(const Algorithms a,
461  const unsigned char *digest_buffer,
462  const Suffix suffix = kSuffixNone) :
463  Digest<kMaxDigestSize, kAny>(a, digest_buffer, suffix) { }
464 
465  explicit Any(const Algorithms a,
466  const HexPtr hex,
467  const char suffix = kSuffixNone) :
468  Digest<kMaxDigestSize, kAny>(a, hex, suffix) { }
469 
470  Md5 CastToMd5();
471 };
472 
473 
478 unsigned GetContextSize(const Algorithms algorithm);
479 
484 class ContextPtr {
485  public:
487  void *buffer;
488  unsigned size;
489 
490  ContextPtr() : algorithm(kAny), buffer(NULL), size(0) {}
491 
492  explicit ContextPtr(const Algorithms a) :
493  algorithm(a), buffer(NULL), size(GetContextSize(a)) {}
494  ContextPtr(const Algorithms a, void *b) :
495  algorithm(a), buffer(b), size(GetContextSize(a)) {}
496 };
497 
498 void Init(ContextPtr context);
499 void Update(const unsigned char *buffer, const unsigned buffer_size,
500  ContextPtr context);
501 void Final(ContextPtr context, Any *any_digest);
502 bool HashFile(const std::string &filename, Any *any_digest);
503 bool HashFd(int fd, Any *any_digest);
504 void HashMem(const unsigned char *buffer, const unsigned buffer_size,
505  Any *any_digest);
506 void HashString(const std::string &content, Any *any_digest);
507 void Hmac(const std::string &key,
508  const unsigned char *buffer, const unsigned buffer_size,
509  Any *any_digest);
510 inline void HmacString(const std::string &key, const std::string &content,
511  Any *any_digest)
512 {
513  Hmac(key,
514  reinterpret_cast<const unsigned char *>(content.data()),
515  content.size(),
516  any_digest);
517 }
518 
526 std::string Hmac256(const std::string &key, const std::string &content,
527  bool raw_output = false);
528 std::string Sha256File(const std::string &filename);
529 std::string Sha256Mem(const unsigned char *buffer, const unsigned buffer_size);
530 std::string Sha256String(const std::string &content);
531 
532 Algorithms ParseHashAlgorithm(const std::string &algorithm_option);
533 Any MkFromHexPtr(const HexPtr hex, const Suffix suffix = kSuffixNone);
534 Any MkFromSuffixedHexPtr(const HexPtr hex);
535 
536 } // namespace shash
537 
538 #ifdef CVMFS_NAMESPACE_GUARD
539 } // namespace CVMFS_NAMESPACE_GUARD
540 #endif
541 
542 #endif // CVMFS_HASH_H_
Hex(const Digest< digest_size_, algorithm_ > *digest)
Definition: hash.h:128
bool HashFile(const std::string &filename, Any *any_digest)
Definition: hash.cc:342
Definition: prng.h:25
const char kSuffixNone
Definition: compat.h:163
bool IsNull() const
Definition: hash.h:379
const unsigned kMaxContextSize
Definition: hash.h:75
bool HashFd(int fd, Any *any_digest)
Definition: hash.cc:321
Md5()
Definition: hash.h:432
void set_suffix(const Suffix s)
Definition: hash.h:236
const unsigned int hash_length_
Definition: hash.h:160
const std::string * str
Definition: hash.h:102
void Randomize()
Definition: hash.h:204
std::string MakeAlternativePath() const
Definition: hash.h:321
string Sha256String(const string &content)
Definition: hash.cc:452
string Sha256Mem(const unsigned char *buffer, const unsigned buffer_size)
Definition: hash.cc:442
std::string ToString(const bool with_suffix=false) const
Definition: hash.h:245
void Randomize(const uint64_t seed)
Definition: hash.h:216
std::string ToStringWithSuffix() const
Definition: hash.h:300
const unsigned kAlgorithmIdSizes[]
Definition: compat.h:160
char GetAlgorithmIdentifierChar(const unsigned int position) const
Definition: hash.h:151
const unsigned kMaxDigestSize
Definition: compat.h:38
void InitLocaltime()
Definition: prng.h:35
void Hmac(const string &key, const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
Definition: hash.cc:274
bool HasSuffix() const
Definition: hash.h:235
std::string Hmac256(const std::string &key, const std::string &content, bool raw_output)
Definition: hash.cc:458
Any MkFromSuffixedHexPtr(const HexPtr hex)
Definition: hash.cc:105
assert((mem||(size==0))&&"Out Of Memory")
string Sha256File(const string &filename)
Definition: hash.cc:412
char ToHex(const char c) const
Definition: hash.h:156
Algorithms algorithm
Definition: hash.h:123
Digest(const Algorithms a, const unsigned char *digest_buffer, const Suffix s=kSuffixNone)
Definition: hash.h:192
void InitSeed(const uint64_t seed)
Definition: prng.h:31
unsigned char digest[digest_size_]
Definition: hash.h:122
ContextPtr(const Algorithms a)
Definition: hash.h:492
char algorithm
HexPtr(const std::string &s)
Definition: hash.h:103
Algorithms
Definition: hash.h:39
const Digest< digest_size_, algorithm_ > & digest_
Definition: hash.h:159
const unsigned kBlockSizes[]
Definition: hash.h:93
unsigned GetDigestSize() const
Definition: hash.h:164
const unsigned kDigestSizes[]
Definition: compat.h:37
void Update(const unsigned char *buffer, const unsigned buffer_length, ContextPtr context)
Definition: hash.cc:190
Any()
Definition: hash.h:454
const std::string * str
Definition: hash.h:108
std::string ToFingerprint(const bool with_suffix=false) const
Definition: hash.h:271
void Final(ContextPtr context, Any *any_digest)
Definition: hash.cc:221
const unsigned kMaxAlgorithmIdentifierSize
Definition: compat.h:161
Algorithms algorithm
Definition: hash.h:486
const char kSuffixHistory
Definition: compat.h:165
bool HasSuffix(const std::string &str, const std::string &suffix, const bool ignore_case)
Definition: string.cc:278
Any MkFromHexPtr(const HexPtr hex, const char suffix)
Definition: hash.cc:83
bool operator!=(const cvmcache_hash &a, const cvmcache_hash &b)
ContextPtr(const Algorithms a, void *b)
Definition: hash.h:494
unsigned GetContextSize(const Algorithms algorithm)
Definition: hash.cc:148
char GetHashChar(const unsigned int position) const
Definition: hash.h:143
AsciiPtr(const std::string &s)
Definition: hash.h:109
unsigned char digest[20]
static int Init(const loader::LoaderExports *loader_exports)
Definition: cvmfs.cc:1755
const char kSuffixMicroCatalog
Definition: compat.h:166
const char kSuffixMetainfo
Definition: hash.h:58
void * buffer
Definition: hash.h:487
Any(const Algorithms a, const unsigned char *digest_buffer, const Suffix suffix=kSuffixNone)
Definition: hash.h:460
const char * kAlgorithmIds[]
Definition: hash.cc:33
char Suffix
Definition: hash.h:112
void HashMem(const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
Definition: hash.cc:255
std::string MakePathWithoutSuffix() const
Definition: hash.h:331
Any(const Algorithms a, const HexPtr hex, const char suffix=kSuffixNone)
Definition: hash.h:465
bool operator==(const cvmcache_hash &a, const cvmcache_hash &b)
void SetNull()
Definition: hash.h:387
unsigned GetHexSize() const
Definition: hash.h:165
unsigned int length() const
Definition: hash.h:133
std::string MakePathExplicit(const unsigned dir_levels, const unsigned digits_per_level, const Suffix hash_suffix=kSuffixNone) const
Definition: hash.h:347
void HmacString(const std::string &key, const std::string &content, Any *any_digest)
Definition: hash.h:510
Digest(const Algorithms a, const HexPtr hex, const char s=0)
Definition: hash.h:175
Algorithms ParseHashAlgorithm(const string &algorithm_option)
Definition: hash.cc:72
const char kSuffixPartial
Definition: compat.h:167
char operator[](const unsigned int position) const
Definition: hash.h:135
Suffix suffix
Definition: hash.h:124
std::string MakePath() const
Definition: hash.h:312
unsigned size
Definition: hash.h:488
const char kSuffixCatalog
Definition: compat.h:164
static void size_t size
Definition: smalloc.h:47
const char kSuffixTemporary
Definition: compat.h:168
void Randomize(Prng *prng)
Definition: hash.h:228
void HashString(const std::string &content, Any *any_digest)
Definition: hash.cc:268
Md5(const HexPtr hex)
Definition: hash.h:434
const char kSuffixCertificate
Definition: compat.h:169
uint32_t Next(const uint64_t boundary)
Definition: prng.h:45
const unsigned int algo_id_length_
Definition: hash.h:161
Any(const Algorithms a, const char s=kSuffixNone)
Definition: hash.h:456