This file is indexed.

/usr/share/pyshared/allmydata/util/hashutil.py is in tahoe-lafs 1.9.2-1.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  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
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
from pycryptopp.hash.sha256 import SHA256
import os
from allmydata.util.netstring import netstring

try:
    import hashlib
    sha1 = hashlib.sha1
except ImportError:
    # hashlib was added in Python 2.5
    import sha
    sha1 = sha.new

# Be very very cautious when modifying this file. Almost any change will
# cause a compatibility break, invalidating all outstanding URIs and making
# any previously uploaded files become inaccessible. BE CONSERVATIVE AND TEST
# AGAINST OLD DATA!

# Various crypto values are this size: hash outputs (from SHA-256d),
# randomly-generated secrets such as the lease secret, and symmetric encryption
# keys.  In the near future we will add DSA private keys, and salts of various
# kinds.
CRYPTO_VAL_SIZE=32

class _SHA256d_Hasher:
    # use SHA-256d, as defined by Ferguson and Schneier: hash the output
    # again to prevent length-extension attacks
    def __init__(self, truncate_to=None):
        self.h = SHA256()
        self.truncate_to = truncate_to
        self._digest = None
    def update(self, data):
        assert isinstance(data, str) # no unicode
        self.h.update(data)
    def digest(self):
        if self._digest is None:
            h1 = self.h.digest()
            del self.h
            h2 = SHA256(h1).digest()
            if self.truncate_to:
                h2 = h2[:self.truncate_to]
            self._digest = h2
        return self._digest



def tagged_hasher(tag, truncate_to=None):
    hasher = _SHA256d_Hasher(truncate_to)
    hasher.update(netstring(tag))
    return hasher

def tagged_hash(tag, val, truncate_to=None):
    hasher = tagged_hasher(tag, truncate_to)
    hasher.update(val)
    return hasher.digest()

def tagged_pair_hash(tag, val1, val2, truncate_to=None):
    s = _SHA256d_Hasher(truncate_to)
    s.update(netstring(tag))
    s.update(netstring(val1))
    s.update(netstring(val2))
    return s.digest()

## specific hash tags that we use

# immutable
STORAGE_INDEX_TAG = "allmydata_immutable_key_to_storage_index_v1"
BLOCK_TAG = "allmydata_encoded_subshare_v1"
UEB_TAG = "allmydata_uri_extension_v1"
PLAINTEXT_TAG = "allmydata_plaintext_v1"
CIPHERTEXT_TAG = "allmydata_crypttext_v1"
CIPHERTEXT_SEGMENT_TAG = "allmydata_crypttext_segment_v1"
PLAINTEXT_SEGMENT_TAG = "allmydata_plaintext_segment_v1"
CONVERGENT_ENCRYPTION_TAG = "allmydata_immutable_content_to_key_with_added_secret_v1+"

CLIENT_RENEWAL_TAG = "allmydata_client_renewal_secret_v1"
CLIENT_CANCEL_TAG = "allmydata_client_cancel_secret_v1"
FILE_RENEWAL_TAG = "allmydata_file_renewal_secret_v1"
FILE_CANCEL_TAG = "allmydata_file_cancel_secret_v1"
BUCKET_RENEWAL_TAG = "allmydata_bucket_renewal_secret_v1"
BUCKET_CANCEL_TAG = "allmydata_bucket_cancel_secret_v1"

# mutable
MUTABLE_WRITEKEY_TAG = "allmydata_mutable_privkey_to_writekey_v1"
MUTABLE_WRITE_ENABLER_MASTER_TAG = "allmydata_mutable_writekey_to_write_enabler_master_v1"
MUTABLE_WRITE_ENABLER_TAG = "allmydata_mutable_write_enabler_master_and_nodeid_to_write_enabler_v1"
MUTABLE_PUBKEY_TAG = "allmydata_mutable_pubkey_to_fingerprint_v1"
MUTABLE_READKEY_TAG = "allmydata_mutable_writekey_to_readkey_v1"
MUTABLE_DATAKEY_TAG = "allmydata_mutable_readkey_to_datakey_v1"
MUTABLE_STORAGEINDEX_TAG = "allmydata_mutable_readkey_to_storage_index_v1"

# dirnodes
DIRNODE_CHILD_WRITECAP_TAG = "allmydata_mutable_writekey_and_salt_to_dirnode_child_capkey_v1"
DIRNODE_CHILD_SALT_TAG = "allmydata_dirnode_child_rwcap_to_salt_v1"

def storage_index_hash(key):
    # storage index is truncated to 128 bits (16 bytes). We're only hashing a
    # 16-byte value to get it, so there's no point in using a larger value.  We
    # use this same tagged hash to go from encryption key to storage index for
    # random-keyed immutable files and convergent-encryption immutabie
    # files. Mutable files use ssk_storage_index_hash().
    return tagged_hash(STORAGE_INDEX_TAG, key, 16)

def block_hash(data):
    return tagged_hash(BLOCK_TAG, data)
