1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
|
# Store Paths
A store path is a pair of a 20-byte digest and a name.
## String representation
A store path is rendered as the concatenation of
- a store directory
- a path-separator (`/`)
- the digest rendered as Base-32 (20 arbitrary bytes becomes 32 ASCII chars)
- a hyphen (`-`)
- the name
Let's take the store path from the very beginning of this manual as an example:
/nix/store/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1
This parses like so:
/nix/store/b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z-firefox-33.1
^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^
store dir digest name
We then can discard the store dir to recover the conceptual pair that is a store path:
{
digest: "b6gvzjyb2pg0kjfwrjmg1vfhh54ad73z",
name: "firefox-33.1",
}
### Where did the "store directory" come from?
If you notice, the above references a "store directory", but that is *not* part of the definition of a store path.
We can discard it when parsing, but what about when printing?
We need to get a store directory from *somewhere*.
The answer is, the store directory is a property of the store that contains the store path.
The explanation for this is simple enough: a store is notionally mounted as a directory at some location, and the store object's root file system likewise mounted at this path within that directory.
This does, however, mean the string representation of a store path is not derived just from the store path itself, but is in fact "context dependent".
## The digest
The calculation of the digest is quite complicated for historical reasons.
The details of the algorithms will be discussed later once more concepts have been introduced.
For now, we just concern ourselves with the *key properties* of those algorithms.
::: {.note}
**Historical note** The 20 byte restriction is because originally a digests were SHA-1 hashes.
This is no longer true, but longer hashes and other information are still boiled down to 20 bytes.
:::
Store paths are either *content-addressed* or *input-addressed*.
::: {.note}
The former is a standard term used elsewhere.
The later is our own creation to evoke a contrast with content addressing.
:::
Content addressing means that the store path digest ultimately derives from referred store object's contents, namely its file system objects and references.
There is more than one *method* of content-addressing, however.
Still, if one does know the content addressing schema that was used,
(or guesses, there isn't that many yet!)
one can recalculate the store path and thus verify the store object.
Input addressing means that the store path digest derives from how the store path was produced, namely the "inputs" and plan that it was built from.
Store paths of this sort can *not* be validated from the content of the store object.
Rather, the store object might come with the store path it expects to be referred to by, and a signature of that path, the contents of the store path, and other metadata.
The signature indicates that someone is vouching for the store object really being the results of a plan with that digest.
While metadata is included in the digest calculation explaining which method it was calculated by, this only serves to thwart pre-image attacks.
That metadata is scrambled with everything else so that it is difficult to tell how a given store path was produced short of a brute-force search.
In the parlance of referencing schemes, this means that store paths are not "self-describing".
|