README.md (3156B)
1 # SLH-DSA Test Vectors 2 3 This folder contains some things that are used to create test vectors 4 using the an "as close as possible" implementation of SPHINCS+, patched 5 to be SLH-DSA compatible. 6 7 The test vectors are generated by using the SPHINCS+ reference 8 implementation 9 10 https://github.com/sphincs/sphincsplus 11 12 However, this implementation is unfortuately *not* compatible with 13 FIPS.205. See page 1--2 in FIPS.205 for a general description. It is 14 also described below. 15 16 ## On differences between FIPS.205 and SPHINCS+ 17 18 There is a difference in how the bits are ordered when extracting a 19 sequence of bits (that is used to derive indices that we need in 20 `fors_sign`, for example). 21 22 FIPS.205 orders the bits from higher to lower order, so that the bit 23 sequence 24 25 b₀, b₁, b₂, ..., bₙ 26 27 is represented as bytes such that b₀ is the most significant bit of the 28 first byte, and b₇ is the least significant bit of the last byte. This 29 means that the first byte has value 30 31 b₀ 2⁷ + b₁ 2⁶ + ... + b₇, 32 33 the second byte has value 34 35 b₈ 2⁷ + b₉ 2⁶ + ... + b₁₅, 36 37 and so on. 38 39 In comparison, the SPHINCS+ specification (and reference implementation) 40 considers the least significant bit in each byte to be the first. This 41 means that the bit sequence 42 43 b₀, b₁, b₂, ..., bₙ 44 45 is representated as bytes in such a way that the first byte has value 46 47 b₇ 2⁷ + b₆ 2⁶ + ... + b₀ 48 49 and the second byte has value 50 51 b₁₅ 2⁷ + b₁₄ 2⁶ + ... + b₈. 52 53 Assuming that there is no other suble differences in this, I've done a 54 quick hack to get some test vectors to compare with. In `fors.c` we 55 replace the code block 56 57 static void message_to_indices(uint32_t *indices, const unsigned char *m) 58 { 59 unsigned int i, j; 60 unsigned int offset = 0; 61 62 for (i = 0; i < SPX_FORS_TREES; i++) { 63 indices[i] = 0; 64 for (j = 0; j < SPX_FORS_HEIGHT; j++) { 65 indices[i] ^= ((m[offset >> 3] >> (offset & 0x7)) & 1u) << j; 66 offset++; 67 } 68 } 69 } 70 71 with the code block 72 73 static void message_to_indices(uint32_t *indices, const unsigned char *m) 74 { 75 unsigned int i, j; 76 unsigned int offset = 0; 77 78 for (i = 0; i < SPX_FORS_TREES; i++) { 79 indices[i] = 0; 80 for (j = 0; j < SPX_FORS_HEIGHT; j++) { 81 indices[i] ^= ((m[offset >> 3] >> (7-(offset & 0x7))) & 1u) << (SPX_FORS_HEIGHT-1-j); 82 offset++; 83 } 84 } 85 } 86 87 So, suddenly my this _independent_ reference implementation is no longer 88 independent, because I just had to put my hacky fingers in it. 89 90 ## Build instructions 91 92 Clone the sphincsplus repo and apply the patch: 93 94 ```console 95 $ git clone https://github.com/sphincs/sphincsplus.git 96 $ cd sphincsplus 97 $ git checkout 035b39429d96ca554402b78f296f0de181674abd 98 $ cd ref/ 99 $ patch -R -p1 < ../../sphincsplus_ref.patch 100 ``` 101 102 Compile the test vector generator: 103 104 ```console 105 $ sphincs/src 106 $ make 107 ``` 108 109 ## Example usage instructions 110 111 Generate a test vector JSON file for parameter set 112 `SLH-DSA-SHAKE-128s`: 113 114 ```console 115 $ ./build/shake_128s_gen 116 ```