This repository contains an experimental implementation of the syzygy distinguisher presented in https://eprint.iacr.org/2024/1193 (see https://github.com/randriam/syzygies for legacy magma code).
We are interested in computing wether a Betti number of the linear strand (
To do so, we build a matrix whose kernel is the
Where :
-
$\mathbb K= \mathbf{GF}(2)$ -
$\mathcal{S}=\mathbb K[x_0, \ldots ,x_k]$ -
$\mathcal{S_1}=\langle x_0, \ldots ,x_k \rangle$ , the$\mathbb K$ -vector space generated by monomials of degree 1 -
$\mathcal{C}$ is a binary code of dimension$k$ and length$n$ such that$\mathcal{C}^{\langle 2 \rangle} = \mathbb K^n$ -
$r$ is where we expect to distinguish
The procedure is as follows:
- First, we compute the matrix of
$d'$ on a basis of a complement of$\mathrm{im}(d)$ . The basis we take is:
-
Then, we run block Wiedemann algorithm, if we find a non trivial vector then
$\beta_{r,r+1} > 0$ and if we don't find a vector then with high probability$\beta_{r,r+1} = 0$ -
The matrix construction is done in python using
numpyandnumbain order to get good performances. -
The block Wiedemann part is done in C/C++ using
cado-nfs/linalg/bwchighly efficient module.
-
Clone the repository with
cado-nfs(submodule):git clone --recurse-submodules https://github.com/piperrier/dyztynguysher.git
-
Compile
cado-nfs:cd cado-nfs; make
-
Add
cado-nfsto your path, we will usecado-nfs/linalg/bwcmodule:export PATH="$PATH:/<cado-dir>/build/<hostname>/linalg/bwc"
-
Create a python env with: sage<=10.6, python>=3.12, numpy<=2.2, numba<=0.61 We provide an
environment.ymlfile, with a conda environement calledsyz.conda env create -f environment.yml # Create the syz environment from file conda activate syz # Activate syz environment
-
From the
dyztynguysherdirectory, activate the env and start a sage interpreter:conda activate syz sage
-
To see the doc of the class and get an overview of the project:
load("syz.py") help(Instance)
-
On the sage interpreter, load
syz.py:load("syz.py")
-
Create an instance:
# Default idir = <dyztynguysher_dir>/instance # Default wdir = /tmp/wdir h48 = Instance("hamming", 15, 11, 8, "128", "64", "2x2", idir="/nvme/user/instance", wdir="/nvme/user/wdir") C = codes.HammingCode(GF(2),4) G = C.generator_matrix() G = id_on_left(G) # ensure that the generator matrix of the code is identity on the left h48.set_code_matrix(G) print(h48) # Print instance information
-
Run the distinguisher with the conditioning of your choice:
RAWRAWPADREDREDPAD
h48.construct_and_write_matrix(ConditioningType.RAWPAD) h48.run(ConditioningType.RAWPAD) h48.check_solution(ConditioningType.RAWPAD)
-
Create an instance and write it a bin:
h48 = Instance("hamming", 15, 11, 8, "128", "64", "2x2") C = codes.HammingCode(GF(2),4) G = C.generator_matrix() h48.set_code_matrix(G) h48.construct_and_write_matrix(ConditioningType.RAWPAD)
-
Draw it:
h48.pretty(ConditioningType.RED, dpi = 400)
-
Create an instance and write/collect it:
h48 = Instance("hamming", 15, 11, 8, "128", "64", "2x2", idir="/nvme/user/instance", wdir="/nvme/user/wdir") C = codes.HammingCode(GF(2),4) G = C.generator_matrix() h48.set_code_matrix(G) h48.construct_and_write_matrix(ConditioningType.RAWPAD) #h48.construct_and_collect_matrix(ConditioningType.RAWPAD) # h48.S is a ndarray of uint32-ndarray
-
Use the
sage_from_bin(path, name, nrows, ncols)ormatrix_to_sage(matrix, nrows, cols)to get a sage matrix:nrows, ncols = RawPad.get_dim(h48.nrows, h48.ncols) matrix = sage_from_bin("Srawpad", h48.idir, nrows, ncols) #matrix = matrix_to_sage(h48.S, nrows, ncols)
-
Create a class in
conditioning.py -
Fix all the case
match/caseinsyz.py
References for Block wiedemann:
Complexity:
-
krylov+mksol:$(1 + n/m + w/n) \times N$ matrix-times-vector products, where w = 64 when working over GF(2) on a 64 bits processor -
lingen:$(m+n) \times Nlog(N) \times (m + n + log(N))$
Probability of success:
- The matrix shouldn't have a non-zero eigenvalue of high multiplicity
-
RAW:
Construct the whole rectangular matrix ($nrows<ncols$ ).$nrows = k \binom{k}{r} - \binom{k}{r+1}$ $ncols = n \binom{k}{r-1}$ -
RAWPAD:
Construct the whole rectangular matrix and pad with random rows to obtain a square matrix.
With a great probability the random row wont change the kernel of the matrix.$nrows = ncols = n \binom{k}{r-1}$ -
RED: Construct the whole reduced matrixWe delete
$r \binom{k}{r}$ rows that have obvious pivots and$k\binom{k}{r-1}$ columns that are all zero.$nrows = k \binom{k}{r} - \binom{k}{r+1} - r \binom{k}{r}$ $ncols = n \binom{k}{r-1} - k\binom{k}{r-1}$ -
REDPAD:
Construct the whole reduced matrix and pad with random rows to obtain a square matrix.
With a great probability the random row wont change the kernel of the matrix.$nrows = ncols = n \binom{k}{r-1} - k\binom{k}{r-1}$
Reduction ratio:
-
We delete
$\frac{k}{n}$ of the columns -
We delete
$\frac{r}{k}\times\frac{1}{1-1/r}$ of the rows
- Multithreading when constructing the matrix
- Improve theoretical matrix reduction before construction
- Use
MPIoption ofcado-nfsto run block Wiedemann on multiple computers and reach harder instances:- more cpu
- amortize the high memory cost (
lingen: fft → 5 times input size)
- Refactor conditioning
- Take advantage of the recursive structure of the cohomology matrix
- Black box, don't construct the matrix