public Matrix GetBasisOfWeight(Matrix B, int weight, int num) { Matrix res = new Matrix(), Bchange, B_copy = new Matrix(B); while (res.size[0] < num) { Bchange = MatrixFuncs.GenNoise(B.size[0]); B_copy = Bchange * B_copy; for (int i = 0; i < B.size[0]; ++i) { if (Common.wt(B_copy.data[i]) == weight) { if (MatrixFuncs.Gauss(res & new Vector(B_copy.data[i])) == res.size[0] + 1) { ; } res &= new Vector(B_copy.data[i]); } if (res.size[0] == num) { break; } } } return(res); }
public static Matrix operator *(Code C1, Code C2) { if (C1.n != C2.n) { return(null); } List <List <int> > new_basis = new List <List <int> >(); List <int> item = new List <int>(); for (int i = 0; i < C1.k; ++i) { for (int j = 0; j < C2.k; ++j) { item = new List <int>(); for (int s = 0; s < C2.n; ++s) { item.Add(C1.G.data[i][s] * C2.G.data[j][s]); } new_basis.Add(item); } } Matrix res = new Matrix(new_basis); MatrixFuncs.Gauss(res); return(res); }
bool checkP(Matrix Gp, Matrix P1_inv, Ham ham, Matrix Zero, int s, int n) { bool result = true; for (int i = 0; i < s - 1; ++i) { result &= MatrixFuncs.SubMatrix(Gp * P1_inv, i * n, (i + 1) * n) * MatrixFuncs.Transp(ham.H) == Zero; } return(result); }
// Find A^{-1} public static Matrix Invert(Matrix A) { Matrix E = new Matrix(A.size[0], A.size[0]); for (int i = 0; i < A.size[0]; ++i) { E.data[i][i] = 1; } return(MatrixFuncs.SolveEq(A, E)); }
public Matrix R; // secret key public double KeyGen(CodeType codetype, int[] param) { Code code = new Code(); int k = 0, n = 0, r, m, l = param[2]; switch (codetype) { case CodeType.Hamming: r = param[0]; code = new Ham(r); break; case CodeType.RM: r = param[0]; m = param[1]; code = new RM(r, m); break; } k = code.G.size[0]; n = code.G.size[1]; Stopwatch t = new Stopwatch(); t.Start(); //Matrix N N = MatrixFuncs.GenNoise(k); //Matrix P int nn = n + l; P = new Matrix(nn, nn); int[] check = new int[nn]; int ind = 0; for (int i = 0; i < nn; ++i) { do { ind = Common.GetRand() % nn; } while (check[ind] == 1); P.data[ind][i] = 1; check[ind] = 1; } //Matrix R R = new Matrix(k, l); for (int i = 0; i < k; ++i) { for (int j = 0; j < l; ++j) { R.data[i][j] = Common.GetRand() & 1; } } Gp = N * (code.G | R) * P; t.Stop(); return(t.ElapsedMilliseconds / 1000.00); }
public Matrix P; // secret key public double KeyGen(CodeType codetype, int[] param) { Code code = new Code(); int k, n, r = 0, s = 0, m, nn; switch (codetype) { case CodeType.Hamming: r = param[0]; s = param[1]; code = new Ham(r); break; case CodeType.RM: r = param[0]; m = param[1]; s = param[2]; code = new RM(r, m); break; } k = code.G.size[0]; n = code.G.size[1]; nn = n * s; Stopwatch t = new Stopwatch(); t.Start(); //Matrix list N N = new List <Matrix>(); Matrix N_i, NG = new Matrix(); for (int ii = 0; ii < s; ++ii) { N_i = MatrixFuncs.GenNoise(k); N.Add(N_i); NG |= N_i * code.G; } //Matrix P P = new Matrix(nn, nn); int[] check = new int[nn]; int ind = 0; for (int i = 0; i < nn; ++i) { do { ind = Common.GetRand() % nn; } while (check[ind] == 1); P.data[ind][i] = 1; check[ind] = 1; } Gp = NG * P; t.Stop(); return(t.ElapsedMilliseconds / 1000.00); }
// Generate a random invertible matrix public static Matrix GenNoise(int size) { Matrix res = new Matrix(size, size); do { for (int i = 0; i < size; ++i) { for (int j = 0; j < size; ++j) { res.data[i][j] = Common.GetRand() & 1; } } } while (MatrixFuncs.Gauss(new Matrix(res)) < size); return(res); }
public static Matrix DualMatrix(Matrix G1) { Matrix G1_copy = new Matrix(G1); List <int> I, J; int k = G1_copy.size[0], n = G1_copy.size[1]; Matrix H1 = new Matrix(n - k, n); MatrixFuncs.Gauss_E(G1_copy, out I, out J); for (int s = 0; s < k; ++s) { for (int i = 0; i < n - k; ++i) { H1.data[i][I[s]] = G1_copy.data[s][J[i]]; } } for (int i = 0; i < n - k; ++i) { H1.data[i][J[i]] = 1; } return(H1); }
public Matrix P; // secret key public double KeyGen(CodeType codetype, int[] param) { Code code = new Code(); int k = 0, n = 0, r, m; switch (codetype) { case CodeType.Hamming: r = param[0]; code = new Ham(r); break; case CodeType.RM: r = param[0]; m = param[1]; code = new RM(r, m); break; } k = code.G.size[0]; n = code.G.size[1]; Stopwatch t = new Stopwatch(); t.Start(); //Matrix N N = MatrixFuncs.GenNoise(k); //Matrix P P = new Matrix(n, n); int[] check = new int[n]; int ind = 0; for (int i = 0; i < n; ++i) { do { ind = Common.GetRand() % n; } while (check[ind] == 1); P.data[ind][i] = 1; check[ind] = 1; } Gp = N * code.G * P; t.Stop(); return(t.ElapsedMilliseconds / 1000.00); }
public double AttackHam(out Matrix N1, out Matrix P1) { int k = Gp.size[0], n = Gp.size[1]; N1 = new Matrix(k, k); P1 = new Matrix(n, n); Code code = new Code(Gp); // compute r int r = 0; while ((1 << r) - 1 < n) { ++r; } Stopwatch t = new Stopwatch(); t.Start(); // Matrix P Ham ham = new Ham(r); IEnumerable <int> tmp1, tmp2; Matrix P1_inv = new Matrix(n, n); for (int j = 0; j < n; ++j) { tmp1 = code.H.data.Select(x => x[j]); for (int jj = 0; jj < n; ++jj) { tmp2 = ham.H.data.Select(x => x[jj]); if (tmp1.SequenceEqual(tmp2)) { P1.data[jj][j] = 1; P1_inv.data[j][jj] = 1; break; } } } // Matrix N code.G = code.G * P1_inv; N1 = MatrixFuncs.Transp(MatrixFuncs.SolveEq(MatrixFuncs.Transp(ham.G), MatrixFuncs.Transp(code.G))); t.Stop(); return(t.ElapsedMilliseconds / 1000.00); }
public List <int>[] GetHamIndices(Code code, Ham ham, int r, int s, int n, int k) { int hweight = 1 << (r - 1); Matrix Bchange = MatrixFuncs.GenNoise(n * s - k), Hsub = GetBasisOfWeight(code.H, s * hweight, n - k); IEnumerable <int> hcol1, hcol2; List <int> check = Enumerable.Range(0, n * s).ToList(); List <int>[] res_idx = new List <int> [n]; for (int j = 0; j < n; ++j) { res_idx[j] = new List <int>(); hcol1 = ham.H.data.Select(x => x[j]); for (int jj = 0; jj < check.Count; ++jj) { hcol2 = Hsub.data.Select(x => x[check[jj]]); if (hcol2.SequenceEqual(hcol1)) { res_idx[j].Add(check[jj]); check.RemoveAt(jj); --jj; } if (res_idx[j].Count > s) { break; } } if (res_idx[j].Count != s) { Hsub = GetBasisOfWeight(code.H, s * hweight, n - k); res_idx = new List <int> [n]; check = Enumerable.Range(0, n * s).ToList(); j = -1; } } return(res_idx); }
// Find vector by weight in a code public static Vector FindWeight_simple(Matrix G1, int w) { int tmp, k = G1.size[0], n = G1.size[1]; List <int> I = new List <int>(), J = new List <int>(); int[] check; Random rnd = new Random(); while (true) { check = new int[n]; while (I.Count < k) { tmp = Math.Abs(Common.GetRand()) % n; // rnd.Next(0, n); if (check[tmp] == 0) { I.Add(tmp); check[tmp] = 1; } } for (int i = 0; i < check.Length; ++i) { if (check[i] == 0) { J.Add(i); } } MatrixFuncs.Gauss_on_I(G1, I, J); for (int i = 0; i < G1.size[0]; ++i) { if (Common.wt(G1.data[i]) <= w) { return(new Vector(G1.data[i])); } } I.Clear(); J.Clear(); } }
public double AttackHam(out List <Matrix> Nlist, out Matrix P1) { int k = Gp.size[0], nn = Gp.size[1]; Nlist = new List <Matrix>(); P1 = new Matrix(nn, nn); int r = (int)Math.Log((nn + 2) / 2, 2); int tmp = nn % ((1 << r) - 1), s; while (tmp != 0) { --r; tmp = nn % ((1 << r) - 1); } s = nn / ((1 << r) - 1); int n = nn / s; Matrix Ni = new Matrix(k, k); P1 = new Matrix(nn, nn); Matrix P1_inv = new Matrix(nn, nn); Code code = new Code(Gp); Ham ham = new Ham(r); Stopwatch t = new Stopwatch(); t.Start(); // Matrix P1 List <int>[] ham_idx = GetHamIndices(code, ham, r, s, n, k); Matrix Zero = new Matrix(k, n - k); BigInteger iter_count = 0, max_iter_num = 1, ind_count = 0; List <int>[] idx_copy = new List <int> [n]; int[][] indices = new int[s][]; for (int i = 0; i < s; ++i) { indices[i] = new int[n]; max_iter_num = BigInteger.Multiply(max_iter_num, BigInteger.Pow(s - i, n)); } do { ++iter_count; ++ind_count; if (iter_count > max_iter_num) { ham_idx = GetHamIndices(code, ham, r, s, n, k); for (int i = 0; i < s; ++i) { indices[i] = new int[n]; } iter_count = 1; ind_count = 1; } idx_copy = ham_idx.Select(x => new List <int>(x)).ToArray(); P1 = new Matrix(nn, nn); P1_inv = new Matrix(nn, nn); for (int i = 0; i < s; i++) { for (int j = 0; j < n; ++j) { P1.data[i * n + j][idx_copy[j][indices[i][j]]] = 1; P1_inv.data[idx_copy[j][indices[i][j]]][i * n + j] = 1; idx_copy[j].RemoveAt(indices[i][j]); } } Common.NextSet(indices[0], s, n); if (ind_count == BigInteger.Pow(s, n)) { indices[0] = new int[n]; Common.NextSet(indices[1], s - 1, n); ind_count = 0; } } while (checkP(Gp, P1_inv, ham, Zero, s, n) == false); // Matrices N Matrix NG = Gp * P1_inv; for (int i = 0; i < s; ++i) { Ni = MatrixFuncs.SolveEq(MatrixFuncs.Transp(ham.G), MatrixFuncs.Transp(MatrixFuncs.SubMatrix(NG, i * n, (i + 1) * n))); var ttt = MatrixFuncs.Transp(Ni) * ham.G == MatrixFuncs.SubMatrix(NG, i * n, (i + 1) * n); Nlist.Add(MatrixFuncs.Transp(Ni)); } NG = new Matrix(); for (int i = 0; i < Nlist.Count; ++i) { NG |= Nlist[i] * ham.G; } t.Stop(); return(t.ElapsedMilliseconds / 1000.00); }
// Reduction on r-parameter (for RM-codes) public static Code Reduction(Code code_r, int r, int m) { int k = code_r.G.size[0], n = code_r.G.size[1]; Matrix res = new Matrix(); int sz = code_r.G.size[0] - Common.C(m, r); Vector x; List <int> ind_f = new List <int>(); List <List <int> > ind_sets = new List <List <int> >(); int w = 1 << (m - r), wmin = (1 << r) - 1; Matrix H_short; while (res.size[0] < sz) { x = Code.FindWeight_simple(code_r.G, w); H_short = new Matrix(n - k, n - w); int c = 0; ind_f.Clear(); for (int j = 0; j < n; ++j) { if (x.data[j] == 0) { for (int i = 0; i < code_r.H.size[0]; ++i) { H_short.data[i][c] = code_r.H.data[i][j]; } ind_f.Add(j); ++c; } } MatrixFuncs.Gauss(H_short); //выделяем максимальную л.н. подсистему Ind_set(H_short, ind_f, r, m, (long)n, ind_sets); List <Vector> vecs = new List <Vector>(); for (int i = 0; i < wmin; ++i) { vecs.Add(new Vector(n)); for (int j = 0; j < w; j++) { vecs[i].data[ind_sets[i][j]] = 1; } } for (int i = 0; i < wmin; ++i) { for (int j = 0; j < n; j++) { if (x.data[j] != 0) { vecs[i].data[j] = 1; } } if (code_r.IsCodeWord(vecs[i])) { if (res.size[0] == 0 || MatrixFuncs.Gauss(res & vecs[i]) == res.size[0] + 1) { res &= vecs[i]; } } if (res.size[0] == sz) { return(new Code(res)); } } ind_f.Clear(); } return(new Code(res)); }
//Gaussian elimination public static int Gauss(Matrix A) { if (A == null || A.size[0] == 0) { return(0); } int k = A.size[0], n = A.size[1]; bool flag = true; int rank = 0; for (int i = 0, j = 0; i < k && j < n; ++i, ++j)//c - для инф. окна { if (i == k - 1) { if (A.data[k - 1][j] != 0) { for (int ii = 0; ii < k - 1; ++ii) { if (A.data[ii][j] != 0) { for (int s = 0; s < n; ++s) { A.data[ii][s] = (A.data[ii][s] + A.data[k - 1][s]) & 1; } } } ++rank; break; } else { i--; } } else { if (A.data[i][j] == 0) { flag = false; for (int s = i + 1; s < k; ++s) { if (A.data[s][j] != 0) { flag = true; MatrixFuncs.SwapRows(A, i, s); break; } } } if (flag) { for (int s = 0; s < k; ++s) { if (s != i && A.data[s][j] != 0) { for (int q = 0; q < n; q++) { A.data[s][q] = (A.data[s][q] + A.data[i][q]) & 1; } } } ++rank; } else { i--; flag = true; } } } //избавление от нулевых строк for (int i = rank; i < k; ++i) { A -= rank; } return(rank); }
public double AttackRM(out Matrix N1, out Matrix P1) { int k = Gp.size[0], n = Gp.size[1]; N1 = new Matrix(k, k); P1 = new Matrix(n, n); Code code = new Code(Gp); Code Gp_reduced; // Compute r, m int r = -1, m = (int)Math.Log(n, 2), k1 = 0; while (k1 < k) { ++r; k1 += Common.C(m, r); } RM rm = new RM(r, m); Stopwatch t = new Stopwatch(); t.Start(); // Reduction //2 * r >= m => reduction on dual code if (2 * r < m || m - r == 1) { Gp_reduced = new Code(code.G); } else { Gp_reduced = new Code(code.H); r = m - r - 1; } while (r > 1) { Gp_reduced = AttackFuncs.Reduction(Gp_reduced, r, m); --r; } // Matrix P Matrix Tmp; int idx = -1; Vector e = new Vector(Enumerable.Repeat(1, n).ToList()); do { ++idx; Tmp = (new Matrix(Gp_reduced.G) - idx) & e; }while (MatrixFuncs.Gauss(Tmp) < m + 1); Tmp = Gp_reduced.G; Tmp -= idx; Matrix RM_1 = (new RM(1, m)).G -= 0; IEnumerable <int> tmp1, tmp2; Matrix P1_inv = new Matrix(n, n); for (int j = 0; j < n; ++j) { tmp1 = Tmp.data.Select(x => x[j]); for (int jj = 0; jj < n; ++jj) { tmp2 = RM_1.data.Select(x => x[jj]); if (tmp1.SequenceEqual(tmp2)) { P1.data[jj][j] = 1; P1_inv.data[j][jj] = 1; break; } } } // Matrix N code.G = code.G * P1_inv; N1 = MatrixFuncs.Transp(MatrixFuncs.SolveEq(MatrixFuncs.Transp(rm.G), MatrixFuncs.Transp(code.G))); t.Stop(); return(t.ElapsedMilliseconds / 1000.00); }
//Gaussian elimination with information window public static int Gauss_E(Matrix A, out List <int> I, out List <int> J) { I = new List <int>(); J = new List <int>(); if (A == null || A.size[0] == 0) { return(0); } int k = A.size[0], n = A.size[1]; if (k <= n) { bool flag = true; for (int i = 0, c = 0, j = 0; i < k && j < n; ++i, ++c, ++j)//c - для инф. окна { if (i == k - 1) { if (A.data[k - 1][j] != 0) { for (int ii = 0; ii < k - 1; ++ii) { if (A.data[ii][j] != 0) { for (int s = 0; s < n; ++s) { A.data[ii][s] = (A.data[ii][s] + A.data[k - 1][s]) & 1; } } } I.Add(j); ++j; while (j < n) { J.Add(j); ++j; } break; } else { i--; J.Add(j); } } else { if (A.data[i][j] == 0) { flag = false; for (int s = i + 1; s < k; ++s) { if (A.data[s][j] != 0) { flag = true; MatrixFuncs.SwapRows(A, i, s); break; } } } if (flag) { for (int s = 0; s < k; ++s) { if (s != i && A.data[s][j] != 0) { for (int q = 0; q < n; q++) { A.data[s][q] = (A.data[s][q] + A.data[i][q]) & 1; } } } I.Add(j); } else { c--; i--; J.Add(j); flag = true; } } } //избавление от нулевых строк for (int i = I.Count; i < A.size[0]; ++i) { A -= I.Count; } return(I.Count); } return(-1); }