1 #pragma once
2 
3 #include "types.hh"
4 #include "serialise.hh"
5 
6 
7 namespace nix {
8 
9 
10 MakeError(BadHash, Error);
11 
12 
13 enum HashType : char { htUnknown, htMD5, htSHA1, htSHA256, htSHA512 };
14 
15 
16 const int md5HashSize = 16;
17 const int sha1HashSize = 20;
18 const int sha256HashSize = 32;
19 const int sha512HashSize = 64;
20 
21 extern const string base32Chars;
22 
23 enum Base : int { Base64, Base32, Base16, SRI };
24 
25 
26 struct Hash
27 {
28     static const unsigned int maxHashSize = 64;
29     unsigned int hashSize = 0;
30     unsigned char hash[maxHashSize] = {};
31 
32     HashType type = htUnknown;
33 
34     /* Create an unset hash object. */
Hashnix::Hash35     Hash() { };
36 
37     /* Create a zero-filled hash object. */
Hashnix::Hash38     Hash(HashType type) : type(type) { init(); };
39 
40     /* Initialize the hash from a string representation, in the format
41        "[<type>:]<base16|base32|base64>" or "<type>-<base64>" (a
42        Subresource Integrity hash expression). If the 'type' argument
43        is htUnknown, then the hash type must be specified in the
44        string. */
45     Hash(const std::string & s, HashType type = htUnknown);
46 
47     void init();
48 
49     /* Check whether a hash is set. */
operator boolnix::Hash50     operator bool () const { return type != htUnknown; }
51 
52     /* Check whether two hash are equal. */
53     bool operator == (const Hash & h2) const;
54 
55     /* Check whether two hash are not equal. */
56     bool operator != (const Hash & h2) const;
57 
58     /* For sorting. */
59     bool operator < (const Hash & h) const;
60 
61     /* Returns the length of a base-16 representation of this hash. */
base16Lennix::Hash62     size_t base16Len() const
63     {
64         return hashSize * 2;
65     }
66 
67     /* Returns the length of a base-32 representation of this hash. */
base32Lennix::Hash68     size_t base32Len() const
69     {
70         return (hashSize * 8 - 1) / 5 + 1;
71     }
72 
73     /* Returns the length of a base-64 representation of this hash. */
base64Lennix::Hash74     size_t base64Len() const
75     {
76         return ((4 * hashSize / 3) + 3) & ~3;
77     }
78 
79     /* Return a string representation of the hash, in base-16, base-32
80        or base-64. By default, this is prefixed by the hash type
81        (e.g. "sha256:"). */
82     std::string to_string(Base base = Base32, bool includeType = true) const;
83 };
84 
85 
86 /* Print a hash in base-16 if it's MD5, or base-32 otherwise. */
87 string printHash16or32(const Hash & hash);
88 
89 /* Compute the hash of the given string. */
90 Hash hashString(HashType ht, const string & s);
91 
92 /* Compute the hash of the given file. */
93 Hash hashFile(HashType ht, const Path & path);
94 
95 /* Compute the hash of the given path.  The hash is defined as
96    (essentially) hashString(ht, dumpPath(path)). */
97 typedef std::pair<Hash, unsigned long long> HashResult;
98 HashResult hashPath(HashType ht, const Path & path,
99     PathFilter & filter = defaultPathFilter);
100 
101 /* Compress a hash to the specified number of bytes by cyclically
102    XORing bytes together. */
103 Hash compressHash(const Hash & hash, unsigned int newSize);
104 
105 /* Parse a string representing a hash type. */
106 HashType parseHashType(const string & s);
107 
108 /* And the reverse. */
109 string printHashType(HashType ht);
110 
111 
112 union Ctx;
113 
114 class HashSink : public BufferedSink
115 {
116 private:
117     HashType ht;
118     Ctx * ctx;
119     unsigned long long bytes;
120 
121 public:
122     HashSink(HashType ht);
123     HashSink(const HashSink & h);
124     ~HashSink();
125     void write(const unsigned char * data, size_t len);
126     HashResult finish();
127     HashResult currentHash();
128 };
129 
130 
131 }
132