@@ -141,66 +141,66 @@ https://github.com/IntersectMBO/ouroboros-network/pull/4951. We would advise to
141141fix this Nix-related bug rather than downgrading ` lsm-tree ` ’s dependency on
142142` io-classes ` to version 1.5.
143143
144- # Security of hash based data structures
144+ # Security of hash- based data structures
145145
146146Data structures based on hashing have to be considered carefully when they may
147- be used with untrusted data. If the attacker can control the keys in a hash
148- table for example, they may be able to arrange for all their keys to have hash
149- collisions which may cause unexpected performance problems. This is why the
150- Haskell Cardano node implementation does not use hash tables, and uses
151- ordering-based containers instead (such as ` Data.Map ` ) .
152-
153- The Bloom filters in an LSM tree are hash based data structures. For performance
154- they do not use cryptographic hashes. So in principle it would be possibile for
155- an attacker to arrange that all their keys hash to a common set of bits. This
156- would be a potential problem for the UTxO and other stake related tables in
157- Cardano, since it is the users that get to pick (with old modest grinding
158- difficulty) their UTxO keys (TxIn ) and stake keys (verification key hashes). It
159- would be even more serious if an attacker can grind their set of malicious keys
160- locally, in the knowledge that the same set of keys will hash the same way on
161- all other Cardano nodes.
162-
163- This issue was not considered in the original project specification, but we
164- have considered it and included a mitigation. The mitigation is that on the
165- initial creation of a lsm-tree session, a random salt is conjured (from
166- ` /dev/random ` ) and stored persistenly as part of the session. This salt is then
167- used as part of the Bloom filter hashing for all runs in all tables in the
168- session.
169-
170- The result is that while it is in principle still possible to produce hash
171- collisions in the Bloom filter, this now depends on knowing the salt. And now
172- every node has a different salt. So a system wide attack becomes impossible;
173- instead it is only plausible to target individual nodes. Discovering a node's
174- salt would also be impractically difficult. In principle there is a timing
175- side channel, in that collisions will cause more I/O and thus take longer .
176- An attacker would need to get upstream of a victim node, supply a valid block
177- and measure the timing of receiving the block downstream. There is however a
178- large amount of noise.
179-
180- Overall, our judgement is that this mitigation is practically sufficient, but
181- it merits a securit review from others who may make a different judgement. It
182- is also worth noting that this issue may occur in other LSM-trees used in other
183- Cardano and non-Cardano implementations. In particular, RocksDB does not appear
184- to use a salt at all.
185-
186- Note that a per-run or per-table hash salt would incur non-trivial costs ,
187- because it would reduce the sharing available in bulk Bloom filter lookups
188- (looking up N keys in M filters). The Bloom filter lookup is a performance
189- sensitive part of the overall database implementation.
190-
191- In the Cardano context, a downside of a per-session (and thus per-node) Bloom
192- filter salt is that it may interact poorly with sharing of pre-created
193- databases. While it will work to copy a whole database session (since this
194- includes the salt), it means the salt is then shared between the nodes. If SPOs
195- share databases widely with each other (to avoid syning the entire chain), then
196- the salt diversity is lost. This would be especially acute with Mithril which
197- shares a single copy of the database. It may be necesary for proper Mithril
198- support to add a re-salting operation, and to perform this re-salting operation
199- after cloning a Mithril snapshot. Re-salting would involve re-creating the
200- Bloom filter for each table run , which involves reading each run and inserting
201- into a new Bloom filter, and writing out the new Bloom filter. This would of
202- course be additional development work, but the infrastructure needed is
203- present already.
147+ be used with untrusted data. For example, an attacker who can control the keys
148+ in a hash table may be able to provoke hash collisions and cause unexpected
149+ performance problems this way . This is why the Haskell Cardano node
150+ implementation does not use hash tables but ordering-based containers, such as
151+ those provided by ` Data.Map ` .
152+
153+ The Bloom filters in an LSM-Tree are hash- based data structures. For the sake of
154+ performance, they do not use cryptographic hashes. Thus, without additional
155+ measures, an attacker can in principle choose keys whose hashs identify mostly
156+ the same bits. This is a potential problem for the UTxO and other stake- related
157+ tables in Cardano, since it is the users who get to pick their UTxO keys (TxIn)
158+ and stake keys (verification key hashes ) and these keys will hash the same way
159+ on all other Cardano nodes.
160+
161+ This issue was not considered in the original project specification, but we have
162+ taken it into account and have included a mitigation in ` lsm-tree ` . The
163+ mitigation is that, on the initial creation of a session, a random salt is
164+ conjured and stored persistenly as part of the session. This salt is then used
165+ as part of the Bloom filter hashing for all runs in all tables of the session.
166+
167+ The consequence is that, while it is in principle still possible to produce hash
168+ collisions in the Bloom filter, this now depends on knowing the salt. However,
169+ every node has a different salt. Thus a system-wide attack becomes impossible.
170+ It is only plausible to target individual nodes, but discovering a node’s salt
171+ is extremely difficult. In principle there is a timing side channel, in that
172+ collisions will cause more I/O and thus cause longer running times. To exploit
173+ this, an attacker would need to get upstream of a victim node, supply a valid
174+ block and measure the timing of receiving the block downstream. There would,
175+ however, be a large amount of noise spoiling such an attack .
176+
177+ Overall, our judgement is that our mitigation is sufficient, but it merits a
178+ security review from others who may make a different judgement. It is also worth
179+ noting that the described hash clash issue may occur in other LSM-tree
180+ implementations used in other software, related and unrelated to Cardano. In
181+ particular, RocksDB does not appear to use a salt at all.
182+
183+ Note that using a per-run or per-table hash salt would incur non-trivial costs,
184+ because it would reduce the sharing available in bulk Bloom filter lookups,
185+ where several keys are looked up in several filters. Given that the Bloom filter
186+ lookup is a performance-sensitive part of the overall database implementation ,
187+ such an approach to salting does not seem feasible.
188+
189+ In the Cardano context, a downside of picking Bloom filter salts per session and
190+ thus per node is that this interacts poorly with sharing of pre-created
191+ databases. While it would still be possible to copy a whole database session,
192+ since this includes the salt, doing so would result in the salt being shared
193+ between nodes. If SPOs shared databases widely with each other, to avoid
194+ processing the entire chain, then the salt diversity would be lost.
195+
196+ Picking Bloom filter salts per session is particularly problematic in Mithril,
197+ which shares a single copy of the database. It may be necessary for proper
198+ Mithril support to add a re-salting operation and to perform this operation
199+ after cloning a Mithril snapshot. Re-salting would involve re-creating the Bloom
200+ filters for all table runs , which would mean reading each run, inserting its
201+ keys into a new Bloom filter and finally writing out the new Bloom filter.
202+ Adding such a feature would, of course, incur additional development work, but
203+ the infrastructure needed is present already.
204204
205205# Possible file system incompatibility with XFS
206206
0 commit comments