Improved definition of magic constants

This commit is contained in:
tevador 2019-03-13 22:58:22 +01:00
parent 0d9beb5418
commit a2e7e05c40
2 changed files with 39 additions and 14 deletions

View File

@ -106,9 +106,9 @@ SquareHash was chosen for its relative simplicity (uses only two operations - mu
From a cryptographic standpoint, SquareHash achieves full [Avalanche effect](https://en.wikipedia.org/wiki/Avalanche_effect). SquareHash was originally based on [exponentiation by squaring](https://en.wikipedia.org/wiki/Exponentiation_by_squaring). In the [x86 assembly implementation](https://github.com/tevador/RandomX/blob/master/src/asm/squareHash.inc), if `adc rax, 0` is added after each subtraction, SquareHash becomes the following operation:
<code>
(x+1613783669344650115)<sup>4398046511104</sup> mod 2<sup>64</sup>+1
(x+9507361525245169745)<sup>4398046511104</sup> mod 2<sup>64</sup>+1
</code>,
where <code>4398046511104 = 2<sup>42</sup></code>. The addition of the carry was removed to improve CPU performance. The constant `1613783669344650115` is added to make SquareHash sensitive to zero.
where <code>4398046511104 = 2<sup>42</sup></code>. The addition of the carry was removed to improve CPU performance. The constant `9507361525245169745` is added to make SquareHash sensitive to zero.
#### Generator

View File

@ -97,11 +97,20 @@ The Generator produces a sequence of pseudo-random bytes.
The Generator state consists of 64 bytes arranged into four columns of 16 bytes each. During each output iteration, every column is decrypted (columns 0, 2) or encrypted (columns 1, 3) with one AES round using the following round keys (one key per column):
```
key0 = 26 4d a0 67 ab e6 2d 7d 2f 8d 49 79 06 f2 74 92
key1 = 12 98 71 4f 15 8a 65 86 1d 6f 3a 2a 05 af f7 e1
key2 = 0e 75 90 ba ce 7b c7 14 14 c9 2e 9e 91 f7 b1 d1
key3 = 1f 62 07 aa 4f be 3b a5 3c 88 57 6e d9 0f 9d 17
key0 = 2d ec ee 84 d5 f6 4f 45 32 91 32 ca e3 a2 20 df
key1 = d0 63 7b 01 78 c5 0f f1 7f 38 d0 fe 71 59 eb 1d
key2 = 52 7a 7d 32 a1 70 2c 2f b4 ce 17 a5 b3 26 c9 df
key3 = d3 77 8d 5c 5e da 17 3d a9 e0 ec a0 1c f3 1c 34
```
These keys were generated by calculating Blake2b hash with 256-bit output of these ASCII strings (first 128 bits of the hash are used):
```
"RandomX Generator key0"
"RandomX Generator key1"
"RandomX Generator key2"
"RandomX Generator key3"
```
Single iteration produces 64 bytes of output which also become the new generator state.
```
state0 (16 B) state1 (16 B) state2 (16 B) state3 (16 B)
@ -120,10 +129,18 @@ The Finalizer calculates a 512-bit fingerprint of its input.
The Finalizer has a 64-byte internal state, which is arranged into four columns of 16 bytes each. The initial state is:
```
state0 = 5d 9f e4 3f 93 8d ac 30 85 33 94 59 ae b0 04 9d
state1 = 64 60 0c 7b d3 ec 24 a7 35 09 c1 dd f1 eb 39 8a
state2 = e3 82 53 fb f7 ec 12 7c da ed 01 df 20 04 c7 7e
state3 = 05 b7 28 77 09 41 e7 b2 c8 d1 82 50 01 d2 a9 94
state0 = 00 8e 77 c4 ab f5 7a 88 67 d1 46 11 fd 26 31 8d
state1 = 4b ef 34 b8 89 af 95 1b 2b 63 da 58 a1 9f fe 19
state2 = 3a dd 42 77 00 3a 28 ab 44 d7 5a c3 74 cd b2 1b
state3 = 9a 44 8b e1 cc 97 5d dc 57 3c 59 49 8a a5 30 bb
```
The initial state vectors were generated by calculating Blake2b hash with 256-bit output of these ASCII strings (first 128 bits of the hash are used):
```
"RandomX Finalizer state0"
"RandomX Finalizer state1"
"RandomX Finalizer state2"
"RandomX Finalizer state3"
```
The input is processed in 64-byte blocks. Each input block is considered to be a set of four AES round keys `key0`, `key1`, `key2`, `key3`. Each state column is encrypted (columns 0, 2) or decrypted (columns 1, 3) with one AES round using the corresponding round key:
@ -141,8 +158,14 @@ state0 (16 B) state1 (16 B) state2 (16 B) state3 (16 B)
When all input bytes have been processed, the state is processed with two additional AES rounds with the following extra keys (one key per round, same pair of keys for all columns):
```
xkey0 = 17 7b 76 c3 44 a7 31 82 05 d7 3b 05 c5 37 f6 4f
xkey1 = 2e ae 8f 8a 00 a2 1d b0 58 9d 87 a8 a6 a1 94 65
xkey0 = 47 f2 cb 11 9c 92 5a 2a 3d 59 c5 e4 83 12 95 83
xkey1 = 95 6c 81 ce 0b ef 7b 47 23 25 bc ab b2 5b 21 ff
```
The extra keys were generated by calculating Blake2b hash with 256-bit output of these ASCII strings (first 128 bits of the hash are used):
```
"RandomX Finalizer xkey0"
"RandomX Finalizer xkey1"
```
```
@ -163,14 +186,16 @@ The final state is the output of the function.
### 3.4 SquareHash
`SquareHash` is a custom diffusion function with a 64-bit input and a 64-bit output. It is calculated by adding `1613783669344650115` to the input value and then repeatedly squaring the state, splitting the 128-bit result in to two 64-bit halves and subtracting the high half from the low half. This is repeated 42 times.
`SquareHash` is a custom diffusion function with a 64-bit input and a 64-bit output. It is calculated by adding `9507361525245169745` to the input value and then repeatedly squaring the state, splitting the 128-bit result in to two 64-bit halves and subtracting the high half from the low half. This is repeated 42 times.
1. `state = input + 1613783669344650115`
1. `state = input + 9507361525245169745`
2. `(hi, lo) = state * state`
3. `state = lo - hi`
4. Perform steps 2-3 total of 42 times.
5. Return `state`.
The magic constant `9507361525245169745` was generated by calculating `SquareHash0(42)`, where `SquareHash0` is a version of `SquareHash` without the magic constant addition in step 1.
## 4. Virtual Machine
The RandomX virtual machine can be summarized by the following schematic: