International Association for Cryptologic Research

International Association
for Cryptologic Research

Transactions on Cryptographic Hardware and Embedded Systems 2026

A Tool for Lightweight (AND, XOR) Implementations of Large-Degree S-boxes


README

implem-sbox

A tool for finding good side-channel-protected circuits implementing small functions (cryptographic S-box).

This tool and its purpose are described in more detailed in the TCHES article (link will be provided soon). A file containing the look-up-tables of all the S-boxes studied in the article is given in list_of_test_luts.txt.

Required Tools

To build and run this program, ensure the following tools are installed:

The build process uses OpenMP for parallelization. Ensure your compiler supports it.

We give instructions for linux-based distribution, we expect it should work for windows also.

Install instructions

Then, download the precomputation files. It may take up to a few hours to download the complete dataset, but you may download only files for a specific S-box size.

-Option 1: Download all precomputation files (total size ~50GB): wget -r -np -nH --cut-dirs=1 -A txt https://caramba.loria.fr/sbox/precomputation_files/

-Option 2: Download files for a specific S-box size (replace n_bits with the desired size, e.g., 5_bits): wget -r -np -nH --cut-dirs=1 -A txt https://caramba.loria.fr/sbox/precomputation_files/5_bits/

-Special Case for 6 bits: If your function has degree 5, you must download both the 6_bits folder and the additional 6_bits_degree_5 folder : wget -r -np -nH --cut-dirs=1 -A txt https://caramba.loria.fr/sbox/precomputation_files/6_bits_degree_5/

4_bits: ~18.2 KB

5_bits: ~0.9 MB

6_bits: ~446 MB

6_bits_degree_5: ~47.5 GB

7_bits: ~2.1 GB

-Option 3: If you do not have a complete wget, you can access the url https://caramba.loria.fr/sbox/precomputation_files/ and download files manually. They should be put into a new directory called 'precomputation_files' inside the 'Code' directory.

Program manual

Example execution

This execution gives an implementation of the S-box corresponding to the inverse of the Q2256 representative (6 bits, degree 3), with at most 15 AND gates. This should run around 30 seconds on a laptop (in some unlucky cases, it may take a few minutes).

./implem --lut 0,1,2,3,4,7,5,6,8,16,32,58,9,19,61,37,10,17,50,43,11,18,45,54,41,52,63,34,47,48,56,39,12,29,62,49,53,57,31,13,20,27,55,36,51,33,23,25,59,42,24,21,26,22,60,44,30,14,40,38,35,46,15,28 --andmax 15 -s 1
ANF is given by :
y0 = x0 ^ x1x2 ^ x0x3 ^ x2x3 ^ x1x2x3 ^ x2x4 ^ x1x2x4 ^ x3x4 ^ x0x3x4 ^ x2x5 ^ x0x2x5 ^ x1x2x5 ^ x0x3x5 ^ x1x3x5 ^ x2x3x5 ^ x4x5 ^ x1x4x5 ^ x2x4x5
y1 = x1 ^ x0x2 ^ x1x2 ^ x1x3 ^ x0x1x3 ^ x1x2x3 ^ x4 ^ x0x4 ^ x1x4 ^ x0x1x4 ^ x3x4 ^ x0x3x4 ^ x2x3x4 ^ x0x1x5 ^ x0x2x5 ^ x1x2x5 ^ x0x3x5 ^ x1x3x5 ^ x2x3x5 ^ x0x4x5 ^ x1x4x5 ^ x3x4x5
y2 = x2 ^ x2x3 ^ x1x2x3 ^ x2x4 ^ x1x2x4 ^ x0x3x4 ^ x1x3x4 ^ x5 ^ x0x1x5 ^ x2x5 ^ x0x2x5 ^ x0x3x5 ^ x4x5 ^ x2x4x5 ^ x3x4x5
y3 = x3 ^ x0x3 ^ x1x3 ^ x1x2x3 ^ x4 ^ x0x4 ^ x1x4 ^ x1x2x4 ^ x3x4 ^ x0x3x4 ^ x5 ^ x0x1x5 ^ x2x5 ^ x0x2x5 ^ x1x2x5 ^ x1x3x5 ^ x2x3x5 ^ x4x5 ^ x0x4x5 ^ x1x4x5 ^ x2x4x5
y4 = x0x3 ^ x1x2x3 ^ x0x4 ^ x1x4 ^ x1x2x4 ^ x0x3x4 ^ x0x5 ^ x1x5 ^ x0x1x5 ^ x2x5 ^ x0x2x5 ^ x1x2x5 ^ x3x5 ^ x1x3x5 ^ x2x3x5 ^ x4x5 ^ x0x4x5 ^ x2x4x5 ^ x3x4x5
y5 = x1x3 ^ x1x4 ^ x3x4 ^ x1x5 ^ x2x5 ^ x1x3x5 ^ x4x5 ^ x1x4x5
The given s-box can be implemented by :