def block_hasher():
    return tagged_hasher(BLOCK_TAG)

def uri_extension_hash(data):
    return tagged_hash(UEB_TAG, data)
def uri_extension_hasher():
    return tagged_hasher(UEB_TAG)

def plaintext_hash(data):
    return tagged_hash(PLAINTEXT_TAG, data)
def plaintext_hasher():
    return tagged_hasher(PLAINTEXT_TAG)

def crypttext_hash(data):
    return tagged_hash(CIPHERTEXT_TAG, data)
def crypttext_hasher():
    return tagged_hasher(CIPHERTEXT_TAG)

def crypttext_segment_hash(data):
    return tagged_hash(CIPHERTEXT_SEGMENT_TAG, data)
def crypttext_segment_hasher():
    return tagged_hasher(CIPHERTEXT_SEGMENT_TAG)

def plaintext_segment_hash(data):
    return tagged_hash(PLAINTEXT_SEGMENT_TAG, data)
def plaintext_segment_hasher():
    return tagged_hasher(PLAINTEXT_SEGMENT_TAG)

KEYLEN = 16
IVLEN = 16

def convergence_hash(k, n, segsize, data, convergence):
    h = convergence_hasher(k, n, segsize, convergence)
    h.update(data)
    return h.digest()
def convergence_hasher(k, n, segsize, convergence):
    assert isinstance(convergence, str)
    param_tag = netstring("%d,%d,%d" % (k, n, segsize))
    tag = CONVERGENT_ENCRYPTION_TAG + netstring(convergence) + param_tag
    return tagged_hasher(tag, KEYLEN)

def random_key():
    return os.urandom(KEYLEN)

def my_renewal_secret_hash(my_secret):
    return tagged_hash(my_secret, CLIENT_RENEWAL_TAG)
def my_cancel_secret_hash(my_secret):
    return tagged_hash(my_secret, CLIENT_CANCEL_TAG)

def file_renewal_secret_hash(client_renewal_secret, storage_index):
    return tagged_pair_hash(FILE_RENEWAL_TAG,
                            client_renewal_secret, storage_index)

def file_cancel_secret_hash(client_cancel_secret, storage_index):
    return tagged_pair_hash(FILE_CANCEL_TAG,
                            client_cancel_secret, storage_index)

def bucket_renewal_secret_hash(file_renewal_secret, peerid):
    assert len(peerid) == 20, "%s: %r" % (len(peerid), peerid) # binary!
    return tagged_pair_hash(BUCKET_RENEWAL_TAG, file_renewal_secret, peerid)

def bucket_cancel_secret_hash(file_cancel_secret, peerid):
    assert len(peerid) == 20, "%s: %r" % (len(peerid), peerid) # binary!
    return tagged_pair_hash(BUCKET_CANCEL_TAG, file_cancel_secret, peerid)


def _xor(a, b):
    return "".join([chr(ord(c) ^ ord(b)) for c in a])

def hmac(tag, data):
    ikey = _xor(tag, "\x36")
    okey = _xor(tag, "\x5c")
    h1 = SHA256(ikey + data).digest()
    h2 = SHA256(okey + h1).digest()
    return h2

def mutable_rwcap_key_hash(iv, writekey):
    return tagged_pair_hash(DIRNODE_CHILD_WRITECAP_TAG, iv, writekey, KEYLEN)
def mutable_rwcap_salt_hash(writekey):
    return tagged_hash(DIRNODE_CHILD_SALT_TAG, writekey, IVLEN)

def ssk_writekey_hash(privkey):
    return tagged_hash(MUTABLE_WRITEKEY_TAG, privkey, KEYLEN)
def ssk_write_enabler_master_hash(writekey):
    return tagged_hash(MUTABLE_WRITE_ENABLER_MASTER_TAG, writekey)
def ssk_write_enabler_hash(writekey, peerid):
    assert len(peerid) == 20, "%s: %r" % (len(peerid), peerid) # binary!
    wem = ssk_write_enabler_master_hash(writekey)
    return tagged_pair_hash(MUTABLE_WRITE_ENABLER_TAG, wem, peerid)

def ssk_pubkey_fingerprint_hash(pubkey):
    return tagged_hash(MUTABLE_PUBKEY_TAG, pubkey)

def ssk_readkey_hash(writekey):
    return tagged_hash(MUTABLE_READKEY_TAG, writekey, KEYLEN)
def ssk_readkey_data_hash(IV, readkey):
    return tagged_pair_hash(MUTABLE_DATAKEY_TAG, IV, readkey, KEYLEN)
def ssk_storage_index_hash(readkey):
    return tagged_hash(MUTABLE_STORAGEINDEX_TAG, readkey, KEYLEN)

def constant_time_compare(a, b):
    n = os.urandom(8)
    return bool(tagged_hash(n, a) == tagged_hash(n, b))

BACKUPDB_DIRHASH_TAG = "allmydata_backupdb_dirhash_v1"
def backupdb_dirhash(contents):
    return tagged_hash(BACKUPDB_DIRHASH_TAG, contents)