CernVM-FS  2.13.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[] = {16, 20, 20, 20, 20};
70 // Md5 Sha1 Rmd160 Shake128 Any
71 const unsigned kMaxDigestSize = 20;
72 
76 const unsigned kMaxContextSize = 256;
77 
84 CVMFS_EXPORT extern const char *kAlgorithmIds[];
85 const unsigned kAlgorithmIdSizes[] = {0, 0, 7, 9, 0};
86 // Md5 Sha1 -rmd160 -shake128 Any
87 const unsigned kMaxAlgorithmIdentifierSize = 9;
88 
93 const unsigned kBlockSizes[] = {64, 64, 64, 168};
94 // Md5 Sha1 Rmd160 Shake128
95 
101  const std::string *str;
102  explicit HexPtr(const std::string &s) { str = &s; }
103  bool IsValid() const;
104 };
105 
107  const std::string *str;
108  explicit AsciiPtr(const std::string &s) { str = &s; }
109 };
110 
111 typedef char Suffix;
112 
119 template<unsigned digest_size_, Algorithms algorithm_>
121  unsigned char digest[digest_size_];
124 
125  class Hex {
126  public:
128  : digest_(*digest)
129  , hash_length_(2 * kDigestSizes[digest_.algorithm])
130  , algo_id_length_(kAlgorithmIdSizes[digest_.algorithm]) { }
131 
132  unsigned int length() const { return hash_length_ + algo_id_length_; }
133 
134  char operator[](const unsigned int position) const {
135  assert(position < length());
136  return (position < hash_length_) ? GetHashChar(position)
137  : GetAlgorithmIdentifierChar(position);
138  }
139 
140  protected:
141  char GetHashChar(const unsigned int position) const {
142  assert(position < hash_length_);
143  const char digit = (position % 2 == 0)
144  ? digest_.digest[position / 2] / 16
145  : digest_.digest[position / 2] % 16;
146  return ToHex(digit);
147  }
148 
149  char GetAlgorithmIdentifierChar(const unsigned int position) const {
150  assert(position >= hash_length_);
151  return kAlgorithmIds[digest_.algorithm][position - hash_length_];
152  }
153 
154  char ToHex(const char c) const {
155  return static_cast<char>(c + ((c <= 9) ? '0' : 'a' - 10));
156  }
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() : algorithm(algorithm_), suffix(kSuffixNone) { SetNull(); }
170 
171  explicit Digest(const Algorithms a, const HexPtr hex, const char s = 0)
172  : algorithm(a), suffix(s) {
173  assert((algorithm_ == kAny) || (a == algorithm_));
174  const unsigned char_size = 2 * kDigestSizes[a];
175 
176  const std::string *str = hex.str;
177  const unsigned length = str->length();
178  assert(length >= char_size); // A suffix won't hurt
179 
180  for (unsigned i = 0; i < char_size; i += 2) {
181  this->digest[i / 2] = ((*str)[i] <= '9' ? (*str)[i] - '0'
182  : (*str)[i] - 'a' + 10)
183  * 16
184  + ((*str)[i + 1] <= '9' ? (*str)[i + 1] - '0'
185  : (*str)[i + 1] - 'a' + 10);
186  }
187  }
188 
190  const unsigned char *digest_buffer,
191  const Suffix s = kSuffixNone)
192  : algorithm(a), suffix(s) {
193  memcpy(digest, digest_buffer, kDigestSizes[a]);
194  }
195 
200  void Randomize() {
201  Prng prng;
202  prng.InitLocaltime();
203  Randomize(&prng);
204  }
205 
212  void Randomize(const uint64_t seed) {
213  Prng prng;
214  prng.InitSeed(seed);
215  Randomize(&prng);
216  }
217 
224  void Randomize(Prng *prng) {
225  const unsigned bytes = GetDigestSize();
226  for (unsigned i = 0; i < bytes; ++i) {
227  digest[i] = prng->Next(256);
228  }
229  }
230 
231  bool HasSuffix() const { return suffix != kSuffixNone; }
232  void set_suffix(const Suffix s) { suffix = s; }
233 
241  std::string ToString(const bool with_suffix = false) const {
242  Hex hex(this);
243  const bool use_suffix = with_suffix && HasSuffix();
244  const unsigned string_length = hex.length() + use_suffix;
245  std::string result(string_length, 0);
246 
247  for (unsigned int i = 0; i < hex.length(); ++i) {
248  result[i] = hex[i];
249  }
250 
251  if (use_suffix) {
252  result[string_length - 1] = suffix;
253  }
254 
255  assert(result.length() == string_length);
256  return result;
257  }
258 
267  std::string ToFingerprint(const bool with_suffix = false) const {
268  Hex hex(this);
269  const bool use_suffix = with_suffix && HasSuffix();
270  const unsigned string_length = hex.length() + kDigestSizes[algorithm] - 1
271  + use_suffix;
272  std::string result(string_length, 0);
273 
274  unsigned l = hex.length();
275  for (unsigned int hex_i = 0, result_i = 0; hex_i < l; ++hex_i, ++result_i) {
276  result[result_i] = toupper(hex[hex_i]);
277  if ((hex_i < 2 * kDigestSizes[algorithm] - 1) && (hex_i % 2 == 1)) {
278  result[++result_i] = ':';
279  }
280  }
281 
282  if (use_suffix) {
283  result[string_length - 1] = suffix;
284  }
285 
286  assert(result.length() == string_length);
287  return result;
288  }
289 
296  std::string ToStringWithSuffix() const { return ToString(true); }
297 
306  std::string MakePath() const { return MakePathExplicit(1, 2, suffix); }
307 
313  std::string MakeAlternativePath() const {
314  return ".cvmfsalt-" + ToStringWithSuffix();
315  }
316 
323  std::string MakePathWithoutSuffix() const {
324  return MakePathExplicit(1, 2, kSuffixNone);
325  }
326 
339  std::string MakePathExplicit(const unsigned dir_levels,
340  const unsigned digits_per_level,
341  const Suffix hash_suffix = kSuffixNone) const {
342  Hex hex(this);
343 
344  // figure out how big the output string needs to be
345  const bool use_suffix = (hash_suffix != kSuffixNone);
346  const unsigned string_length = hex.length() + dir_levels + use_suffix;
347  std::string result;
348  result.resize(string_length);
349 
350  // build hexified hash and path delimiters
351  unsigned i = 0;
352  unsigned pos = 0;
353  for (; i < hex.length(); ++i) {
354  if (i > 0 && (i % digits_per_level == 0)
355  && (i / digits_per_level <= dir_levels)) {
356  result[pos++] = '/';
357  }
358  result[pos++] = hex[i];
359  }
360 
361  // (optionally) add hash hint suffix
362  if (use_suffix) {
363  result[pos++] = hash_suffix;
364  }
365 
366  assert(i == hex.length());
367  assert(pos == string_length);
368  return result;
369  }
370 
371  bool IsNull() const {
372  for (unsigned i = 0; i < kDigestSizes[algorithm]; ++i) {
373  if (digest[i] != 0)
374  return false;
375  }
376  return true;
377  }
378 
382  uint32_t Partial32() const {
383  const uint32_t *partial = (const uint32_t *)digest;
384  return ntohl(*partial);
385  }
386 
387 
388  void SetNull() { memset(digest, 0, digest_size_); }
389 
390 
391  bool operator==(const Digest<digest_size_, algorithm_> &other) const {
392  if (this->algorithm != other.algorithm)
393  return false;
394  for (unsigned i = 0; i < kDigestSizes[algorithm]; ++i) {
395  if (this->digest[i] != other.digest[i])
396  return false;
397  }
398  return true;
399  }
400 
401  bool operator!=(const Digest<digest_size_, algorithm_> &other) const {
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 CVMFS_EXPORT 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 CVMFS_EXPORT Sha1 : public Digest<20, kSha1> { };
445 struct CVMFS_EXPORT Rmd160 : public Digest<20, kRmd160> { };
446 struct CVMFS_EXPORT Shake128 : public Digest<20, kShake128> { };
447 
453 struct CVMFS_EXPORT Any : public Digest<kMaxDigestSize, kAny> {
455 
456  explicit Any(const Algorithms a, const char s = kSuffixNone)
457  : Digest<kMaxDigestSize, kAny>() {
458  algorithm = a;
459  suffix = s;
460  }
461 
462  Any(const Algorithms a,
463  const unsigned char *digest_buffer,
464  const Suffix suffix = kSuffixNone)
465  : Digest<kMaxDigestSize, kAny>(a, digest_buffer, suffix) { }
466 
467  explicit Any(const Algorithms a,
468  const HexPtr hex,
469  const char suffix = kSuffixNone)
470  : Digest<kMaxDigestSize, kAny>(a, hex, suffix) { }
471 
472  Md5 CastToMd5();
473 };
474 
475 
481 
487  public:
489  void *buffer;
490  unsigned size;
491 
492  ContextPtr() : algorithm(kAny), buffer(NULL), size(0) { }
493 
494  explicit ContextPtr(const Algorithms a)
495  : algorithm(a), buffer(NULL), size(GetContextSize(a)) { }
496  ContextPtr(const Algorithms a, void *b)
497  : algorithm(a), buffer(b), size(GetContextSize(a)) { }
498 };
499 
500 CVMFS_EXPORT void Init(ContextPtr context);
501 CVMFS_EXPORT void Update(const unsigned char *buffer,
502  const unsigned buffer_size,
503  ContextPtr context);
504 CVMFS_EXPORT void Final(ContextPtr context, Any *any_digest);
505 CVMFS_EXPORT bool HashFile(const std::string &filename, Any *any_digest);
506 CVMFS_EXPORT bool HashFd(int fd, Any *any_digest);
507 CVMFS_EXPORT void HashMem(const unsigned char *buffer,
508  const unsigned buffer_size,
509  Any *any_digest);
510 CVMFS_EXPORT void HashString(const std::string &content, Any *any_digest);
511 CVMFS_EXPORT void Hmac(const std::string &key,
512  const unsigned char *buffer,
513  const unsigned buffer_size,
514  Any *any_digest);
515 inline void HmacString(const std::string &key, const std::string &content,
516  Any *any_digest) {
517  Hmac(key,
518  reinterpret_cast<const unsigned char *>(content.data()),
519  content.size(),
520  any_digest);
521 }
522 
530 CVMFS_EXPORT std::string Hmac256(const std::string &key,
531  const std::string &content,
532  bool raw_output = false);
533 CVMFS_EXPORT std::string Sha256File(const std::string &filename);
534 CVMFS_EXPORT std::string Sha256Mem(const unsigned char *buffer,
535  const unsigned buffer_size);
536 CVMFS_EXPORT std::string Sha256String(const std::string &content);
537 
539 Algorithms ParseHashAlgorithm(const std::string &algorithm_option);
541 Any MkFromHexPtr(const HexPtr hex, const Suffix suffix = kSuffixNone);
542 CVMFS_EXPORT Any MkFromSuffixedHexPtr(const HexPtr hex);
543 
544 } // namespace shash
545 
546 #ifdef CVMFS_NAMESPACE_GUARD
547 } // namespace CVMFS_NAMESPACE_GUARD
548 #endif
549 
550 #endif // CVMFS_CRYPTO_HASH_H_
void HashString(const std::string &content, Any *any_digest)
Definition: hash.cc:269
Hex(const Digest< digest_size_, algorithm_ > *digest)
Definition: hash.h:127
Definition: prng.h:27
bool operator==(const Digest< digest_size_, algorithm_ > &other) const
Definition: hash.h:391
const char kSuffixNone
Definition: compat.h:162
bool IsNull() const
Definition: hash.h:371
const unsigned kMaxContextSize
Definition: hash.h:76
Md5()
Definition: hash.h:432
void set_suffix(const Suffix s)
Definition: hash.h:232
const unsigned int hash_length_
Definition: hash.h:160
const std::string * str
Definition: hash.h:101
void Randomize()
Definition: hash.h:200
std::string MakeAlternativePath() const
Definition: hash.h:313
bool HashFile(const std::string &filename, Any *any_digest)
Definition: hash.cc:341
string Sha256String(const string &content)
Definition: hash.cc:451
std::string ToString(const bool with_suffix=false) const
Definition: hash.h:241
void Randomize(const uint64_t seed)
Definition: hash.h:212
std::string ToStringWithSuffix() const
Definition: hash.h:296
const unsigned kAlgorithmIdSizes[]
Definition: compat.h:159
char GetAlgorithmIdentifierChar(const unsigned int position) const
Definition: hash.h:149
const unsigned kMaxDigestSize
Definition: compat.h:38
void InitLocaltime()
Definition: prng.h:34
void Hmac(const string &key, const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
Definition: hash.cc:275
#define CVMFS_EXPORT
Definition: export.h:11
bool HasSuffix() const
Definition: hash.h:231
assert((mem||(size==0))&&"Out Of Memory")
string Sha256File(const string &filename)
Definition: hash.cc:411
char ToHex(const char c) const
Definition: hash.h:154
Algorithms algorithm
Definition: hash.h:122
Digest(const Algorithms a, const unsigned char *digest_buffer, const Suffix s=kSuffixNone)
Definition: hash.h:189
void InitSeed(const uint64_t seed)
Definition: prng.h:32
unsigned char digest[digest_size_]
Definition: hash.h:121
ContextPtr(const Algorithms a)
Definition: hash.h:494
char algorithm
HexPtr(const std::string &s)
Definition: hash.h:102
Algorithms
Definition: hash.h:41
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
Any()
Definition: hash.h:454
const std::string * str
Definition: hash.h:107
std::string ToFingerprint(const bool with_suffix=false) const
Definition: hash.h:267
string Sha256Mem(const unsigned char *buffer, const unsigned buffer_size)
Definition: hash.cc:441
const unsigned kMaxAlgorithmIdentifierSize
Definition: compat.h:160
Algorithms algorithm
Definition: hash.h:488
const char kSuffixHistory
Definition: compat.h:164
bool HasSuffix(const std::string &str, const std::string &suffix, const bool ignore_case)
Definition: string.cc:296
bool operator!=(const Digest< digest_size_, algorithm_ > &other) const
Definition: hash.h:401
ContextPtr(const Algorithms a, void *b)
Definition: hash.h:496
char GetHashChar(const unsigned int position) const
Definition: hash.h:141
AsciiPtr(const std::string &s)
Definition: hash.h:108
unsigned char digest[20]
static int Init(const loader::LoaderExports *loader_exports)
Definition: cvmfs.cc:2309
void Final(ContextPtr context, Any *any_digest)
Definition: hash.cc:223
const char kSuffixMicroCatalog
Definition: compat.h:165
const char kSuffixMetainfo
Definition: hash.h:60
void * buffer
Definition: hash.h:489
Any(const Algorithms a, const unsigned char *digest_buffer, const Suffix suffix=kSuffixNone)
Definition: hash.h:462
const char * kAlgorithmIds[]
Definition: hash.cc:33
uint32_t Partial32() const
Definition: hash.h:382
char Suffix
Definition: hash.h:111
void HashMem(const unsigned char *buffer, const unsigned buffer_size, Any *any_digest)
Definition: hash.cc:257
unsigned GetContextSize(const Algorithms algorithm)
Definition: hash.cc:150
std::string MakePathWithoutSuffix() const
Definition: hash.h:323
Any(const Algorithms a, const HexPtr hex, const char suffix=kSuffixNone)
Definition: hash.h:467
void Update(const unsigned char *buffer, const unsigned buffer_length, ContextPtr context)
Definition: hash.cc:192
void SetNull()
Definition: hash.h:388
unsigned GetHexSize() const
Definition: hash.h:165
unsigned int length() const
Definition: hash.h:132
std::string MakePathExplicit(const unsigned dir_levels, const unsigned digits_per_level, const Suffix hash_suffix=kSuffixNone) const
Definition: hash.h:339
void HmacString(const std::string &key, const std::string &content, Any *any_digest)
Definition: hash.h:515
Any MkFromSuffixedHexPtr(const HexPtr hex)
Definition: hash.cc:104
Digest(const Algorithms a, const HexPtr hex, const char s=0)
Definition: hash.h:171
Algorithms ParseHashAlgorithm(const string &algorithm_option)
Definition: hash.cc:71
const char kSuffixPartial
Definition: compat.h:166
char operator[](const unsigned int position) const
Definition: hash.h:134
bool HashFd(int fd, Any *any_digest)
Definition: hash.cc:320
Any MkFromHexPtr(const HexPtr hex, const char suffix)
Definition: hash.cc:82
std::string Hmac256(const std::string &key, const std::string &content, bool raw_output)
Definition: hash.cc:457
Suffix suffix
Definition: hash.h:123
std::string MakePath() const
Definition: hash.h:306
unsigned size
Definition: hash.h:490
bool operator>(const Digest< digest_size_, algorithm_ > &other) const
Definition: hash.h:417
const char kSuffixCatalog
Definition: compat.h:163
static void size_t size
Definition: smalloc.h:54
const char kSuffixTemporary
Definition: compat.h:167
void Randomize(Prng *prng)
Definition: hash.h:224
Md5(const HexPtr hex)
Definition: hash.h:434
const char kSuffixCertificate
Definition: compat.h:168
uint32_t Next(const uint64_t boundary)
Definition: prng.h:44
const unsigned int algo_id_length_
Definition: hash.h:161
Any(const Algorithms a, const char s=kSuffixNone)
Definition: hash.h:456