add proof of equivalence PoC
This commit is contained in:
parent
7baa1caf77
commit
ba564a3f38
|
@ -0,0 +1,949 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 3,
|
||||||
|
"id": "50885b34",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"# BLS12-381 Base field\n",
|
||||||
|
"BLS12_381_BASEFIELD = 0x1a0111ea397fe69a4b1ba7b6434bacd764774b84f38512bf6730d2a0f6b0f6241eabfffeb153ffffb9feffffffffaaab\n",
|
||||||
|
"# BLS12-381 Scalar field\n",
|
||||||
|
"BLS12_381_SCALARFIELD = 0x73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001\n",
|
||||||
|
"\n",
|
||||||
|
"# BLS12-377 Base field = BW6_761 Scalar field\n",
|
||||||
|
"BLS12_377_BASEFIELD = 0x1ae3a4617c510eac63b05c06ca1493b1a22d9f300f5138f1ef3622fba094800170b5d44300000008508c00000000001\n",
|
||||||
|
"# BLS12-377 Scalar field = Ed_on_bls_12_377 Base field\n",
|
||||||
|
"BLS12_377_SCALARFIELD = 0x12ab655e9a2ca55660b44d1e5c37b00159aa76fed00000010a11800000000001\n",
|
||||||
|
"\n",
|
||||||
|
"# BN-254 Base field\n",
|
||||||
|
"BN_254_BASEFIELD = 0x30644e72e131a029b85045b68181585d97816a916871ca8d3c208c16d87cfd47\n",
|
||||||
|
"# BN-254 Scalar field\n",
|
||||||
|
"BN_254_SCALARFIELD = 0x30644e72e131a029b85045b68181585d2833e84879b9709143e1f593f0000001\n",
|
||||||
|
"\n",
|
||||||
|
"# Pallas Base field = Vesta Scalar field\n",
|
||||||
|
"PALLAS_BASEFIELD = 0x40000000000000000000000000000000224698fc094cf91b992d30ed00000001\n",
|
||||||
|
"\n",
|
||||||
|
"# Vesta Base field = Pallas Scalar field\n",
|
||||||
|
"VESTA_BASEFIELD = 0x40000000000000000000000000000000224698fc0994a8dd8c46eb2100000001\n",
|
||||||
|
"\n",
|
||||||
|
"# Small Goldilocks field\n",
|
||||||
|
"GOLDILOCKS_64_FIELD = 0xffffffff00000001"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "23180928",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "c309f191",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"from sage.all import *\n",
|
||||||
|
"import hashlib\n",
|
||||||
|
"import itertools\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"COST_ALPHA = {\n",
|
||||||
|
" 3 : 2, 5 : 3, 7 : 4, 9 : 4,\n",
|
||||||
|
" 11 : 5, 13 : 5, 15 : 5, 17 : 5,\n",
|
||||||
|
" 19 : 6, 21 : 6, 23 : 6, 25 : 6,\n",
|
||||||
|
" 27 : 6, 29 : 7, 31 : 7, 33 : 6,\n",
|
||||||
|
" 35 : 7, 37 : 7, 39 : 7, 41 : 7,\n",
|
||||||
|
" 43 : 7, 45 : 7, 47 : 8, 49 : 7,\n",
|
||||||
|
" 51 : 7, 53 : 8, 55 : 8, 57 : 8,\n",
|
||||||
|
" 59 : 8, 61 : 8, 63 : 8, 65 : 7,\n",
|
||||||
|
" 67 : 8, 69 : 8, 71 : 9, 73 : 8,\n",
|
||||||
|
" 75 : 8, 77 : 8, 79 : 9, 81 : 8,\n",
|
||||||
|
" 83 : 8, 85 : 8, 87 : 9, 89 : 9,\n",
|
||||||
|
" 91 : 9, 93 : 9, 95 : 9, 97 : 8,\n",
|
||||||
|
" 99 : 8, 101 : 9, 103 : 9, 105 : 9,\n",
|
||||||
|
" 107 : 9, 109 : 9, 111 : 9, 113 : 9,\n",
|
||||||
|
" 115 : 9, 117 : 9, 119 : 9, 121 : 9,\n",
|
||||||
|
" 123 : 9, 125 : 9, 127 : 10,\n",
|
||||||
|
"}\n",
|
||||||
|
"\n",
|
||||||
|
"ALPHA_BY_COST = {\n",
|
||||||
|
" c : [x for x in range(3, 128, 2) if COST_ALPHA[x] == c]\n",
|
||||||
|
" for c in range(2, 11)\n",
|
||||||
|
"}\n",
|
||||||
|
"\n",
|
||||||
|
"PI_0 = 1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679\n",
|
||||||
|
"PI_1 = 8214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196\n",
|
||||||
|
"\n",
|
||||||
|
"def get_prime(N):\n",
|
||||||
|
" result = (1 << N) - 1\n",
|
||||||
|
" while not is_prime(result):\n",
|
||||||
|
" result -= 2\n",
|
||||||
|
" return result\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"def get_n_rounds(s, l, alpha):\n",
|
||||||
|
" r = 0\n",
|
||||||
|
" complexity = 0\n",
|
||||||
|
" kappa = {3:1, 5:2, 7:4, 9:7, 11:9}\n",
|
||||||
|
" assert alpha in kappa\n",
|
||||||
|
" while complexity < 2**s:\n",
|
||||||
|
" r += 1\n",
|
||||||
|
" complexity = binomial(\n",
|
||||||
|
" 4*l*r + kappa[alpha],\n",
|
||||||
|
" 2*l*r\n",
|
||||||
|
" )**2\n",
|
||||||
|
" r += 2 # considering the second model\n",
|
||||||
|
" r += min(5,l+1) # security margin\n",
|
||||||
|
" \n",
|
||||||
|
" return max(8, r)\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"# Linear layer generation\n",
|
||||||
|
"\n",
|
||||||
|
"def is_mds(m):\n",
|
||||||
|
" # Uses the Laplace expansion of the determinant to calculate the (m+1)x(m+1) minors in terms of the mxm minors.\n",
|
||||||
|
" # Taken from https://github.com/mir-protocol/hash-constants/blob/master/mds_search.sage.\n",
|
||||||
|
"\n",
|
||||||
|
" # 1-minors are just the elements themselves\n",
|
||||||
|
" if any(any(r == 0 for r in row) for row in m):\n",
|
||||||
|
" return False\n",
|
||||||
|
"\n",
|
||||||
|
" N = m.nrows()\n",
|
||||||
|
" assert m.is_square() and N >= 2\n",
|
||||||
|
"\n",
|
||||||
|
" det_cache = m\n",
|
||||||
|
"\n",
|
||||||
|
" # Calculate all the nxn minors of m:\n",
|
||||||
|
" for n in range(2, N+1):\n",
|
||||||
|
" new_det_cache = dict()\n",
|
||||||
|
" for rows in itertools.combinations(range(N), n):\n",
|
||||||
|
" for cols in itertools.combinations(range(N), n):\n",
|
||||||
|
" i, *rs = rows\n",
|
||||||
|
"\n",
|
||||||
|
" # Laplace expansion along row i\n",
|
||||||
|
" det = 0\n",
|
||||||
|
" for j in range(n):\n",
|
||||||
|
" # pick out c = column j; the remaining columns are in cs\n",
|
||||||
|
" c = cols[j]\n",
|
||||||
|
" cs = cols[:j] + cols[j+1:]\n",
|
||||||
|
"\n",
|
||||||
|
" # Look up the determinant from the previous iteration\n",
|
||||||
|
" # and multiply by -1 if j is odd\n",
|
||||||
|
" cofactor = det_cache[(*rs, *cs)]\n",
|
||||||
|
" if j % 2 == 1:\n",
|
||||||
|
" cofactor = -cofactor\n",
|
||||||
|
"\n",
|
||||||
|
" # update the determinant with the j-th term\n",
|
||||||
|
" det += m[i, c] * cofactor\n",
|
||||||
|
"\n",
|
||||||
|
" if det == 0:\n",
|
||||||
|
" return False\n",
|
||||||
|
" new_det_cache[(*rows, *cols)] = det\n",
|
||||||
|
" det_cache = new_det_cache\n",
|
||||||
|
" return True\n",
|
||||||
|
"\n",
|
||||||
|
"def M_2(x_input, b):\n",
|
||||||
|
" x = x_input[:]\n",
|
||||||
|
" x[0] += b*x[1]\n",
|
||||||
|
" x[1] += b*x[0]\n",
|
||||||
|
" return x\n",
|
||||||
|
"\n",
|
||||||
|
"def M_3(x_input, b):\n",
|
||||||
|
" x = x_input[:]\n",
|
||||||
|
" t = x[0] + b*x[2]\n",
|
||||||
|
" x[2] += x[1]\n",
|
||||||
|
" x[2] += b*x[0]\n",
|
||||||
|
" x[0] = t + x[2]\n",
|
||||||
|
" x[1] += t\n",
|
||||||
|
" return x\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"def M_4(x_input, b):\n",
|
||||||
|
" x = x_input[:]\n",
|
||||||
|
" x[0] += x[1]\n",
|
||||||
|
" x[2] += x[3]\n",
|
||||||
|
" x[3] += b*x[0]\n",
|
||||||
|
" x[1] = b*(x[1] + x[2])\n",
|
||||||
|
" x[0] += x[1]\n",
|
||||||
|
" x[2] += b*x[3]\n",
|
||||||
|
" x[1] += x[2]\n",
|
||||||
|
" x[3] += x[0]\n",
|
||||||
|
" return x\n",
|
||||||
|
"\n",
|
||||||
|
"def lfsr(x_input, b):\n",
|
||||||
|
" x = x_input[:]\n",
|
||||||
|
" l = len(x)\n",
|
||||||
|
" for r in range(0, l):\n",
|
||||||
|
" t = sum(b**(2**i) * x[i] for i in range(0, l))\n",
|
||||||
|
" x = x[1:] + [t]\n",
|
||||||
|
" return x\n",
|
||||||
|
"\n",
|
||||||
|
"def circulant_mds_matrix(field, l, coeff_upper_limit=None):\n",
|
||||||
|
" if coeff_upper_limit == None:\n",
|
||||||
|
" coeff_upper_limit = l+1\n",
|
||||||
|
" assert(coeff_upper_limit > l)\n",
|
||||||
|
" for v in itertools.combinations_with_replacement(range(1,coeff_upper_limit), l):\n",
|
||||||
|
" mat = matrix.circulant(list(v)).change_ring(field)\n",
|
||||||
|
" if is_mds(mat):\n",
|
||||||
|
" return(mat)\n",
|
||||||
|
" # In some cases, the method won't return any valid matrix,\n",
|
||||||
|
" # hence the need to increase the limit further.\n",
|
||||||
|
" return circulant_mds_matrix(field, l, coeff_upper_limit+1)\n",
|
||||||
|
"\n",
|
||||||
|
"def get_mds(field, l):\n",
|
||||||
|
" if l == 1:\n",
|
||||||
|
" return identity_matrix(field, 1)\n",
|
||||||
|
" if l <= 4: # low addition case\n",
|
||||||
|
" a = field.multiplicative_generator()\n",
|
||||||
|
" b = field.one()\n",
|
||||||
|
" t = 0\n",
|
||||||
|
" while True:\n",
|
||||||
|
" # we construct the matrix\n",
|
||||||
|
" mat = []\n",
|
||||||
|
" b = b*a\n",
|
||||||
|
" t += 1\n",
|
||||||
|
" for i in range(0, l):\n",
|
||||||
|
" x_i = [field.one() * (j == i) for j in range(0, l)]\n",
|
||||||
|
" if l == 2:\n",
|
||||||
|
" mat.append(M_2(x_i, b))\n",
|
||||||
|
" elif l == 3:\n",
|
||||||
|
" mat.append(M_3(x_i, b))\n",
|
||||||
|
" elif l == 4:\n",
|
||||||
|
" mat.append(M_4(x_i, b))\n",
|
||||||
|
" mat = Matrix(field, l, l, mat).transpose()\n",
|
||||||
|
" if is_mds(mat):\n",
|
||||||
|
" return mat\n",
|
||||||
|
" else: # circulant matrix case\n",
|
||||||
|
" return circulant_mds_matrix(field, l)\n",
|
||||||
|
"\n",
|
||||||
|
"# AnemoiPermutation class\n",
|
||||||
|
"\n",
|
||||||
|
"class AnemoiPermutation:\n",
|
||||||
|
" def __init__(self,\n",
|
||||||
|
" q=None,\n",
|
||||||
|
" alpha=None,\n",
|
||||||
|
" mat=None,\n",
|
||||||
|
" n_rounds=None,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" security_level=128):\n",
|
||||||
|
" if q == None:\n",
|
||||||
|
" raise Exception(\"The characteristic of the field must be specified!\")\n",
|
||||||
|
" self.q = q\n",
|
||||||
|
" self.prime_field = is_prime(q) # if true then we work over a\n",
|
||||||
|
" # prime field with\n",
|
||||||
|
" # characteristic just under\n",
|
||||||
|
" # 2**N, otherwise the\n",
|
||||||
|
" # characteristic is 2**self\n",
|
||||||
|
" self.n_cols = n_cols # the number of parallel S-boxes in each round\n",
|
||||||
|
" self.security_level = security_level\n",
|
||||||
|
"\n",
|
||||||
|
" # initializing the other variables in the state:\n",
|
||||||
|
" # - q is the characteristic of the field\n",
|
||||||
|
" # - g is a generator of the multiplicative subgroup\n",
|
||||||
|
" # - alpha is the main exponent (in the center of the Flystel)\n",
|
||||||
|
" # - beta is the coefficient in the quadratic subfunction\n",
|
||||||
|
" # - gamma is the constant in the second quadratic subfunction\n",
|
||||||
|
" # - QUAD is the secondary (quadratic) exponent\n",
|
||||||
|
" # - from_field is a function mapping field elements to integers\n",
|
||||||
|
" # - to_field is a function mapping integers to field elements\n",
|
||||||
|
" self.F = GF(self.q)\n",
|
||||||
|
" if self.prime_field:\n",
|
||||||
|
" if alpha != None:\n",
|
||||||
|
" if gcd(alpha, self.q-1) != 1:\n",
|
||||||
|
" raise Exception(\"alpha should be co-prime with the characteristic!\")\n",
|
||||||
|
" else:\n",
|
||||||
|
" self.alpha = alpha\n",
|
||||||
|
" else:\n",
|
||||||
|
" self.alpha = 3\n",
|
||||||
|
" while gcd(self.alpha, self.q-1) != 1:\n",
|
||||||
|
" self.alpha += 1\n",
|
||||||
|
" self.QUAD = 2\n",
|
||||||
|
" self.to_field = lambda x : self.F(x)\n",
|
||||||
|
" self.from_field = lambda x : Integer(x)\n",
|
||||||
|
" else:\n",
|
||||||
|
" self.alpha = 3\n",
|
||||||
|
" self.QUAD = 3\n",
|
||||||
|
" self.to_field = lambda x : self.F.fetch_int(x)\n",
|
||||||
|
" self.from_field = lambda x : x.integer_representation()\n",
|
||||||
|
" self.g = self.F.multiplicative_generator()\n",
|
||||||
|
" self.beta = self.g\n",
|
||||||
|
" self.delta = self.g**(-1)\n",
|
||||||
|
" self.alpha_inv = inverse_mod(self.alpha, self.q-1)\n",
|
||||||
|
"\n",
|
||||||
|
" # total number of rounds\n",
|
||||||
|
" if n_rounds != None:\n",
|
||||||
|
" self.n_rounds = n_rounds\n",
|
||||||
|
" else:\n",
|
||||||
|
" self.n_rounds = get_n_rounds(self.security_level,\n",
|
||||||
|
" self.n_cols,\n",
|
||||||
|
" self.alpha)\n",
|
||||||
|
"\n",
|
||||||
|
" # Choosing constants: self.C and self.D are built from the\n",
|
||||||
|
" # digits of pi using an open butterfly\n",
|
||||||
|
" self.C = []\n",
|
||||||
|
" self.D = []\n",
|
||||||
|
" pi_F_0 = self.to_field(PI_0 % self.q)\n",
|
||||||
|
" pi_F_1 = self.to_field(PI_1 % self.q)\n",
|
||||||
|
" for r in range(0, self.n_rounds):\n",
|
||||||
|
" pi_0_r = pi_F_0**r\n",
|
||||||
|
" self.C.append([])\n",
|
||||||
|
" self.D.append([])\n",
|
||||||
|
" for i in range(0, self.n_cols):\n",
|
||||||
|
" pi_1_i = pi_F_1**i\n",
|
||||||
|
" pow_alpha = (pi_0_r + pi_1_i)**self.alpha\n",
|
||||||
|
" self.C[r].append(self.g * (pi_0_r)**2 + pow_alpha)\n",
|
||||||
|
" self.D[r].append(self.g * (pi_1_i)**2 + pow_alpha + self.delta)\n",
|
||||||
|
" self.mat = get_mds(self.F, self.n_cols)\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
" def __str__(self):\n",
|
||||||
|
" result = \"Anemoi instance over F_{:d} ({}), n_rounds={:d}, n_cols={:d}, s={:d}\".format(\n",
|
||||||
|
" self.q,\n",
|
||||||
|
" \"odd prime field\" if self.prime_field else \"characteristic 2\",\n",
|
||||||
|
" self.n_rounds,\n",
|
||||||
|
" self.n_cols,\n",
|
||||||
|
" self.security_level\n",
|
||||||
|
" )\n",
|
||||||
|
" result += \"\\nalpha={}, beta={}, \\ndelta={}\\nM_x=\\n{}\\ninv_alpha={}\\n\".format(\n",
|
||||||
|
" self.alpha,\n",
|
||||||
|
" self.beta,\n",
|
||||||
|
" self.delta,\n",
|
||||||
|
" self.mat,\n",
|
||||||
|
" self.alpha_inv\n",
|
||||||
|
" )\n",
|
||||||
|
" result += \"C={}\\nD={}\".format(\n",
|
||||||
|
" [[self.from_field(x) for x in self.C[r]] for r in range(0, self.n_rounds)],\n",
|
||||||
|
" [[self.from_field(x) for x in self.D[r]] for r in range(0, self.n_rounds)],\n",
|
||||||
|
" )\n",
|
||||||
|
" return result\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
" # !SECTION! Sub-components\n",
|
||||||
|
"\n",
|
||||||
|
" def evaluate_sbox(self, _x, _y):\n",
|
||||||
|
" x, y = _x, _y\n",
|
||||||
|
" x -= self.beta*y**self.QUAD\n",
|
||||||
|
" y -= x**self.alpha_inv\n",
|
||||||
|
" x += self.beta*y**self.QUAD + self.delta\n",
|
||||||
|
" return x, y\n",
|
||||||
|
"\n",
|
||||||
|
" def linear_layer(self, _x, _y):\n",
|
||||||
|
" x, y = _x[:], _y[:]\n",
|
||||||
|
" x = self.mat*vector(x)\n",
|
||||||
|
" y = self.mat*vector(y[1:] + [y[0]])\n",
|
||||||
|
"\n",
|
||||||
|
" # Pseudo-Hadamard transform on each (x,y) pair\n",
|
||||||
|
" y += x\n",
|
||||||
|
" x += y\n",
|
||||||
|
" return list(x), list(y)\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
" # !SECTION! Evaluation\n",
|
||||||
|
"\n",
|
||||||
|
" def eval_with_intermediate_values(self, _x, _y):\n",
|
||||||
|
" x, y = _x[:], _y[:]\n",
|
||||||
|
" result = [[x[:], y[:]]]\n",
|
||||||
|
" for r in range(0, self.n_rounds):\n",
|
||||||
|
" for i in range(0, self.n_cols):\n",
|
||||||
|
" x[i] += self.C[r][i]\n",
|
||||||
|
" y[i] += self.D[r][i]\n",
|
||||||
|
" x, y = self.linear_layer(x, y)\n",
|
||||||
|
" for i in range(0, self.n_cols):\n",
|
||||||
|
" x[i], y[i] = self.evaluate_sbox(x[i], y[i])\n",
|
||||||
|
" result.append([x[:], y[:]])\n",
|
||||||
|
" # final call to the linear layer\n",
|
||||||
|
" x, y = self.linear_layer(x, y)\n",
|
||||||
|
" result.append([x[:], y[:]])\n",
|
||||||
|
" return result\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
" def input_size(self):\n",
|
||||||
|
" return 2*self.n_cols\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
" def __call__(self, _x):\n",
|
||||||
|
" if len(_x) != self.input_size():\n",
|
||||||
|
" raise Exception(\"wrong input size!\")\n",
|
||||||
|
" else:\n",
|
||||||
|
" x, y = _x[:self.n_cols], _x[self.n_cols:]\n",
|
||||||
|
" u, v = self.eval_with_intermediate_values(x, y)[-1]\n",
|
||||||
|
" return u + v # concatenation, not a sum\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
" # !SECTION! Writing full system of equations\n",
|
||||||
|
"\n",
|
||||||
|
" def get_polynomial_variables(self):\n",
|
||||||
|
" x_vars = []\n",
|
||||||
|
" y_vars = []\n",
|
||||||
|
" all_vars = []\n",
|
||||||
|
" for r in range(0, self.n_rounds+1):\n",
|
||||||
|
" x_vars.append([\"X{:02d}{:02d}\".format(r, i) for i in range(0, self.n_cols)])\n",
|
||||||
|
" y_vars.append([\"Y{:02d}{:02d}\".format(r, i) for i in range(0, self.n_cols)])\n",
|
||||||
|
" all_vars += x_vars[-1]\n",
|
||||||
|
" all_vars += y_vars[-1]\n",
|
||||||
|
" pol_ring = PolynomialRing(self.F, (self.n_rounds+1)*2*self.n_cols, all_vars)\n",
|
||||||
|
" pol_gens = pol_ring.gens()\n",
|
||||||
|
" result = {\"X\" : [], \"Y\" : []}\n",
|
||||||
|
" for r in range(0, self.n_rounds+1):\n",
|
||||||
|
" result[\"X\"].append([])\n",
|
||||||
|
" result[\"Y\"].append([])\n",
|
||||||
|
" for i in range(0, self.n_cols):\n",
|
||||||
|
" result[\"X\"][r].append(pol_gens[self.n_cols*2*r + i])\n",
|
||||||
|
" result[\"Y\"][r].append(pol_gens[self.n_cols*2*r + i + self.n_cols])\n",
|
||||||
|
" return result\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
" def verification_polynomials(self, pol_vars):\n",
|
||||||
|
" equations = []\n",
|
||||||
|
" for r in range(0, self.n_rounds):\n",
|
||||||
|
" # the outputs of the open flystel are the state variables x, y at round r+1\n",
|
||||||
|
" u = pol_vars[\"X\"][r+1]\n",
|
||||||
|
" v = pol_vars[\"Y\"][r+1]\n",
|
||||||
|
" # the inputs of the open flystel are the state variables\n",
|
||||||
|
" # x, y at round r after undergoing the constant addition\n",
|
||||||
|
" # and the linear layer\n",
|
||||||
|
" x, y = pol_vars[\"X\"][r], pol_vars[\"Y\"][r]\n",
|
||||||
|
" x = [x[i] + self.C[r][i] for i in range(0, self.n_cols)]\n",
|
||||||
|
" y = [y[i] + self.D[r][i] for i in range(0, self.n_cols)]\n",
|
||||||
|
" x, y = self.linear_layer(x, y)\n",
|
||||||
|
" for i in range(0, self.n_cols):\n",
|
||||||
|
" equations.append(\n",
|
||||||
|
" (y[i]-v[i])**self.alpha + self.beta*y[i]**self.QUAD - x[i]\n",
|
||||||
|
" )\n",
|
||||||
|
" equations.append(\n",
|
||||||
|
" (y[i]-v[i])**self.alpha + self.beta*v[i]**self.QUAD + self.delta - u[i]\n",
|
||||||
|
" )\n",
|
||||||
|
" return equations\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
" def print_verification_polynomials(self):\n",
|
||||||
|
" p_vars = self.get_polynomial_variables()\n",
|
||||||
|
" eqs = self.verification_polynomials(p_vars)\n",
|
||||||
|
" variables_string = \"\"\n",
|
||||||
|
" for r in range(0, self.n_rounds+1):\n",
|
||||||
|
" variables_string += str(p_vars[\"X\"][r])[1:-1] + \",\" + str(p_vars[\"Y\"][r])[1:-1] + \",\"\n",
|
||||||
|
" print(variables_string[:-1].replace(\" \", \"\"))\n",
|
||||||
|
" print(self.q)\n",
|
||||||
|
" for f in eqs:\n",
|
||||||
|
" print(f)\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"# !SECTION! Modes of operation\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"def jive(P, b, _x):\n",
|
||||||
|
" if b < 2:\n",
|
||||||
|
" raise Exception(\"b must be at least equal to 2\")\n",
|
||||||
|
" if P.input_size() % b != 0:\n",
|
||||||
|
" raise Exception(\"b must divide the input size!\")\n",
|
||||||
|
" c = P.input_size()/b # length of the compressed output\n",
|
||||||
|
" # Output size check: we allow the output size to be 3 bits shorter than\n",
|
||||||
|
" # the theoretical target, as commonly used finite fields usually have a\n",
|
||||||
|
" # characteristic size slightly under 2**256.\n",
|
||||||
|
" if c * P.F.cardinality().nbits() < 2 * P.security_level - 3:\n",
|
||||||
|
" raise Exception(f\"digest size is too small for the targeted security level!\")\n",
|
||||||
|
" x = _x[:]\n",
|
||||||
|
" u = P(x)\n",
|
||||||
|
" compressed = []\n",
|
||||||
|
" for i in range(0, c):\n",
|
||||||
|
" compressed.append(sum(x[i+c*j] + u[i+c*j]\n",
|
||||||
|
" for j in range(0, b)))\n",
|
||||||
|
" return compressed\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"def sponge_hash(P, r, h, _x):\n",
|
||||||
|
" x = _x[:]\n",
|
||||||
|
" if P.input_size() <= r:\n",
|
||||||
|
" raise Exception(\"rate must be strictly smaller than state size!\")\n",
|
||||||
|
" # Digest size and capacity check: we allow the digest size to be 3 bits\n",
|
||||||
|
" # shorter than the theoretical target, as commonly used finite fields\n",
|
||||||
|
" # usually have a characteristic size slightly under 2**256.\n",
|
||||||
|
" if h * P.F.cardinality().nbits() < 2 * P.security_level - 3:\n",
|
||||||
|
" raise Exception(f\"digest size is too small for the targeted security level!\")\n",
|
||||||
|
" capacity = P.input_size() - r\n",
|
||||||
|
" if capacity * P.F.cardinality().nbits() < 2 * P.security_level - 3:\n",
|
||||||
|
" raise Exception(f\"capacity is too small for the targeted security level!\")\n",
|
||||||
|
"\n",
|
||||||
|
" # message padding (and domain separator computation)\n",
|
||||||
|
" if len(x) % r == 0 and len(x) != 0:\n",
|
||||||
|
" sigma = 1\n",
|
||||||
|
" else:\n",
|
||||||
|
" sigma = 0\n",
|
||||||
|
" x += [1]\n",
|
||||||
|
" # if x is still not long enough, append 0s\n",
|
||||||
|
" if len(x) % r != 0:\n",
|
||||||
|
" x += (r - (len(x) % r))*[0]\n",
|
||||||
|
" padded_x = [[x[pos+i] for i in range(0, r)]\n",
|
||||||
|
" for pos in range(0, len(x), r)]\n",
|
||||||
|
" # absorption phase\n",
|
||||||
|
" internal_state = [0] * P.input_size()\n",
|
||||||
|
" for pos in range(0, len(padded_x)):\n",
|
||||||
|
" for i in range(0, r):\n",
|
||||||
|
" internal_state[i] += padded_x[pos][i]\n",
|
||||||
|
" internal_state = P(internal_state)\n",
|
||||||
|
" if pos == len(padded_x)-1:\n",
|
||||||
|
" # adding sigma if it is the last block\n",
|
||||||
|
" internal_state[-1] += sigma\n",
|
||||||
|
" # squeezing\n",
|
||||||
|
" digest = []\n",
|
||||||
|
" pos = 0\n",
|
||||||
|
" while len(digest) < h:\n",
|
||||||
|
" digest.append(internal_state[pos])\n",
|
||||||
|
" pos += 1\n",
|
||||||
|
" if pos == r:\n",
|
||||||
|
" pos = 0\n",
|
||||||
|
" internal_state = P(internal_state)\n",
|
||||||
|
" return digest\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"# !SECTION! Tests\n",
|
||||||
|
"\n",
|
||||||
|
"def check_polynomial_verification(n_tests=10, q=2**63, alpha=3, n_rounds=3, n_cols=1):\n",
|
||||||
|
" A = AnemoiPermutation(q=q, alpha=alpha, n_rounds=n_rounds, n_cols=n_cols)\n",
|
||||||
|
" # formal polynomial variables and equations\n",
|
||||||
|
" p_vars = A.get_polynomial_variables()\n",
|
||||||
|
" eqs = A.verification_polynomials(p_vars)\n",
|
||||||
|
" A.print_verification_polynomials()\n",
|
||||||
|
" # for n_tests random inputs, we check that the equations are\n",
|
||||||
|
" # coherent with the actual intermediate values\n",
|
||||||
|
" print(\"\\n ======== Verification:\")\n",
|
||||||
|
" print(A)\n",
|
||||||
|
" print(\"{} equations in {} variables.\".format(\n",
|
||||||
|
" len(eqs),\n",
|
||||||
|
" (A.n_rounds+1) * 2 * A.n_cols,\n",
|
||||||
|
" ))\n",
|
||||||
|
" for t in range(0, n_tests):\n",
|
||||||
|
" # generate random input\n",
|
||||||
|
" x = [A.to_field(randint(0, A.q - 1))\n",
|
||||||
|
" for i in range(0, A.n_cols)]\n",
|
||||||
|
" y = [A.to_field(randint(0, A.q - 1))\n",
|
||||||
|
" for i in range(0, A.n_cols)]\n",
|
||||||
|
" # generate intermediate values, formal polynomial variables,\n",
|
||||||
|
" # and equations\n",
|
||||||
|
" iv = A.eval_with_intermediate_values(x, y)\n",
|
||||||
|
" p_vars = A.get_polynomial_variables()\n",
|
||||||
|
" eqs = A.verification_polynomials(p_vars)\n",
|
||||||
|
" # obtain variable assignment from the actual evaluation\n",
|
||||||
|
" assignment = {}\n",
|
||||||
|
" for r in range(0, A.n_rounds+1):\n",
|
||||||
|
" for i in range(0, A.n_cols):\n",
|
||||||
|
" assignment[p_vars[\"X\"][r][i]] = iv[r][0][i]\n",
|
||||||
|
" assignment[p_vars[\"Y\"][r][i]] = iv[r][1][i]\n",
|
||||||
|
" # printing the value of the equations for the actual\n",
|
||||||
|
" # intermediate states\n",
|
||||||
|
" print(\"\\n--- \", t, \"(all values except the input should be 0)\")\n",
|
||||||
|
" print(\"input: \", x, y)\n",
|
||||||
|
" for r in range(0, A.n_rounds):\n",
|
||||||
|
" polynomial_values = [eqs[r*2*A.n_cols + i].subs(assignment)\n",
|
||||||
|
" for i in range(0, 2*A.n_cols)]\n",
|
||||||
|
" print(\"round {:3d}: {}\\n {}\".format(\n",
|
||||||
|
" r,\n",
|
||||||
|
" polynomial_values[0::2],\n",
|
||||||
|
" polynomial_values[1::2]\n",
|
||||||
|
" ))\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"def test_jive(n_tests=10,\n",
|
||||||
|
" q=2**63, alpha=3,\n",
|
||||||
|
" n_rounds=None,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" b=2,\n",
|
||||||
|
" security_level=32):\n",
|
||||||
|
" A = AnemoiPermutation(q=q, alpha=alpha, n_rounds=n_rounds, n_cols=n_cols, security_level=security_level)\n",
|
||||||
|
" print(A)\n",
|
||||||
|
" for t in range(0, n_tests):\n",
|
||||||
|
" # generate random input\n",
|
||||||
|
" x = [A.to_field(randint(0, A.q - 1))\n",
|
||||||
|
" for i in range(0, A.n_cols)]\n",
|
||||||
|
" y = [A.to_field(randint(0, A.q - 1))\n",
|
||||||
|
" for i in range(0, A.n_cols)]\n",
|
||||||
|
" print(\"x = {}\\ny = {}\\nAnemoiJive_{}(x,y) = {}\".format(\n",
|
||||||
|
" x,\n",
|
||||||
|
" y,\n",
|
||||||
|
" b,\n",
|
||||||
|
" jive(A, b, x + y)\n",
|
||||||
|
" ))\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"def test_sponge(n_tests=10,\n",
|
||||||
|
" q=2**63,\n",
|
||||||
|
" alpha=3,\n",
|
||||||
|
" n_rounds=None,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" b=2,\n",
|
||||||
|
" security_level=32):\n",
|
||||||
|
" A = AnemoiPermutation(q=q, alpha=alpha, n_rounds=n_rounds, n_cols=n_cols, security_level=security_level)\n",
|
||||||
|
" print(A)\n",
|
||||||
|
" for t in range(0, n_tests):\n",
|
||||||
|
" # generate random input of length t\n",
|
||||||
|
" x = [A.to_field(randint(0, A.q - 1))\n",
|
||||||
|
" for i in range(0, t)]\n",
|
||||||
|
" print(\"x = {}\\nAnemoiSponge(x) = {}\".format(\n",
|
||||||
|
" x,\n",
|
||||||
|
" sponge_hash(A, 2, 2, x)\n",
|
||||||
|
" ))\n",
|
||||||
|
"\n",
|
||||||
|
"def generate_test_vectors_jive(P, b, n):\n",
|
||||||
|
" assert n >= 4, \"The number of test vectors should be greater than 4.\"\n",
|
||||||
|
" m = hashlib.sha512(str(P).encode())\n",
|
||||||
|
" m.update(\"Jive test vectors\".encode())\n",
|
||||||
|
" m.update(f\"B={b}\".encode())\n",
|
||||||
|
" seed = Integer(m.digest().hex(), 16)\n",
|
||||||
|
"\n",
|
||||||
|
" inputs = []\n",
|
||||||
|
" outputs = []\n",
|
||||||
|
" inputs.append([P.F(0) for _ in range(P.input_size())])\n",
|
||||||
|
" inputs.append([P.F(1) for _ in range(P.input_size())])\n",
|
||||||
|
" inputs.append([P.F(0) for _ in range(P.n_cols)] + [P.F(1) for _ in range(P.n_cols)])\n",
|
||||||
|
" inputs.append([P.F(1) for _ in range(P.n_cols)] + [P.F(0) for _ in range(P.n_cols)])\n",
|
||||||
|
" for i in range(n - 4):\n",
|
||||||
|
" input = []\n",
|
||||||
|
" for _ in range(P.input_size()):\n",
|
||||||
|
" input.append(P.to_field(seed))\n",
|
||||||
|
" m.update(str(seed).encode())\n",
|
||||||
|
" seed = Integer(m.digest().hex(), 16)\n",
|
||||||
|
" inputs.append(input)\n",
|
||||||
|
" for input in inputs:\n",
|
||||||
|
" outputs.append(jive(P, b, input))\n",
|
||||||
|
"\n",
|
||||||
|
" print(\n",
|
||||||
|
" \"Test vectors for Anemoi instance over F_{:d}, n_rounds={:d}, n_cols={:d}, s={:d}\".format(\n",
|
||||||
|
" P.q,\n",
|
||||||
|
" P.n_rounds,\n",
|
||||||
|
" P.n_cols,\n",
|
||||||
|
" P.security_level)\n",
|
||||||
|
" )\n",
|
||||||
|
" return (inputs, outputs)\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"def generate_test_vectors_sponge(P, r, h, n):\n",
|
||||||
|
" assert n >= 4, \"The number of test vectors should be greater than 4.\"\n",
|
||||||
|
" m = hashlib.sha512(str(P).encode())\n",
|
||||||
|
" m.update(\"Sponge test vectors\".encode())\n",
|
||||||
|
" m.update(f\"R={r}\".encode())\n",
|
||||||
|
" m.update(f\"H={h}\".encode())\n",
|
||||||
|
" seed = Integer(m.digest().hex(), 16)\n",
|
||||||
|
"\n",
|
||||||
|
" inputs = []\n",
|
||||||
|
" outputs = []\n",
|
||||||
|
" inputs.append([P.F(0) for _ in range(P.input_size())])\n",
|
||||||
|
" inputs.append([P.F(1) for _ in range(P.input_size())])\n",
|
||||||
|
" inputs.append([P.F(0) for _ in range(P.n_cols)] + [P.F(1) for _ in range(P.n_cols)])\n",
|
||||||
|
" inputs.append([P.F(1) for _ in range(P.n_cols)] + [P.F(0) for _ in range(P.n_cols)])\n",
|
||||||
|
" for i in range(n - 4):\n",
|
||||||
|
" input = []\n",
|
||||||
|
" for _ in range(i+1):\n",
|
||||||
|
" input.append(P.to_field(seed))\n",
|
||||||
|
" m.update(str(seed).encode())\n",
|
||||||
|
" seed = Integer(m.digest().hex(), 16)\n",
|
||||||
|
" inputs.append(input)\n",
|
||||||
|
" for input in inputs:\n",
|
||||||
|
" outputs.append(sponge_hash(P, r, h, input))\n",
|
||||||
|
"\n",
|
||||||
|
" print(\n",
|
||||||
|
" \"Test vectors for Anemoi instance over F_{:d}, n_rounds={:d}, n_cols={:d}, s={:d}\".format(\n",
|
||||||
|
" P.q,\n",
|
||||||
|
" P.n_rounds,\n",
|
||||||
|
" P.n_cols,\n",
|
||||||
|
" P.security_level)\n",
|
||||||
|
" )\n",
|
||||||
|
" return (inputs, outputs)\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"def generate_test_vectors_sbox(P, n):\n",
|
||||||
|
" assert n >= 4, \"The number of test vectors should be greater than 4.\"\n",
|
||||||
|
" m = hashlib.sha512(str(P).encode())\n",
|
||||||
|
" m.update(\"S-Box test vectors\".encode())\n",
|
||||||
|
" seed = Integer(m.digest().hex(), 16)\n",
|
||||||
|
"\n",
|
||||||
|
" inputs = []\n",
|
||||||
|
" outputs = []\n",
|
||||||
|
" inputs.append([P.F(0) for _ in range(P.input_size())])\n",
|
||||||
|
" inputs.append([P.F(1) for _ in range(P.input_size())])\n",
|
||||||
|
" inputs.append([P.F(0) for _ in range(P.n_cols)] + [P.F(1) for _ in range(P.n_cols)])\n",
|
||||||
|
" inputs.append([P.F(1) for _ in range(P.n_cols)] + [P.F(0) for _ in range(P.n_cols)])\n",
|
||||||
|
"\n",
|
||||||
|
" for _ in range(n - 4):\n",
|
||||||
|
" input = []\n",
|
||||||
|
" for _ in range(P.input_size()):\n",
|
||||||
|
" input.append(P.to_field(seed))\n",
|
||||||
|
" m.update(str(seed).encode())\n",
|
||||||
|
" seed = Integer(m.digest().hex(), 16)\n",
|
||||||
|
" inputs.append(input)\n",
|
||||||
|
" for input in inputs:\n",
|
||||||
|
" x = [0 for i in range(P.n_cols)]\n",
|
||||||
|
" y = [0 for i in range(P.n_cols)]\n",
|
||||||
|
" for i in range(P.n_cols):\n",
|
||||||
|
" x[i], y[i] = P.evaluate_sbox(input[i], input[P.n_cols + i])\n",
|
||||||
|
" x.extend(y)\n",
|
||||||
|
" outputs.append(x)\n",
|
||||||
|
"\n",
|
||||||
|
" return (inputs, outputs)\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"def generate_test_vectors_mds(P, n):\n",
|
||||||
|
" assert n >= 4, \"The number of test vectors should be greater than 4.\"\n",
|
||||||
|
" m = hashlib.sha512(str(P).encode())\n",
|
||||||
|
" m.update(\"MDS test vectors\".encode())\n",
|
||||||
|
" seed = Integer(m.digest().hex(), 16)\n",
|
||||||
|
"\n",
|
||||||
|
" inputs = []\n",
|
||||||
|
" outputs = []\n",
|
||||||
|
" inputs.append([P.F(0) for _ in range(P.input_size())])\n",
|
||||||
|
" inputs.append([P.F(1) for _ in range(P.input_size())])\n",
|
||||||
|
" inputs.append([P.F(0) for _ in range(P.n_cols)] + [P.F(1) for _ in range(P.n_cols)])\n",
|
||||||
|
" inputs.append([P.F(1) for _ in range(P.n_cols)] + [P.F(0) for _ in range(P.n_cols)])\n",
|
||||||
|
" for _ in range(n - 4):\n",
|
||||||
|
" input = []\n",
|
||||||
|
" for _ in range(P.input_size()):\n",
|
||||||
|
" input.append(P.to_field(seed))\n",
|
||||||
|
" m.update(str(seed).encode())\n",
|
||||||
|
" seed = Integer(m.digest().hex(), 16)\n",
|
||||||
|
" inputs.append(input)\n",
|
||||||
|
" for input in inputs:\n",
|
||||||
|
" x,y = P.linear_layer(input[0:P.n_cols], input[P.n_cols:])\n",
|
||||||
|
" x.extend(y)\n",
|
||||||
|
" outputs.append(x)\n",
|
||||||
|
"\n",
|
||||||
|
" return (inputs, outputs)\n",
|
||||||
|
"\n",
|
||||||
|
"\n",
|
||||||
|
"if __name__ == \"__main__\":\n",
|
||||||
|
"\n",
|
||||||
|
" # These are the first circulant matrices being found by the circulant_mds_matrix()\n",
|
||||||
|
" # method above. These are precomputed for faster initiatialization of large Anemoi\n",
|
||||||
|
" # instances.\n",
|
||||||
|
" CIRCULANT_FP5_MDS_MATRIX = matrix.circulant([1, 1, 3, 4, 5])\n",
|
||||||
|
" CIRCULANT_FP6_MDS_MATRIX = matrix.circulant([1, 1, 3, 4, 5, 6])\n",
|
||||||
|
" CIRCULANT_FP7_MDS_MATRIX = matrix.circulant([1, 2, 3, 5, 5, 6, 7])\n",
|
||||||
|
" CIRCULANT_FP8_MDS_MATRIX = matrix.circulant([1, 2, 3, 5, 7, 8, 8, 9])\n",
|
||||||
|
" CIRCULANT_FP9_MDS_MATRIX = matrix.circulant([1, 3, 5, 6, 8, 9, 9, 10, 11])\n",
|
||||||
|
" CIRCULANT_FP10_MDS_MATRIX = matrix.circulant([1, 2, 5, 6, 8, 11, 11, 12, 13, 14])\n",
|
||||||
|
"\n",
|
||||||
|
" # 128-bit security level instantiations\n",
|
||||||
|
"\n",
|
||||||
|
" A_BLS_12_381_BASEFIELD_1_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_381_BASEFIELD,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_BLS_12_381_BASEFIELD_2_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_381_BASEFIELD,\n",
|
||||||
|
" n_cols=2,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_BLS_12_381_BASEFIELD_3_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_381_BASEFIELD,\n",
|
||||||
|
" n_cols=3,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" A_JUBJUB_BASEFIELD_1_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_381_SCALARFIELD,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_JUBJUB_BASEFIELD_2_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_381_SCALARFIELD,\n",
|
||||||
|
" n_cols=2,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_JUBJUB_BASEFIELD_3_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_381_SCALARFIELD,\n",
|
||||||
|
" n_cols=3,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" A_BLS_12_377_BASEFIELD_1_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_377_BASEFIELD,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_BLS_12_377_BASEFIELD_2_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_377_BASEFIELD,\n",
|
||||||
|
" n_cols=2,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_BLS_12_377_BASEFIELD_3_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_377_BASEFIELD,\n",
|
||||||
|
" n_cols=3,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" A_ED_ON_BLS_12_377_BASEFIELD_1_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_377_SCALARFIELD,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_ED_ON_BLS_12_377_BASEFIELD_2_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_377_SCALARFIELD,\n",
|
||||||
|
" n_cols=2,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_ED_ON_BLS_12_377_BASEFIELD_3_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BLS12_377_SCALARFIELD,\n",
|
||||||
|
" n_cols=3,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" A_BN_254_BASEFIELD_1_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BN_254_BASEFIELD,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_BN_254_BASEFIELD_2_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BN_254_BASEFIELD,\n",
|
||||||
|
" n_cols=2,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_BN_254_BASEFIELD_3_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BN_254_BASEFIELD,\n",
|
||||||
|
" n_cols=3,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" A_BN_254_SCALARFIELD_1_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BN_254_SCALARFIELD,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_BN_254_SCALARFIELD_2_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BN_254_SCALARFIELD,\n",
|
||||||
|
" n_cols=2,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_BN_254_SCALARFIELD_3_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=BN_254_SCALARFIELD,\n",
|
||||||
|
" n_cols=3,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" A_PALLAS_BASEFIELD_1_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=PALLAS_BASEFIELD,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_PALLAS_BASEFIELD_2_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=PALLAS_BASEFIELD,\n",
|
||||||
|
" n_cols=2,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_PALLAS_BASEFIELD_3_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=PALLAS_BASEFIELD,\n",
|
||||||
|
" n_cols=3,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" A_VESTA_BASEFIELD_1_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=VESTA_BASEFIELD,\n",
|
||||||
|
" n_cols=1,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_VESTA_BASEFIELD_2_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=VESTA_BASEFIELD,\n",
|
||||||
|
" n_cols=2,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_VESTA_BASEFIELD_3_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=VESTA_BASEFIELD,\n",
|
||||||
|
" n_cols=3,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
"\n",
|
||||||
|
" A_GOLDILOCKS_64_FIELD_4_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=GOLDILOCKS_64_FIELD,\n",
|
||||||
|
" n_cols=4,\n",
|
||||||
|
" security_level=128\n",
|
||||||
|
" )\n",
|
||||||
|
" A_GOLDILOCKS_64_FIELD_5_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=GOLDILOCKS_64_FIELD,\n",
|
||||||
|
" mat=CIRCULANT_FP5_MDS_MATRIX,\n",
|
||||||
|
" n_cols=5,\n",
|
||||||
|
" security_level=128)\n",
|
||||||
|
" A_GOLDILOCKS_64_FIELD_6_COL_128_BITS = AnemoiPermutation(\n",
|
||||||
|
" q=GOLDILOCKS_64_FIELD,\n",
|
||||||
|
" mat=CIRCULANT_FP6_MDS_MATRIX,\n",
|
||||||
|
" n_cols=6,\n",
|
||||||
|
" security_level=128)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "4de5d23c",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "55940b58",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"A_2 = AnemoiPermutation(q=BLS12_381_SCALARFIELD, alpha=5, n_rounds=None, n_cols=1, security_level=128)\n",
|
||||||
|
"A_4 = AnemoiPermutation(q=BLS12_381_SCALARFIELD, alpha=5, n_rounds=None, n_cols=2, security_level=128)\n",
|
||||||
|
"A_16 = AnemoiPermutation(q=BLS12_381_SCALARFIELD, alpha=5, n_rounds=None, n_cols=8, security_level=128)"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 4,
|
||||||
|
"id": "1714dd8a",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"def h4(a,b,c,d):\n",
|
||||||
|
" return jive(A_4,4,[a,b,c,d])[0]\n",
|
||||||
|
"def h2(x,y):\n",
|
||||||
|
" return jive(A_2,2,[x,y])[0]\n",
|
||||||
|
"def h16(a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p):\n",
|
||||||
|
" return jive(A_4,16,[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p])[0]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "6fb511da",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "d149c137",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "SageMath 9.5",
|
||||||
|
"language": "sage",
|
||||||
|
"name": "sagemath"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.10.12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
|
@ -0,0 +1,348 @@
|
||||||
|
{
|
||||||
|
"cells": [
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 126,
|
||||||
|
"id": "30834567",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"p = 65000549695646603732796438742359905742570406053903786389881062969044166799969\n",
|
||||||
|
"import json\n",
|
||||||
|
"F= FiniteField(p)\n",
|
||||||
|
"\n",
|
||||||
|
"n = 15 #nombre de robot\n",
|
||||||
|
"m = 20 #nombre de tache\n",
|
||||||
|
"borne = 127 # positions entre 0 et borne"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 127,
|
||||||
|
"id": "69686a85",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"robots = [[F(int(random()*borne)),F(int(random()*borne))] for i in range(n)]\n",
|
||||||
|
"\n",
|
||||||
|
"taches = [[F(int(random()*borne)),F(int(random()*borne))] for i in range(m)]\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "raw",
|
||||||
|
"id": "4cc0e6c8",
|
||||||
|
"metadata": {},
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "raw",
|
||||||
|
"id": "1aed5f4e",
|
||||||
|
"metadata": {},
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 128,
|
||||||
|
"id": "ce20e261",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"[[96, 16],\n",
|
||||||
|
" [106, 13],\n",
|
||||||
|
" [63, 13],\n",
|
||||||
|
" [54, 57],\n",
|
||||||
|
" [80, 41],\n",
|
||||||
|
" [11, 78],\n",
|
||||||
|
" [96, 66],\n",
|
||||||
|
" [88, 69],\n",
|
||||||
|
" [99, 55],\n",
|
||||||
|
" [68, 118],\n",
|
||||||
|
" [2, 92],\n",
|
||||||
|
" [86, 28],\n",
|
||||||
|
" [61, 77],\n",
|
||||||
|
" [96, 74],\n",
|
||||||
|
" [114, 111]]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 128,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"robots"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 129,
|
||||||
|
"id": "edc621d1",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"[[14, 92],\n",
|
||||||
|
" [12, 55],\n",
|
||||||
|
" [68, 78],\n",
|
||||||
|
" [102, 2],\n",
|
||||||
|
" [37, 41],\n",
|
||||||
|
" [98, 64],\n",
|
||||||
|
" [101, 69],\n",
|
||||||
|
" [121, 53],\n",
|
||||||
|
" [71, 84],\n",
|
||||||
|
" [80, 115],\n",
|
||||||
|
" [127, 44],\n",
|
||||||
|
" [68, 105],\n",
|
||||||
|
" [14, 117],\n",
|
||||||
|
" [127, 61],\n",
|
||||||
|
" [65, 67],\n",
|
||||||
|
" [17, 27],\n",
|
||||||
|
" [39, 97],\n",
|
||||||
|
" [45, 60],\n",
|
||||||
|
" [30, 22],\n",
|
||||||
|
" [49, 3]]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 129,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"taches"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 130,
|
||||||
|
"id": "f46a80f9",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"La tache 1 est attribuée à : Robot 11 \n",
|
||||||
|
"La tache 2 est attribuée à : Robot 6 \n",
|
||||||
|
"La tache 3 est attribuée à : Robot 8 Robot 13 \n",
|
||||||
|
"La tache 4 est attribuée à : Robot 1 Robot 2 \n",
|
||||||
|
"La tache 5 est attribuée à : Robot 4 Robot 5 \n",
|
||||||
|
"La tache 6 est attribuée à : Robot 7 \n",
|
||||||
|
"La tache 7 est attribuée à : Robot 14 \n",
|
||||||
|
"La tache 8 est attribuée à : Robot 9 \n",
|
||||||
|
"La tache 9 est attribuée à : -\n",
|
||||||
|
"La tache 10 est attribuée à : Robot 10 Robot 15 \n",
|
||||||
|
"La tache 11 est attribuée à : -\n",
|
||||||
|
"La tache 12 est attribuée à : -\n",
|
||||||
|
"La tache 13 est attribuée à : -\n",
|
||||||
|
"La tache 14 est attribuée à : -\n",
|
||||||
|
"La tache 15 est attribuée à : -\n",
|
||||||
|
"La tache 16 est attribuée à : -\n",
|
||||||
|
"La tache 17 est attribuée à : -\n",
|
||||||
|
"La tache 18 est attribuée à : -\n",
|
||||||
|
"La tache 19 est attribuée à : Robot 3 \n",
|
||||||
|
"La tache 20 est attribuée à : Robot 12 \n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"#Algo\n",
|
||||||
|
"distance = [[F((taches[i][0] - robots[j][0])**2 + (taches[i][1] - robots[j][1])**2) for i in range(m)] for j in range(n)]\n",
|
||||||
|
"\n",
|
||||||
|
"position = [[F(0) for j in range(m)] for i in range(n)] # calcul des P_ij\n",
|
||||||
|
"for i in range(n):\n",
|
||||||
|
" for k in range(n):\n",
|
||||||
|
" if(k != i):\n",
|
||||||
|
" for j in range(m):\n",
|
||||||
|
" if(distance[k][j] < distance[i][j]):\n",
|
||||||
|
" position[i][j] += 1\n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
" \n",
|
||||||
|
"attribution = [[F(0) for j in range(m)] for i in range(n)] # attribution correspond à la matrice A du papier\n",
|
||||||
|
"attribution_v2 = [F(0) for i in range(n)] # attribution_v2 la case i représente la tache assigné au robot i.\n",
|
||||||
|
"\n",
|
||||||
|
"for i in range(n):\n",
|
||||||
|
" mini = position[i][0]\n",
|
||||||
|
" idx = 0\n",
|
||||||
|
" for j in range(m):\n",
|
||||||
|
" if(position[i][j] < mini):\n",
|
||||||
|
" idx = j\n",
|
||||||
|
" mini = position[i][j]\n",
|
||||||
|
" attribution[i][idx] = 1\n",
|
||||||
|
" attribution_v2[i] = idx+1\n",
|
||||||
|
"\n",
|
||||||
|
"for j in range(m):\n",
|
||||||
|
" compteur = True\n",
|
||||||
|
" print(\"La tache \"+str(j+1)+\" est attribuée à :\", end='')\n",
|
||||||
|
" for i in range(n):\n",
|
||||||
|
" if(attribution[i][j]):\n",
|
||||||
|
" print(\" Robot \"+str(i+1)+\" \",end='')\n",
|
||||||
|
" compteur = False\n",
|
||||||
|
" if(compteur):\n",
|
||||||
|
" print(\" -\",end=\"\")\n",
|
||||||
|
" print()"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 131,
|
||||||
|
"id": "ebf05832",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"sortie = [\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"1\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"1\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"1\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"1\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"1\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"1\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"1\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"1\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"1\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"1\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\",\"0\"]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 132,
|
||||||
|
"id": "a965d7f6",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"[[13, 12, 13, 1, 9, 8, 9, 7, 13, 12, 3, 13, 13, 8, 11, 7, 13, 12, 6, 2],\n",
|
||||||
|
" [14, 13, 14, 0, 12, 10, 10, 4, 14, 14, 1, 14, 14, 6, 14, 11, 14, 13, 10, 5],\n",
|
||||||
|
" [10, 4, 11, 3, 1, 12, 12, 11, 12, 13, 9, 12, 12, 11, 9, 1, 12, 5, 0, 0],\n",
|
||||||
|
" [3, 2, 2, 9, 0, 7, 8, 10, 4, 7, 11, 6, 4, 10, 1, 0, 4, 0, 1, 4],\n",
|
||||||
|
" [6, 5, 6, 4, 2, 4, 4, 4, 7, 8, 7, 9, 9, 4, 3, 3, 8, 3, 2, 3],\n",
|
||||||
|
" [1, 0, 10, 12, 4, 13, 13, 13, 10, 9, 13, 8, 1, 13, 10, 2, 1, 2, 4, 10],\n",
|
||||||
|
" [8, 9, 4, 6, 9, 0, 0, 1, 3, 5, 2, 5, 7, 1, 4, 10, 7, 6, 11, 9],\n",
|
||||||
|
" [5, 6, 1, 7, 6, 3, 2, 3, 1, 4, 6, 2, 5, 3, 2, 8, 5, 4, 7, 8],\n",
|
||||||
|
" [9, 11, 5, 5, 8, 1, 3, 0, 6, 6, 0, 7, 10, 0, 6, 9, 9, 10, 9, 6],\n",
|
||||||
|
" [4, 8, 7, 13, 13, 11, 11, 12, 5, 0, 12, 0, 2, 12, 8, 13, 2, 11, 13, 13],\n",
|
||||||
|
" [0, 1, 12, 14, 7, 14, 14, 14, 11, 10, 14, 10, 0, 14, 13, 5, 3, 9, 8, 12],\n",
|
||||||
|
" [11, 7, 8, 2, 5, 5, 6, 6, 9, 11, 5, 11, 11, 7, 7, 6, 11, 7, 3, 1],\n",
|
||||||
|
" [2, 3, 0, 10, 3, 6, 5, 9, 0, 2, 10, 1, 3, 9, 0, 4, 0, 1, 5, 7],\n",
|
||||||
|
" [7, 10, 3, 8, 11, 2, 1, 2, 2, 3, 4, 3, 6, 2, 5, 12, 6, 8, 12, 11],\n",
|
||||||
|
" [12, 14, 9, 11, 14, 9, 7, 8, 8, 1, 8, 4, 8, 5, 12, 14, 10, 14, 14, 14]]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 132,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"position"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "5942b82d",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 133,
|
||||||
|
"id": "1c13076f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": [
|
||||||
|
"#Algo v3\n",
|
||||||
|
"distance = [[F((taches[i][0] - robots[j][0])**2 + (taches[i][1] - robots[j][1])**2) for i in range(m)] for j in range(n)]\n",
|
||||||
|
"distance2 = [[F((taches[i][0] - robots[j][0])**2 + (taches[i][1] - robots[j][1])**2) for i in range(m)] for j in range(n)]\n",
|
||||||
|
"position = [[F(i) for j in range(m)] for i in range(n)]\n",
|
||||||
|
"\n",
|
||||||
|
"for j in range(m): #PAS PROUVé\n",
|
||||||
|
" for i in range(n):\n",
|
||||||
|
" for k in range(i+1,n):\n",
|
||||||
|
" if(distance2[k][j]<distance2[i][j]):\n",
|
||||||
|
" tmp = distance2[i][j]\n",
|
||||||
|
" distance2[i][j] = distance2[k][j]\n",
|
||||||
|
" distance2[k][j] = tmp\n",
|
||||||
|
" tmp = position[i][j]\n",
|
||||||
|
" position[i][j] = position[k][j]\n",
|
||||||
|
" position[k][j] = tmp"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "a5daf707",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": 134,
|
||||||
|
"id": "8d00d65f",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [
|
||||||
|
{
|
||||||
|
"data": {
|
||||||
|
"text/plain": [
|
||||||
|
"[[10, 5, 12, 1, 3, 6, 6, 8, 12, 9, 8, 9, 10, 8, 12, 3, 12, 3, 2, 2],\n",
|
||||||
|
" [5, 10, 7, 0, 2, 8, 13, 6, 7, 14, 1, 12, 5, 6, 3, 2, 5, 12, 3, 11],\n",
|
||||||
|
" [12, 3, 3, 11, 4, 13, 7, 13, 13, 12, 6, 7, 9, 13, 7, 5, 9, 5, 4, 0],\n",
|
||||||
|
" [3, 12, 13, 2, 12, 7, 8, 7, 6, 13, 0, 13, 12, 7, 4, 4, 10, 4, 11, 4],\n",
|
||||||
|
" [9, 2, 6, 4, 5, 4, 4, 1, 3, 7, 13, 14, 3, 4, 6, 12, 3, 7, 5, 3],\n",
|
||||||
|
" [7, 4, 8, 8, 11, 11, 12, 4, 9, 6, 11, 6, 7, 14, 13, 10, 7, 2, 12, 1],\n",
|
||||||
|
" [4, 7, 4, 6, 7, 12, 11, 11, 8, 8, 7, 3, 13, 1, 8, 11, 13, 6, 0, 8],\n",
|
||||||
|
" [13, 11, 9, 7, 10, 3, 14, 0, 4, 3, 4, 8, 6, 11, 11, 0, 6, 11, 7, 12],\n",
|
||||||
|
" [6, 9, 11, 13, 8, 0, 3, 14, 14, 4, 14, 5, 14, 0, 9, 7, 4, 13, 10, 7],\n",
|
||||||
|
" [8, 6, 14, 3, 6, 14, 0, 12, 11, 5, 2, 4, 4, 12, 2, 8, 8, 10, 8, 6],\n",
|
||||||
|
" [2, 13, 5, 12, 0, 1, 1, 3, 5, 10, 12, 10, 8, 3, 5, 6, 14, 8, 1, 5],\n",
|
||||||
|
" [11, 8, 2, 14, 13, 9, 9, 2, 10, 11, 3, 11, 11, 2, 0, 1, 11, 9, 6, 13],\n",
|
||||||
|
" [14, 0, 10, 5, 1, 2, 2, 9, 2, 0, 9, 2, 2, 9, 14, 13, 2, 0, 13, 10],\n",
|
||||||
|
" [0, 1, 0, 9, 9, 5, 5, 5, 0, 2, 5, 0, 0, 5, 10, 9, 0, 1, 9, 9],\n",
|
||||||
|
" [1, 14, 1, 10, 14, 10, 10, 10, 1, 1, 10, 1, 1, 10, 1, 14, 1, 14, 14, 14]]"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"execution_count": 134,
|
||||||
|
"metadata": {},
|
||||||
|
"output_type": "execute_result"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"position"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "7ca9c652",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cell_type": "code",
|
||||||
|
"execution_count": null,
|
||||||
|
"id": "92f75ac1",
|
||||||
|
"metadata": {},
|
||||||
|
"outputs": [],
|
||||||
|
"source": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"metadata": {
|
||||||
|
"kernelspec": {
|
||||||
|
"display_name": "SageMath 9.5",
|
||||||
|
"language": "sage",
|
||||||
|
"name": "sagemath"
|
||||||
|
},
|
||||||
|
"language_info": {
|
||||||
|
"codemirror_mode": {
|
||||||
|
"name": "ipython",
|
||||||
|
"version": 3
|
||||||
|
},
|
||||||
|
"file_extension": ".py",
|
||||||
|
"mimetype": "text/x-python",
|
||||||
|
"name": "python",
|
||||||
|
"nbconvert_exporter": "python",
|
||||||
|
"pygments_lexer": "ipython3",
|
||||||
|
"version": "3.10.6"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nbformat": 4,
|
||||||
|
"nbformat_minor": 5
|
||||||
|
}
|
|
@ -0,0 +1,103 @@
|
||||||
|
//test
|
||||||
|
pragma circom 2.1.9;
|
||||||
|
|
||||||
|
include "../../circom_circuits/hash/poseidon/poseidon_16_to_1_Jubjub.circom";
|
||||||
|
include "../../circom_circuits/hash/poseidon/poseidon_4_to_1_Jubjub.circom";
|
||||||
|
|
||||||
|
template coefficient_hash(){
|
||||||
|
signal input coefficients[2048];
|
||||||
|
|
||||||
|
signal output hash;
|
||||||
|
|
||||||
|
component hasher[136];
|
||||||
|
hasher[0] = permutation_16_to_1();
|
||||||
|
hasher[0].in[0] <== 0;
|
||||||
|
for(var i = 1; i<16; i++){
|
||||||
|
hasher[0].in[i] <== coefficients[i-1];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(var i = 1; i<136; i++){
|
||||||
|
hasher[i] = permutation_16_to_1();
|
||||||
|
hasher[i].in[0] <== hasher[i-1].out[0];
|
||||||
|
for(var j = 1; j<16; j++){
|
||||||
|
hasher[i].in[j] <== hasher[i-1].out[j] + coefficients[15*i+j-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
component final_hasher = hash_16_to_1();
|
||||||
|
for (var i =0; i<8; i++){
|
||||||
|
final_hasher.in[i] <== hasher[135].out[i] + coefficients[2040+i];
|
||||||
|
}
|
||||||
|
for (var i =8; i<16; i++){
|
||||||
|
final_hasher.in[i] <== hasher[135].out[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
hash <== final_hasher.out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template drawn_random_point(){
|
||||||
|
signal input da_commitment[2];
|
||||||
|
signal input hash_of_data;
|
||||||
|
|
||||||
|
signal output x_0;
|
||||||
|
|
||||||
|
component final_hasher = hash_4_to_1();
|
||||||
|
|
||||||
|
final_hasher.in[0] <== 0;
|
||||||
|
final_hasher.in[1] <== da_commitment[0];
|
||||||
|
final_hasher.in[2] <== da_commitment[1];
|
||||||
|
final_hasher.in[3] <== hash_of_data;
|
||||||
|
|
||||||
|
x_0 <== final_hasher.out;
|
||||||
|
}
|
||||||
|
|
||||||
|
template evaluate_polynomial(){
|
||||||
|
signal input coefficients[2048];
|
||||||
|
signal input evaluation_point;
|
||||||
|
|
||||||
|
signal output result;
|
||||||
|
|
||||||
|
signal intermediate_values[2046];
|
||||||
|
intermediate_values[2045] <== coefficients[2047] * evaluation_point + coefficients[2046];
|
||||||
|
for(var i = 2044; i >= 0; i--){
|
||||||
|
intermediate_values[i] <== coefficients[i + 1] + intermediate_values[i+1] * evaluation_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
result <== coefficients[0] + intermediate_values[0] * evaluation_point;
|
||||||
|
}
|
||||||
|
|
||||||
|
template proof_of_equivalence(){
|
||||||
|
signal input coefficients[2048];
|
||||||
|
signal input da_commitment[2];
|
||||||
|
|
||||||
|
signal output x_0;
|
||||||
|
signal output y_0;
|
||||||
|
signal output coefficients_hash;
|
||||||
|
|
||||||
|
//Hash of the coefficients
|
||||||
|
component coefficient_hasher = coefficient_hash();
|
||||||
|
for(var i = 0; i<2048; i++){
|
||||||
|
coefficient_hasher.coefficients[i] <== coefficients[i];
|
||||||
|
}
|
||||||
|
coefficients_hash <== coefficient_hasher.hash;
|
||||||
|
|
||||||
|
//Hash the coefficient hash with the da_commitment
|
||||||
|
component point_drawer = drawn_random_point();
|
||||||
|
point_drawer.da_commitment[0] <== da_commitment[0];
|
||||||
|
point_drawer.da_commitment[1] <== da_commitment[1];
|
||||||
|
point_drawer.hash_of_data <== coefficients_hash;
|
||||||
|
x_0 <== point_drawer.x_0;
|
||||||
|
|
||||||
|
//Evaluate the polynomial at x_0
|
||||||
|
component evaluator = evaluate_polynomial();
|
||||||
|
evaluator.evaluation_point <== x_0;
|
||||||
|
for(var i =0; i<2048; i++){
|
||||||
|
evaluator.coefficients[i] <== coefficients[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
y_0 <== evaluator.result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
component main {public [da_commitment]} = proof_of_equivalence();
|
Loading…
Reference in New Issue