summaryrefslogtreecommitdiff
path: root/src/ext/equix/hashx/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'src/ext/equix/hashx/README.md')
-rw-r--r--src/ext/equix/hashx/README.md135
1 files changed, 135 insertions, 0 deletions
diff --git a/src/ext/equix/hashx/README.md b/src/ext/equix/hashx/README.md
new file mode 100644
index 0000000000..1d8ea47652
--- /dev/null
+++ b/src/ext/equix/hashx/README.md
@@ -0,0 +1,135 @@
+# HashX
+
+HashX is an algorithm designed for client puzzles and proof-of-work schemes.
+While traditional cryptographic hash functions use a fixed one-way compression
+function, each HashX instance represents a unique pseudorandomly generated
+one-way function.
+
+HashX functions are generated as a carefully crafted sequence of integer
+operations to fully saturate a 3-way superscalar CPU pipeline (modeled after
+the Intel Ivy Bridge architecture). Extra care is taken to avoid optimizations
+and to ensure that each function takes exactly the same number of CPU cycles
+(currently 512 instructions over 192 cycles).
+
+## API
+
+The API consists of 4 functions and is documented in the public header file
+[hashx.h](include/hashx.h).
+
+Example of usage:
+
+```c
+#include <hashx.h>
+#include <stdio.h>
+
+int main() {
+ char seed[] = "this is a seed that will generate a hash function";
+ char hash[HASHX_SIZE];
+ hashx_ctx* ctx = hashx_alloc(HASHX_COMPILED);
+ if (ctx == HASHX_NOTSUPP)
+ ctx = hashx_alloc(HASHX_INTERPRETED);
+ if (ctx == NULL)
+ return 1;
+ if (!hashx_make(ctx, seed, sizeof(seed))) /* generate a hash function */
+ return 1;
+ hashx_exec(ctx, 123456789, hash); /* calculate the hash of a nonce value */
+ hashx_free(ctx);
+ for (unsigned i = 0; i < HASHX_SIZE; ++i)
+ printf("%02x", hash[i] & 0xff);
+ printf("\n");
+ return 0;
+}
+```
+
+## Build
+
+A C99-compatible compiler and `cmake` are required.
+
+```
+git clone https://github.com/tevador/hashx.git
+cd hashx
+mkdir build
+cd build
+cmake .. [-DHASHX_BLOCK_MODE=ON] [-DHASHX_SIZE=<1-32>] [-DHASHX_SALT="my custom hash"]
+make
+```
+
+### Block mode (default: off)
+
+Because HashX is meant to be used in proof-of-work schemes and client puzzles,
+the input is a 64-bit counter value. If you need to hash arbitrary data, build
+with `-DHASHX_BLOCK_MODE=ON`. This will change the API to accept `const void*, size_t` instead of `uint64_t`.
+However, it is strongly recommended to use the counter mode, which is almost twice faster for short inputs.
+
+### Hash size (default: 32)
+
+The default hash output size is 32 bytes (256 bits). If you want to reduce the output
+size, build with, for example, `-DHASHX_SIZE=20`. Output sizes in the range of 1-32 bytes
+are supported. Shorter output sizes are formed by simply truncating the full 256-bit hash.
+
+### Generator salt (default: "HashX v1")
+
+An implementation-specific salt value may be specified when building, for example: `-DHASHX_SALT="my custom hash"`.
+This value is used as a salt when generating hash instances. The maximum supported
+salt size is 15 characters.
+
+## Performance
+
+HashX was designed for fast verification. Generating a hash function from seed
+takes about 50 μs and a 64-bit nonce can be hashed in under 100 ns (in compiled
+mode) or in about 1-2 μs (in interpreted mode).
+
+A benchmark executable is included:
+```
+./hashx-bench --seeds 500
+```
+
+## Security
+
+HashX should provide strong preimage resistance. No other security guarantees are made. About
+ 99% of HashX instances pass [SMHasher](https://github.com/tevador/smhasher),
+ but using HashX as a generic hash function is not recommended.
+
+Known vulnerabilities that should not affect intended use cases:
+
+1. HashX is not collision resistant. Around 0.2% of seeds produce "weak" hash functions for
+which hash collisions are plentiful.
+2. Secret values should not be used as inputs to HashX because the generated instructions
+include data-dependent branches by design.
+
+## Protocols based on HashX
+
+Here are two examples of how HashX can be used in practice:
+
+### Interactive client puzzle
+
+Client puzzles are protocols designed to protect server resources from abuse.
+A client requesting a resource from a server may be asked to solve a puzzle
+before the request is accepted.
+
+One of the first proposed client puzzles is [Hashcash](https://en.wikipedia.org/wiki/Hashcash),
+which requires the client to find a partial SHA-1 hash inversion. However,
+because of the static nature of cryptographic hash functions, an attacker can
+offload hashing to a GPU or FPGA to gain a significant advantage over legitimate
+clients equipped only with a CPU.
+
+In a HashX-based interactive client puzzle, the server sends each client
+a 256-bit challenge used to generate a unique HashX function. The client then
+has to find a 64-bit nonce value such that the resulting hash has a predefined
+number of leading zeroes. An attacker cannot easily parallelize the workload
+because each request would require a new GPU kernel or FPGA bistream.
+
+### Non-interactive proof-of-work
+
+In the absence of a central authority handing out challenges (for example in
+a cryptocurrency), the client takes some public information `T` (for example
+a block template) and combines it with a chosen 64-bit nonce `N1`.
+The resulting string `X = T||N1` is then used to generate a HashX function
+<code>H<sub>X</sub></code>. The client then tries to find a 16-bit nonce `N2`
+such that <code>r = H<sub>X</sub>(N2)</code> meets the difficulty target of
+the protocol. If no `N2` value is successful, the client increments `N1` and
+tries with a different hash function.
+
+In this protocol, each HashX function provides only 65536 attempts before it
+must be discarded. This limits the parallelization advantage of GPUs and FPGAs.
+A CPU core will be able to test about 200 different hash functions per second.