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