uint32_t Sbox(uint32_t X, uint8_t size) {
	uint32_t x[size];
	for(uint8_t b=0; b<size; b++)  {
		x[b] = X&1ul;
		X >>= 1;
	}
	uint32_t y[size];
	uint32_t l2 = x[5];
	uint32_t l3 = x[3] ^ x[4];
	uint32_t l0 = x[5] ^ l3;
	uint32_t l4 = x[2] ^ x[4];
	uint32_t l5 = x[2];
	uint32_t l6 = x[1] ^ x[4];
	uint32_t l1 = x[5] ^ l6;
	uint32_t l7 = x[4] ^ x[5];
	uint32_t l8 = l6 ^ l7;
	uint32_t l9 = x[0] ^ x[2];
	uint32_t l10 = x[0] ^ l1;
	uint32_t l11 = x[2] ^ l6;
	uint32_t l13 = x[2] ^ l0;
	uint32_t l14 = x[4] ^ l10;
	uint32_t l15 = l10 ^ l13;
	uint32_t l16 = l9 ^ l10;
	uint32_t l17 = l9 ^ l14;
	uint32_t l12 = 1 ^ l17;
	uint32_t q0 = x[4] & x[5];
	uint32_t q1 = l2 & l3;
	uint32_t q2 = l2 & l4;
	uint32_t q3 = l5 & l0;
	uint32_t q4 = l6 & l7 ^ x[4];
	uint32_t q5 = l5 & l8;
	uint32_t q6 = x[0] & x[5];
	uint32_t q7 = x[0] & x[4];
	uint32_t q8 = l9 & l3;
	uint32_t q9 = q1 ^ q3;
	uint32_t q16 = q0 ^ q8;
	uint32_t q17 = q2 ^ q8;
	uint32_t tq0 = q0 ^ q6;
	uint32_t q10 = q2 ^ tq0;
	uint32_t q11 = q3 ^ q10;
	uint32_t q12 = q9 ^ q10;
	uint32_t q13 = q7 ^ tq0;
	uint32_t q14 = q4 ^ q13;
	uint32_t q15 = q5 ^ q13;
	uint32_t q18 = q17 ^ tq0;
	uint32_t q19 = q1 ^ q18;
	uint32_t ty3 = ((q4) ^ (x[3])) & ((q15) ^ (l10)) ^ (q14);
	uint32_t ty4 = ((q19) ^ (l11)) & ((q12) ^ (l12)) ^ (q10);
	uint32_t ty0 = ((q16) ^ (l5)) & ((l1)) ^ (q18);
	uint32_t ty1 = ty4 ^ ((q0) ^ (l13)) & ((q6) ^ (l14)) ^ (q7);
	uint32_t ty5 = ((q1) ^ (l0)) & ((l15)) ^ (q17);
	uint32_t ty2 = ((q19) ^ (l16)) & ((q11) ^ (l17)) ^ (q10);
	y[3] = ty3 ^ l0;
	y[4] = ty4 ^ x[4];
	y[0] = ty0 ^ x[0];
	y[1] = ty1 ^ l1;
	y[5] = ty5 ^ x[3];
	y[2] = ty2 ^ x[1];
	uint32_t Y = 0;
	for(uint8_t b=0; b<size; b++) {
		Y ^= ((Y>>b) ^ y[b]) << b;
	}
	return Y;
}
Nb_and = 15
Nb_xor = 52

Expected timings

Degree 4 on 6 bits takes half an hour, degree 5 on 6 bits takes around a day, degree 3 on 7 bits takes few hours, all other results are obtained within seconds on a laptop.