CernVM-FS  2.10.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 <arpa/inet.h>
16 #include <stdint.h>
17 
18 #include <cassert>
19 #include <cctype>
20 #include <cstdlib>
21 #include <cstring>
22 #include <string>
23 
24 #include "logging.h"
25 #include "prng.h"
26 #include "smalloc.h"
27 
28 #ifdef CVMFS_NAMESPACE_GUARD
29 namespace CVMFS_NAMESPACE_GUARD {
30 #endif
31 
32 namespace shash {
33 
40 enum Algorithms {
41  kMd5 = 0,
44  kShake128, // with 160 output bits
46 };
47 
52 const char kSuffixNone = 0;
53 const char kSuffixCatalog = 'C';
54 const char kSuffixHistory = 'H';
55 const char kSuffixMicroCatalog = 'L'; // currently unused
56 const char kSuffixPartial = 'P';
57 const char kSuffixTemporary = 'T';
58 const char kSuffixCertificate = 'X';
59 const char kSuffixMetainfo = 'M';
60 
61 
68 const unsigned kDigestSizes[] =
69  {16, 20, 20, 20, 20};
70 // Md5 Sha1 Rmd160 Shake128 Any
71 const unsigned kMaxDigestSize = 20;
72 
76 const unsigned kMaxContextSize = 256;
77 
84 extern const char *kAlgorithmIds[];
85 const unsigned kAlgorithmIdSizes[] =
86  {0, 0, 7, 9, 0};
87 // Md5 Sha1 -rmd160 -shake128 Any
88 const unsigned kMaxAlgorithmIdentifierSize = 9;
89 
94 const unsigned kBlockSizes[] =
95  {64, 64, 64, 168};
96 // Md5 Sha1 Rmd160 Shake128
97 
102 struct HexPtr {
103  const std::string *str;
104  explicit HexPtr(const std::string &s) { str = &s; }
105  bool IsValid() const;
106 };
107 
108 struct AsciiPtr {
109  const std::string *str;
110  explicit AsciiPtr(const std::string &s) { str = &s; }
111 };
112 
113 typedef char Suffix;
114 
121 template<unsigned digest_size_, Algorithms algorithm_>
122 struct Digest {
123  unsigned char digest[digest_size_];
126 
127  class Hex {
128  public:
130  digest_(*digest),
131  hash_length_(2 * kDigestSizes[digest_.algorithm]),
132  algo_id_length_(kAlgorithmIdSizes[digest_.algorithm]) {}
133 
134  unsigned int length() const { return hash_length_ + algo_id_length_; }
135 
136  char operator[](const unsigned int position) const {
137  assert(position < length());
138  return (position < hash_length_)
139  ? GetHashChar(position)
140  : GetAlgorithmIdentifierChar(position);
141  }
142 
143  protected:
144  char GetHashChar(const unsigned int position) const {
145  assert(position < hash_length_);
146  const char digit = (position % 2 == 0)
147  ? digest_.digest[position / 2] / 16
148  : digest_.digest[position / 2] % 16;
149  return ToHex(digit);
150  }
151 
152  char GetAlgorithmIdentifierChar(const unsigned int position) const {
153  assert(position >= hash_length_);
154  return kAlgorithmIds[digest_.algorithm][position - hash_length_];
155  }
156 
157  char ToHex(const char c) const {
158  return static_cast<char>(c + ((c <= 9) ? '0' : 'a' - 10));
159  }
160 
161  private:
163  const unsigned int hash_length_;
164  const unsigned int algo_id_length_;
165  };
166 
167  unsigned GetDigestSize() const { return kDigestSizes[algorithm]; }
168  unsigned GetHexSize() const {
170  }
171 
172  Digest() :
173  algorithm(algorithm_), suffix(kSuffixNone)
174  {
175  SetNull();
176  }
177 
178  explicit Digest(const Algorithms a, const HexPtr hex, const char s = 0) :
179  algorithm(a), suffix(s)
180  {
181  assert((algorithm_ == kAny) || (a == algorithm_));
182  const unsigned char_size = 2*kDigestSizes[a];
183 
184  const std::string *str = hex.str;
185  const unsigned length = str->length();
186  assert(length >= char_size); // A suffix won't hurt
187 
188  for (unsigned i = 0; i < char_size; i += 2) {
189  this->digest[i/2] =
190  ((*str)[i] <= '9' ? (*str)[i] -'0' : (*str)[i] - 'a' + 10)*16 +
191  ((*str)[i+1] <= '9' ? (*str)[i+1] - '0' : (*str)[i+1] - 'a' + 10);
192  }
193  }
194 
196  const unsigned char *digest_buffer,
197  const Suffix s = kSuffixNone) :
198  algorithm(a), suffix(s)
199  {
200  memcpy(digest, digest_buffer, kDigestSizes[a]);
201  }
202 
207  void Randomize() {
208  Prng prng;
209  prng.InitLocaltime();
210  Randomize(&prng);
211  }
212 
219  void Randomize(const uint64_t seed) {
220  Prng prng;
221  prng.InitSeed(seed);
222  Randomize(&prng);
223  }
224 
231  void Randomize(Prng *prng) {
232  const unsigned bytes = GetDigestSize();
233  for (unsigned i = 0; i < bytes; ++i) {
234  digest[i] = prng->Next(256);
235  }
236  }
237 
238  bool HasSuffix() const { return suffix != kSuffixNone; }
239  void set_suffix(const Suffix s) { suffix = s; }
240 
248  std::string ToString(const bool with_suffix = false) const {
249  Hex hex(this);
250  const bool use_suffix = with_suffix && HasSuffix();
251  const unsigned string_length = hex.length() + use_suffix;
252  std::string result(string_length, 0);
253 
254  for (unsigned int i = 0; i < hex.length(); ++i) {
255  result[i] = hex[i];
256  }
257 
258  if (use_suffix) {
259  result[string_length - 1] = suffix;
260  }
261 
262  assert(result.length() == string_length);
263  return result;
264  }
265 
274  std::string ToFingerprint(const bool with_suffix = false) const {
275  Hex hex(this);
276  const bool use_suffix = with_suffix && HasSuffix();
277  const unsigned string_length =
278  hex.length() + kDigestSizes[algorithm] - 1 + use_suffix;
279  std::string result(string_length, 0);
280 
281  unsigned l = hex.length();
282  for (unsigned int hex_i = 0, result_i = 0; hex_i < l; ++hex_i, ++result_i) {
283  result[result_i] = toupper(hex[hex_i]);
284  if ((hex_i < 2 * kDigestSizes[algorithm] - 1) && (hex_i % 2 == 1)) {
285  result[++result_i] = ':';
286  }
287  }
288 
289  if (use_suffix) {
290  result[string_length - 1] = suffix;
291  }
292 
293  assert(result.length() == string_length);
294  return result;
295  }
296 
303  std::string ToStringWithSuffix() const {
304  return ToString(true);
305  }
306 
315  std::string MakePath() const {
316  return MakePathExplicit(1, 2, suffix);
317  }
318 
324  std::string MakeAlternativePath() const {
325  return ".cvmfsalt-" + ToStringWithSuffix();
326  }
327 
334  std::string MakePathWithoutSuffix() const {
335  return MakePathExplicit(1, 2, kSuffixNone);
336  }
337 
350  std::string MakePathExplicit(const unsigned dir_levels,
351  const unsigned digits_per_level,
352  const Suffix hash_suffix = kSuffixNone) const {
353  Hex hex(this);
354 
355  // figure out how big the output string needs to be
356  const bool use_suffix = (hash_suffix != kSuffixNone);
357  const unsigned string_length = hex.length() + dir_levels + use_suffix;
358  std::string result;
359  result.resize(string_length);
360 
361  // build hexified hash and path delimiters
362  unsigned i = 0;
363  unsigned pos = 0;
364  for (; i < hex.length(); ++i) {
365  if (i > 0 && (i % digits_per_level == 0)
366  && (i / digits_per_level <= dir_levels)) {
367  result[pos++] = '/';
368  }
369  result[pos++] = hex[i];
370  }
371 
372  // (optionally) add hash hint suffix
373  if (use_suffix) {
374  result[pos++] = hash_suffix;
375  }
376 
377  assert(i == hex.length());
378  assert(pos == string_length);
379  return result;
380  }
381 
382  bool IsNull() const {
383  for (unsigned i = 0; i < kDigestSizes[algorithm]; ++i) {
384  if (digest[i] != 0)
385  return false;
386  }
387  return true;
388  }
389 
393  uint32_t Partial32() const {
394  const uint32_t *partial = (const uint32_t *)digest;
395  return ntohl(*partial);
396  }
397 
398 
399  void SetNull() {
400  memset(digest, 0, digest_size_);
401  }
402 
403 
405  if (this->algorithm != other.algorithm)
406  return false;
407  for (unsigned i = 0; i < kDigestSizes[algorithm]; ++i) {
408  if (this->digest[i] != other.digest[i])
409  return false;
410  }
411  return true;
412  }
413 
415  return !(*this == other);
416  }
417 
418  bool operator <(const Digest<digest_size_, algorithm_> &other) const {
419  if (this->algorithm != other.algorithm)
420  return (this->algorithm < other.algorithm);
421  for (unsigned i = 0; i < kDigestSizes[algorithm]; ++i) {
422  if (this->digest[i] > other.digest[i])
423  return false;
424  if (this->digest[i] < other.digest[i])
425  return true;
426  }
427  return false;
428  }
429 
430  bool operator >(const Digest<digest_size_, algorithm_> &other) const {
431  if (this->algorithm != other.algorithm)
432  return (this->algorithm > other.algorithm);
433  for (unsigned i = 0; i < kDigestSizes[algorithm]; ++i) {
434  if (this->digest[i] < other.digest[i])
435  return false;
436  if (this->digest[i] > other.digest[i])
437  return true;
438  }
439  return false;
440  }
441 };
442 
443 
444 struct Md5 : public Digest<16, kMd5> {
445  Md5() : Digest<16, kMd5>() { }
446  explicit Md5(const AsciiPtr ascii);
447  explicit Md5(const HexPtr hex) : Digest<16, kMd5>(kMd5, hex) { }
448  Md5(const char *chars, const unsigned length);
449 
453  Md5(const uint64_t lo, const uint64_t hi);
454  void ToIntPair(uint64_t *lo, uint64_t *hi) const;
455 };
456 
457 struct Sha1 : public Digest<20, kSha1> { };
458 struct Rmd160 : public Digest<20, kRmd160> { };
459 struct Shake128 : public Digest<20, kShake128> { };
460 
466 struct Any : public Digest<kMaxDigestSize, kAny> {
468 
469  explicit Any(const Algorithms a,
470  const char s = kSuffixNone) :
471  Digest<kMaxDigestSize, kAny>() { algorithm = a; suffix = s; }
472 
473  Any(const Algorithms a,
474  const unsigned char *digest_buffer,
475  const Suffix suffix = kSuffixNone) :
476  Digest<kMaxDigestSize, kAny>(a, digest_buffer, suffix) { }
477 
478  explicit Any(const Algorithms a,
479  const HexPtr hex,
480  const char suffix = kSuffixNone) :
481  Digest<kMaxDigestSize, kAny>(a, hex, suffix) { }
482 
483  Md5 CastToMd5();
484 };
485 
486 
491 unsigned GetContextSize(const Algorithms algorithm);
492 
497 class ContextPtr {
498  public:
500  void *buffer;
501  unsigned size;
502 
503  ContextPtr() : algorithm(kAny), buffer(NULL), size(0) {}
504 
505  explicit ContextPtr(const Algorithms a) :
506  algorithm(a), buffer(NULL), size(GetContextSize(a)) {}
507  ContextPtr(const Algorithms a, void *b) :
508  algorithm(a), buffer(b), size(GetContextSize(a)) {}
509 };
510 
511 void Init(ContextPtr context);
512 void Update(const unsigned char *buffer, const unsigned buffer_size,
513  ContextPtr context);
514 void Final(ContextPtr context, Any *any_digest);
515 bool HashFile(const std::string &filename, Any *any_digest);
516 bool HashFd(int fd, Any *any_digest);
517 void HashMem(const unsigned char *buffer, const unsigned buffer_size,
518  Any *any_digest);
519 void HashString(const std::string &content, Any *any_digest);
520 void Hmac(const std::string &key,
521  const unsigned char *buffer, const unsigned buffer_size,
522  Any *any_digest);
523 inline void HmacString(const std::string &key, const std::string &content,
524  Any *any_digest)
525 {
526  Hmac(key,
527  reinterpret_cast<const unsigned char *>(content.data()),
528  content.size(),
529  any_digest);
530 }
531 
539 std::string Hmac256(const std::string &key, const std::string &content,
540  bool raw_output = false);
541 std::string Sha256File(const std::string &filename);
542 std::string Sha256Mem(const unsigned char *buffer, const unsigned buffer_size);
543 std::string Sha256String(const std::string &content);
544 
545 Algorithms ParseHashAlgorithm(const std::string &algorithm_option);
546 Any MkFromHexPtr(const HexPtr hex, const Suffix suffix = kSuffixNone);
547 Any MkFromSuffixedHexPtr(const HexPtr hex);
548 
549 } // namespace shash
550 
551 #ifdef CVMFS_NAMESPACE_GUARD
552 } // namespace CVMFS_NAMESPACE_GUARD
553 #endif
554 
555 #endif // CVMFS_HASH_H_
Hex(const Digest< digest_size_, algorithm_ > *digest)
Definition: hash.h:129
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:382
const unsigned kMaxContextSize
Definition: hash.h:76
bool HashFd(int fd, Any *any_digest)
Definition: hash.cc:321
Md5()
Definition: hash.h:445
void set_suffix(const Suffix s)
Definition: hash.h:239
const unsigned int hash_length_
Definition: hash.h:163
const std::string * str
Definition: hash.h:103
void Randomize()
Definition: hash.h:207
std::string MakeAlternativePath() const
Definition: hash.h:324
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:248
void Randomize(const uint64_t seed)
Definition: hash.h:219
std::string ToStringWithSuffix() const
Definition: hash.h:303
const unsigned kAlgorithmIdSizes[]
Definition: compat.h:160
char GetAlgorithmIdentifierChar(const unsigned int position) const
Definition: hash.h:152
const unsigned kMaxDigestSize
Definition: compat.h:38
void InitLocaltime()
Definition: prng.h:36
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:238
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:157
Algorithms algorithm
Definition: hash.h:124
Digest(const Algorithms a, const unsigned char *digest_buffer, const Suffix s=kSuffixNone)
Definition: hash.h:195
void InitSeed(const uint64_t seed)
Definition: prng.h:32
unsigned char digest[digest_size_]
Definition: hash.h:123
ContextPtr(const Algorithms a)
Definition: hash.h:505
char algorithm
HexPtr(const std::string &s)
Definition: hash.h:104
Algorithms
Definition: hash.h:40
const Digest< digest_size_, algorithm_ > & digest_
Definition: hash.h:162
const unsigned kBlockSizes[]
Definition: hash.h:94
unsigned GetDigestSize() const
Definition: hash.h:167
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:467
const std::string * str
Definition: hash.h:109
std::string ToFingerprint(const bool with_suffix=false) const
Definition: hash.h:274
void Final(ContextPtr context, Any *any_digest)
Definition: hash.cc:221
const unsigned kMaxAlgorithmIdentifierSize
Definition: compat.h:161
Algorithms algorithm
Definition: hash.h:499
const char kSuffixHistory
Definition: compat.h:165
bool HasSuffix(const std::string &str, const std::string &suffix, const bool ignore_case)
Definition: string.cc:279
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:507
unsigned GetContextSize(const Algorithms algorithm)
Definition: hash.cc:148
char GetHashChar(const unsigned int position) const
Definition: hash.h:144
AsciiPtr(const std::string &s)
Definition: hash.h:110
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:59
void * buffer
Definition: hash.h:500
Any(const Algorithms a, const unsigned char *digest_buffer, const Suffix suffix=kSuffixNone)
Definition: hash.h:473
const char * kAlgorithmIds[]
Definition: hash.cc:33
uint32_t Partial32() const
Definition: hash.h:393
char Suffix
Definition: hash.h:113
void HashMem(const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
Definition: hash.cc:255
std::string MakePathWithoutSuffix() const
Definition: hash.h:334
Any(const Algorithms a, const HexPtr hex, const char suffix=kSuffixNone)
Definition: hash.h:478
bool operator==(const cvmcache_hash &a, const cvmcache_hash &b)
void SetNull()
Definition: hash.h:399
unsigned GetHexSize() const
Definition: hash.h:168
unsigned int length() const
Definition: hash.h:134
std::string MakePathExplicit(const unsigned dir_levels, const unsigned digits_per_level, const Suffix hash_suffix=kSuffixNone) const
Definition: hash.h:350
void HmacString(const std::string &key, const std::string &content, Any *any_digest)
Definition: hash.h:523
Digest(const Algorithms a, const HexPtr hex, const char s=0)
Definition: hash.h:178
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:136
Suffix suffix
Definition: hash.h:125
std::string MakePath() const
Definition: hash.h:315
unsigned size
Definition: hash.h:501
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:231
void HashString(const std::string &content, Any *any_digest)
Definition: hash.cc:268
Md5(const HexPtr hex)
Definition: hash.h:447
const char kSuffixCertificate
Definition: compat.h:169
uint32_t Next(const uint64_t boundary)
Definition: prng.h:46
const unsigned int algo_id_length_
Definition: hash.h:164
Any(const Algorithms a, const char s=kSuffixNone)
Definition: hash.h:469