/// <summary> /// Initialize this class /// </summary> /// /// <param name="Field">The finite field</param> /// <param name="Poly">The reduction polynomial</param> public PolynomialRingGF2m(GF2mField Field, PolynomialGF2mSmallM Poly) { _field = Field; _poly = Poly; ComputeSquaringMatrix(); ComputeSquareRootMatrix(); }
/// <summary> /// Swap two columns /// </summary> private static void SwapColumns(PolynomialGF2mSmallM[] Matrix, int First, int Second) { PolynomialGF2mSmallM tmp = Matrix[First]; Matrix[First] = Matrix[Second]; Matrix[Second] = tmp; }
/// <summary> /// Compute the inverse of this polynomial modulo the given polynomial /// </summary> /// /// <param name="A">The reduction polynomial</param> /// /// <returns>Returns <c>this^(-1) mod a</c></returns> public PolynomialGF2mSmallM ModInverse(PolynomialGF2mSmallM A) { int[] unit = { 1 }; int[] resultCoeff = ModDiv(unit, _coefficients, A._coefficients, _field); return(new PolynomialGF2mSmallM(_field, resultCoeff)); }
/// <summary> /// Copy constructor /// </summary> /// /// <param name="Gf">The PolynomialGF2mSmallM to copy</param> public PolynomialGF2mSmallM(PolynomialGF2mSmallM Gf) { // field needs not to be cloned since it is immutable _field = Gf._field; _degree = Gf._degree; _coefficients = IntUtils.DeepCopy(Gf._coefficients); }
/// <summary> /// Divide this polynomial by the given polynomial /// </summary> /// <param name="F">The polynomial</param> /// <returns>Returns polynomial pair = {q,r} where this = q*f+r and deg(r) < deg(f)</returns> public PolynomialGF2mSmallM[] Divide(PolynomialGF2mSmallM F) { int[][] resultCoeffs = Divide(_coefficients, F._coefficients, _field); return(new PolynomialGF2mSmallM[] { new PolynomialGF2mSmallM(_field, resultCoeffs[0]), new PolynomialGF2mSmallM(_field, resultCoeffs[1]) }); }
/// <summary> /// Initialize this class for CCA2 MPKCS /// </summary> /// /// <param name="N">Length of the code</param> /// <param name="K">The dimension of the code</param> /// <param name="Gf">The finite field <c>GF(2^m)</c></param> /// <param name="Gp">The irreducible Goppa polynomial</param> /// <param name="P">The permutation</param> /// <param name="H">The canonical check matrix</param> /// <param name="QInv">The matrix used to compute square roots in <c>(GF(2^m))^t</c></param> internal MPKCPrivateKey(int N, int K, GF2mField Gf, PolynomialGF2mSmallM Gp, Permutation P, GF2Matrix H, PolynomialGF2mSmallM[] QInv) { _N = N; _K = K; _gField = Gf; _goppaPoly = Gp; _P1 = P; _H = H; _qInv = QInv; }
/// <summary> /// Compute the square root of this polynomial modulo the given polynomial /// </summary> /// /// <param name="A">The reduction polynomial</param> /// /// <returns>Returns <c>this^(1/2) mod A</c></returns> public PolynomialGF2mSmallM ModSquareRoot(PolynomialGF2mSmallM A) { int[] resultCoeff = IntUtils.DeepCopy(_coefficients); int[] help = ModMultiply(resultCoeff, resultCoeff, A._coefficients, _field); while (!IsEqual(help, _coefficients)) { resultCoeff = NormalForm(help); help = ModMultiply(resultCoeff, resultCoeff, A._coefficients, _field); } return(new PolynomialGF2mSmallM(_field, resultCoeff)); }
/// <summary> /// Initialize this class CCA2 MPKCS using encoded byte arrays /// </summary> /// /// <param name="N">Length of the code</param> /// <param name="K">The dimension of the code</param> /// <param name="Gf">Encoded field polynomial defining the finite field <c>GF(2^m)</c></param> /// <param name="Gp">Encoded irreducible Goppa polynomial</param> /// <param name="P">The encoded permutation</param> /// <param name="H">Encoded canonical check matrix</param> /// <param name="QInv">The encoded matrix used to compute square roots in <c>(GF(2^m))^t</c></param> public MPKCPrivateKey(int N, int K, byte[] Gf, byte[] Gp, byte[] P, byte[] H, byte[][] QInv) { _N = N; _K = K; _gField = new GF2mField(Gf); _goppaPoly = new PolynomialGF2mSmallM(_gField, Gp); _P1 = new Permutation(P); _H = new GF2Matrix(H); _qInv = new PolynomialGF2mSmallM[QInv.Length]; for (int i = 0; i < QInv.Length; i++) _qInv[i] = new PolynomialGF2mSmallM(_gField, QInv[i]); }
/// <summary> /// Compare this element with another object /// </summary> /// /// <param name="Obj">The object for comprison</param> /// /// <returns>Returns <c>true</c> if the two objects are equal, <c>false</c> otherwise</returns> public override bool Equals(Object Obj) { if (Obj == null || !(Obj is PolynomialGF2mSmallM)) { return(false); } PolynomialGF2mSmallM p = (PolynomialGF2mSmallM)Obj; if ((_field.Equals(p._field)) && (_degree.Equals(p._degree)) && (Compare.AreEqual(_coefficients, p._coefficients))) { return(true); } return(false); }
/// <summary> /// Find an error vector <c>E</c> over <c>GF(2)</c> from an input syndrome <c>S</c> over <c>GF(2^M)</c> /// </summary> /// /// <param name="SyndVec">The syndrome</param> /// <param name="Field">The finite field</param> /// <param name="Gp">The irreducible Goppa polynomial</param> /// <param name="SqRootMatrix">The matrix for computing square roots in <c>(GF(2M))<sup>T</sup></c></param> /// /// <returns>The error vector</returns> public static GF2Vector SyndromeDecode(GF2Vector SyndVec, GF2mField Field, PolynomialGF2mSmallM Gp, PolynomialGF2mSmallM[] SqRootMatrix) { int n = 1 << Field.Degree; // the error vector GF2Vector errors = new GF2Vector(n); // if the syndrome vector is zero, the error vector is also zero if (!SyndVec.IsZero()) { // convert syndrome vector to polynomial over GF(2^m) PolynomialGF2mSmallM syndrome = new PolynomialGF2mSmallM(SyndVec.ToExtensionFieldVector(Field)); // compute T = syndrome^-1 mod gp PolynomialGF2mSmallM t = syndrome.ModInverse(Gp); // compute tau = sqRoot(T + X) mod gp PolynomialGF2mSmallM tau = t.AddMonomial(1); tau = tau.ModSquareRootMatrix(SqRootMatrix); // compute polynomials a and b satisfying a + b*tau = 0 mod gp PolynomialGF2mSmallM[] ab = tau.ModPolynomialToFracton(Gp); // compute the polynomial a^2 + X*b^2 PolynomialGF2mSmallM a2 = ab[0].Multiply(ab[0]); PolynomialGF2mSmallM b2 = ab[1].Multiply(ab[1]); PolynomialGF2mSmallM xb2 = b2.MultWithMonomial(1); PolynomialGF2mSmallM a2plusXb2 = a2.Add(xb2); // normalize a^2 + X*b^2 to obtain the error locator polynomial int headCoeff = a2plusXb2.Head; int invHeadCoeff = Field.Inverse(headCoeff); PolynomialGF2mSmallM elp = a2plusXb2.MultWithElement(invHeadCoeff); // for all elements i of GF(2^m) for (int i = 0; i < n; i++) { // evaluate the error locator polynomial at i int z = elp.EvaluateAt(i); // if polynomial evaluates to zero if (z == 0) { // set the i-th coefficient of the error vector errors.SetBit(i); } } } return(errors); }
/// <summary> /// Compute the squaring matrix for this polynomial ring, using the base field and the reduction polynomial /// </summary> private void ComputeSquaringMatrix() { int numColumns = _poly.Degree; _sqMatrix = new PolynomialGF2mSmallM[numColumns]; PolynomialGF2mSmallM[] _sqMatrix2 = new PolynomialGF2mSmallM[numColumns]; if (ParallelUtils.IsParallel) { int nct = numColumns >> 1; Parallel.For(0, nct, i => { int[] monomCoeffs = new int[(i << 1) + 1]; monomCoeffs[i << 1] = 1; _sqMatrix[i] = new PolynomialGF2mSmallM(_field, monomCoeffs); }); Parallel.For(nct, numColumns, i => { int[] monomCoeffs = new int[(i << 1) + 1]; monomCoeffs[i << 1] = 1; PolynomialGF2mSmallM monomial = new PolynomialGF2mSmallM(_field, monomCoeffs); _sqMatrix[i] = monomial.Mod(_poly); }); } else { for (int i = 0; i < numColumns >> 1; i++) { int[] monomCoeffs = new int[(i << 1) + 1]; monomCoeffs[i << 1] = 1; _sqMatrix[i] = new PolynomialGF2mSmallM(_field, monomCoeffs); } for (int i = numColumns >> 1; i < numColumns; i++) { int[] monomCoeffs = new int[(i << 1) + 1]; monomCoeffs[i << 1] = 1; PolynomialGF2mSmallM monomial = new PolynomialGF2mSmallM(_field, monomCoeffs); _sqMatrix[i] = monomial.Mod(_poly); } } }
/// <summary> /// Compute a polynomial pair (a,b) from this polynomial and the given /// polynomial g with the property b*this = a mod g and deg(a)<=deg(g)/2 /// </summary> /// /// <param name="G">The reduction polynomial</param> /// /// <returns>Returns PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)<= deg(g)/2</returns> public PolynomialGF2mSmallM[] ModPolynomialToFracton(PolynomialGF2mSmallM G) { int dg = G._degree >> 1; int[] a0 = NormalForm(G._coefficients); int[] a1 = Mod(_coefficients, G._coefficients, _field); int[] b0 = { 0 }; int[] b1 = { 1 }; while (ComputeDegree(a1) > dg) { int[][] q = Divide(a0, a1, _field); a0 = a1; a1 = q[1]; int[] b2 = Add(b0, ModMultiply(q[0], b1, G._coefficients, _field), _field); b0 = b1; b1 = b2; } return(new PolynomialGF2mSmallM[] { new PolynomialGF2mSmallM(_field, a1), new PolynomialGF2mSmallM(_field, b1) }); }
/// <summary> /// Compute the inverse of this polynomial modulo the given polynomial /// </summary> /// /// <param name="A">The reduction polynomial</param> /// /// <returns>Returns <c>this^(-1) mod a</c></returns> public PolynomialGF2mSmallM ModInverse(PolynomialGF2mSmallM A) { int[] unit = { 1 }; int[] resultCoeff = ModDiv(unit, _coefficients, A._coefficients, _field); return new PolynomialGF2mSmallM(_field, resultCoeff); }
/// <summary> /// Compute the product of this polynomial and the given factor using a Karatzuba like scheme /// </summary> /// /// <param name="Factor">the polynomial factor</param> /// /// <returns>Returns <c>this * factor</c></returns> public PolynomialGF2mSmallM Multiply(PolynomialGF2mSmallM Factor) { int[] resultCoeff = Multiply(_coefficients, Factor._coefficients, _field); return(new PolynomialGF2mSmallM(_field, resultCoeff)); }
/// <summary> /// Find an error vector <c>E</c> over <c>GF(2)</c> from an input syndrome <c>S</c> over <c>GF(2^M)</c> /// </summary> /// /// <param name="SyndVec">The syndrome</param> /// <param name="Field">The finite field</param> /// <param name="Gp">The irreducible Goppa polynomial</param> /// <param name="SqRootMatrix">The matrix for computing square roots in <c>(GF(2M))<sup>T</sup></c></param> /// /// <returns>The error vector</returns> public static GF2Vector SyndromeDecode(GF2Vector SyndVec, GF2mField Field, PolynomialGF2mSmallM Gp, PolynomialGF2mSmallM[] SqRootMatrix) { int n = 1 << Field.Degree; // the error vector GF2Vector errors = new GF2Vector(n); // if the syndrome vector is zero, the error vector is also zero if (!SyndVec.IsZero()) { // convert syndrome vector to polynomial over GF(2^m) PolynomialGF2mSmallM syndrome = new PolynomialGF2mSmallM(SyndVec.ToExtensionFieldVector(Field)); // compute T = syndrome^-1 mod gp PolynomialGF2mSmallM t = syndrome.ModInverse(Gp); // compute tau = sqRoot(T + X) mod gp PolynomialGF2mSmallM tau = t.AddMonomial(1); tau = tau.ModSquareRootMatrix(SqRootMatrix); // compute polynomials a and b satisfying a + b*tau = 0 mod gp PolynomialGF2mSmallM[] ab = tau.ModPolynomialToFracton(Gp); // compute the polynomial a^2 + X*b^2 PolynomialGF2mSmallM a2 = ab[0].Multiply(ab[0]); PolynomialGF2mSmallM b2 = ab[1].Multiply(ab[1]); PolynomialGF2mSmallM xb2 = b2.MultWithMonomial(1); PolynomialGF2mSmallM a2plusXb2 = a2.Add(xb2); // normalize a^2 + X*b^2 to obtain the error locator polynomial int headCoeff = a2plusXb2.Head; int invHeadCoeff = Field.Inverse(headCoeff); PolynomialGF2mSmallM elp = a2plusXb2.MultWithElement(invHeadCoeff); // for all elements i of GF(2^m) for (int i = 0; i < n; i++) { // evaluate the error locator polynomial at i int z = elp.EvaluateAt(i); // if polynomial evaluates to zero if (z == 0) { // set the i-th coefficient of the error vector errors.SetBit(i); } } } return errors; }
/// <summary> /// Reduce this polynomial modulo another polynomial /// </summary> /// /// <param name="F">The reduction polynomial</param> /// /// <returns>Returns <c>this mod f</c></returns> public PolynomialGF2mSmallM Mod(PolynomialGF2mSmallM F) { int[] resultCoeff = Mod(_coefficients, F._coefficients, _field); return(new PolynomialGF2mSmallM(_field, resultCoeff)); }
/// <summary> /// Add the given polynomial to this polynomial (overwrite this). /// </summary> /// /// <param name="Addend">The addend</param> public void AddToThis(PolynomialGF2mSmallM Addend) { _coefficients = Add(_coefficients, Addend._coefficients, _field); ComputeDegree(); }
/// <summary> /// Construct the check matrix of a Goppa code in canonical form from the irreducible Goppa polynomial over the finite field <c>GF(2^m)</c>. /// </summary> /// /// <param name="Field">The finite field</param> /// <param name="Gp">The irreducible Goppa polynomial</param> /// /// <returns>The new GF2Matrix</returns> public static GF2Matrix CreateCanonicalCheckMatrix(GF2mField Field, PolynomialGF2mSmallM Gp) { int m = Field.Degree; int n = 1 << m; int t = Gp.Degree; // create matrix H over GF(2^m) int[][] hArray = ArrayUtils.CreateJagged <int[][]>(t, n); // create matrix YZ int[][] yz = ArrayUtils.CreateJagged <int[][]>(t, n); if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => yz[0][j] = Field.Inverse(Gp.EvaluateAt(j))); } else { // here j is used as index and as element of field GF(2^m) for (int j = 0; j < n; j++) { yz[0][j] = Field.Inverse(Gp.EvaluateAt(j)); } } for (int i = 1; i < t; i++) { // here j is used as index and as element of field GF(2^m) if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => { yz[i][j] = Field.Multiply(yz[i - 1][j], j); }); } else { for (int j = 0; j < n; j++) { yz[i][j] = Field.Multiply(yz[i - 1][j], j); } } } // create matrix H = XYZ for (int i = 0; i < t; i++) { if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => { for (int k = 0; k <= i; k++) { hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i))); } }); } else { for (int j = 0; j < n; j++) { for (int k = 0; k <= i; k++) { hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i))); } } } } // convert to matrix over GF(2) int[][] result = ArrayUtils.CreateJagged <int[][]>(t * m, IntUtils.URShift((n + 31), 5)); if (ParallelUtils.IsParallel) { for (int j = 0; j < n; j++) { int q = IntUtils.URShift(j, 5); int r = 1 << (j & 0x1f); for (int i = 0; i < t; i++) { int e = hArray[i][j]; Parallel.For(0, m, u => { int b = (IntUtils.URShift(e, u)) & 1; if (b != 0) { int ind = (i + 1) * m - u - 1; result[ind][q] ^= r; } }); } } } else { for (int j = 0; j < n; j++) { int q = IntUtils.URShift(j, 5); int r = 1 << (j & 0x1f); for (int i = 0; i < t; i++) { int e = hArray[i][j]; for (int u = 0; u < m; u++) { int b = (IntUtils.URShift(e, u)) & 1; if (b != 0) { int ind = (i + 1) * m - u - 1; result[ind][q] ^= r; } } } } } return(new GF2Matrix(n, result)); }
/// <summary> /// Compute the product of this polynomial and the given factor using a Karatzuba like scheme /// </summary> /// /// <param name="Factor">the polynomial factor</param> /// /// <returns>Returns <c>this * factor</c></returns> public PolynomialGF2mSmallM Multiply(PolynomialGF2mSmallM Factor) { int[] resultCoeff = Multiply(_coefficients, Factor._coefficients, _field); return new PolynomialGF2mSmallM(_field, resultCoeff); }
/// <summary> /// Compute the square root of this polynomial using a square root matrix /// </summary> /// /// <param name="M">The matrix for computing square roots in <c>(GF(2^m))^t</c> the polynomial ring defining the square root matrix</param> /// /// <returns>Returns <c>this^(1/2)</c> modulo the reduction polynomial implicitly given via the square root matrix</returns> public PolynomialGF2mSmallM ModSquareRootMatrix(PolynomialGF2mSmallM[] M) { int length = M.Length; int[] resultCoeff = new int[length]; // do matrix multiplication for (int i = 0; i < length; i++) { // compute scalar product of i-th row and j-th column for (int j = 0; j < length; j++) { if (i >= M[j]._coefficients.Length) continue; if (j < _coefficients.Length) { int scalarTerm = _field.Multiply(M[j]._coefficients[i], _coefficients[j]); resultCoeff[i] = _field.Add(resultCoeff[i], scalarTerm); } } } // compute the square root of each entry of the result coefficients for (int i = 0; i < length; i++) resultCoeff[i] = _field.Sqrt(resultCoeff[i]); return new PolynomialGF2mSmallM(_field, resultCoeff); }
/// <summary> /// Compute the square root of this polynomial modulo the given polynomial /// </summary> /// /// <param name="A">The reduction polynomial</param> /// /// <returns>Returns <c>this^(1/2) mod A</c></returns> public PolynomialGF2mSmallM ModSquareRoot(PolynomialGF2mSmallM A) { int[] resultCoeff = IntUtils.DeepCopy(_coefficients); int[] help = ModMultiply(resultCoeff, resultCoeff, A._coefficients, _field); while (!IsEqual(help, _coefficients)) { resultCoeff = NormalForm(help); help = ModMultiply(resultCoeff, resultCoeff, A._coefficients, _field); } return new PolynomialGF2mSmallM(_field, resultCoeff); }
/// <summary> /// Square this polynomial using a squaring matrix /// </summary> /// /// <param name="M">The squaring matrix</param> /// /// <returns>Returns <c>this^2</c> modulo the reduction polynomial implicitly given via the squaring matrix</returns> public PolynomialGF2mSmallM ModSquareMatrix(PolynomialGF2mSmallM[] M) { int length = M.Length; int[] resultCoeff = new int[length]; int[] thisSquare = new int[length]; // square each entry of this polynomial for (int i = 0; i < _coefficients.Length; i++) thisSquare[i] = _field.Multiply(_coefficients[i], _coefficients[i]); // do matrix-vector multiplication for (int i = 0; i < length; i++) { // compute scalar product of i-th row and coefficient vector for (int j = 0; j < length; j++) { if (i >= M[j]._coefficients.Length) continue; int scalarTerm = _field.Multiply(M[j]._coefficients[i], thisSquare[j]); resultCoeff[i] = _field.Add(resultCoeff[i], scalarTerm); } } return new PolynomialGF2mSmallM(_field, resultCoeff); }
/// <summary> /// Compute a polynomial pair (a,b) from this polynomial and the given /// polynomial g with the property b*this = a mod g and deg(a)<=deg(g)/2 /// </summary> /// /// <param name="G">The reduction polynomial</param> /// /// <returns>Returns PolynomialGF2mSmallM[] {a,b} with b*this = a mod g and deg(a)<= deg(g)/2</returns> public PolynomialGF2mSmallM[] ModPolynomialToFracton(PolynomialGF2mSmallM G) { int dg = G._degree >> 1; int[] a0 = NormalForm(G._coefficients); int[] a1 = Mod(_coefficients, G._coefficients, _field); int[] b0 = { 0 }; int[] b1 = { 1 }; while (ComputeDegree(a1) > dg) { int[][] q = Divide(a0, a1, _field); a0 = a1; a1 = q[1]; int[] b2 = Add(b0, ModMultiply(q[0], b1, G._coefficients, _field), _field); b0 = b1; b1 = b2; } return new PolynomialGF2mSmallM[] { new PolynomialGF2mSmallM(_field, a1), new PolynomialGF2mSmallM(_field, b1) }; }
/// <summary> /// Compute the product of this polynomial and another polynomial modulo a third polynomial /// </summary> /// /// <param name="A">The polynomial</param> /// <param name="B">The reduction polynomial</param> /// /// <returns>Returns <c>this * a mod b</c></returns> public PolynomialGF2mSmallM ModMultiply(PolynomialGF2mSmallM A, PolynomialGF2mSmallM B) { int[] resultCoeff = ModMultiply(_coefficients, A._coefficients, B._coefficients, _field); return new PolynomialGF2mSmallM(_field, resultCoeff); }
/// <summary> /// Compute the sum of this polynomial and the given polynomial /// </summary> /// /// <param name="Addend">he addend</param> /// /// <returns>Return <c>this + a</c> (newly created)</returns> public PolynomialGF2mSmallM Add(PolynomialGF2mSmallM Addend) { int[] resultCoeff = Add(_coefficients, Addend._coefficients, _field); return new PolynomialGF2mSmallM(_field, resultCoeff); }
/// <summary> /// Reduce this polynomial modulo another polynomial /// </summary> /// /// <param name="F">The reduction polynomial</param> /// /// <returns>Returns <c>this mod f</c></returns> public PolynomialGF2mSmallM Mod(PolynomialGF2mSmallM F) { int[] resultCoeff = Mod(_coefficients, F._coefficients, _field); return new PolynomialGF2mSmallM(_field, resultCoeff); }
/// <summary> /// Compute the sum of this polynomial and the given polynomial /// </summary> /// /// <param name="Addend">he addend</param> /// /// <returns>Return <c>this + a</c> (newly created)</returns> public PolynomialGF2mSmallM Add(PolynomialGF2mSmallM Addend) { int[] resultCoeff = Add(_coefficients, Addend._coefficients, _field); return(new PolynomialGF2mSmallM(_field, resultCoeff)); }
/// <summary> /// Divide this polynomial by the given polynomial /// </summary> /// <param name="F">The polynomial</param> /// <returns>Returns polynomial pair = {q,r} where this = q*f+r and deg(r) < deg(f)</returns> public PolynomialGF2mSmallM[] Divide(PolynomialGF2mSmallM F) { int[][] resultCoeffs = Divide(_coefficients, F._coefficients, _field); return new PolynomialGF2mSmallM[]{ new PolynomialGF2mSmallM(_field, resultCoeffs[0]), new PolynomialGF2mSmallM(_field, resultCoeffs[1])}; }
/// <summary> /// Construct the check matrix of a Goppa code in canonical form from the irreducible Goppa polynomial over the finite field <c>GF(2^m)</c>. /// </summary> /// /// <param name="Field">The finite field</param> /// <param name="Gp">The irreducible Goppa polynomial</param> /// /// <returns>The new GF2Matrix</returns> public static GF2Matrix CreateCanonicalCheckMatrix(GF2mField Field, PolynomialGF2mSmallM Gp) { int m = Field.Degree; int n = 1 << m; int t = Gp.Degree; // create matrix H over GF(2^m) int[][] hArray = ArrayUtils.CreateJagged<int[][]>(t, n); // create matrix YZ int[][] yz = ArrayUtils.CreateJagged<int[][]>(t, n); if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => yz[0][j] = Field.Inverse(Gp.EvaluateAt(j))); } else { // here j is used as index and as element of field GF(2^m) for (int j = 0; j < n; j++) yz[0][j] = Field.Inverse(Gp.EvaluateAt(j)); } for (int i = 1; i < t; i++) { // here j is used as index and as element of field GF(2^m) if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => { yz[i][j] = Field.Multiply(yz[i - 1][j], j); }); } else { for (int j = 0; j < n; j++) yz[i][j] = Field.Multiply(yz[i - 1][j], j); } } // create matrix H = XYZ for (int i = 0; i < t; i++) { if (ParallelUtils.IsParallel) { Parallel.For(0, n, j => { for (int k = 0; k <= i; k++) hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i))); }); } else { for (int j = 0; j < n; j++) { for (int k = 0; k <= i; k++) hArray[i][j] = Field.Add(hArray[i][j], Field.Multiply(yz[k][j], Gp.GetCoefficient(t + k - i))); } } } // convert to matrix over GF(2) int[][] result = ArrayUtils.CreateJagged<int[][]>(t * m, IntUtils.URShift((n + 31), 5)); if (ParallelUtils.IsParallel) { for (int j = 0; j < n; j++) { int q = IntUtils.URShift(j, 5); int r = 1 << (j & 0x1f); for (int i = 0; i < t; i++) { int e = hArray[i][j]; Parallel.For(0, m, u => { int b = (IntUtils.URShift(e, u)) & 1; if (b != 0) { int ind = (i + 1) * m - u - 1; result[ind][q] ^= r; } }); } } } else { for (int j = 0; j < n; j++) { int q = IntUtils.URShift(j, 5); int r = 1 << (j & 0x1f); for (int i = 0; i < t; i++) { int e = hArray[i][j]; for (int u = 0; u < m; u++) { int b = (IntUtils.URShift(e, u)) & 1; if (b != 0) { int ind = (i + 1) * m - u - 1; result[ind][q] ^= r; } } } } } return new GF2Matrix(n, result); }
/// <summary> /// Compute the result of the division of this polynomial by another polynomial modulo a third polynomial /// </summary> /// /// <param name="Divisor">The divisor</param> /// <param name="Modulus">The reduction polynomial</param> /// /// <returns>Returns <c>this * divisor^(-1) mod modulus</c></returns> public PolynomialGF2mSmallM ModDivide(PolynomialGF2mSmallM Divisor, PolynomialGF2mSmallM Modulus) { int[] resultCoeff = ModDiv(_coefficients, Divisor._coefficients, Modulus._coefficients, _field); return(new PolynomialGF2mSmallM(_field, resultCoeff)); }
/// <summary> /// Compute the matrix for computing square roots in this polynomial ring by inverting the squaring matrix /// </summary> private void ComputeSquareRootMatrix() { int numColumns = _poly.Degree; // clone squaring matrix PolynomialGF2mSmallM[] tmpMatrix = new PolynomialGF2mSmallM[numColumns]; for (int i = numColumns - 1; i >= 0; i--) tmpMatrix[i] = new PolynomialGF2mSmallM(_sqMatrix[i]); // initialize square root matrix as unit matrix _sqRootMatrix = new PolynomialGF2mSmallM[numColumns]; for (int i = numColumns - 1; i >= 0; i--) _sqRootMatrix[i] = new PolynomialGF2mSmallM(_field, i); // simultaneously compute Gaussian reduction of squaring matrix and unit matrix for (int i = 0; i < numColumns; i++) { // if diagonal element is zero if (tmpMatrix[i].GetCoefficient(i) == 0) { bool foundNonZero = false; // find a non-zero element in the same row for (int j = i + 1; j < numColumns; j++) { if (tmpMatrix[j].GetCoefficient(i) != 0) { // found it, swap columns ... foundNonZero = true; SwapColumns(tmpMatrix, i, j); SwapColumns(_sqRootMatrix, i, j); // ... and quit searching j = numColumns; continue; } } // if no non-zero element was found the matrix is not invertible if (!foundNonZero) throw new ArithmeticException("Squaring matrix is not invertible."); } // normalize i-th column int coef = tmpMatrix[i].GetCoefficient(i); int invCoef = _field.Inverse(coef); tmpMatrix[i].MultThisWithElement(invCoef); _sqRootMatrix[i].MultThisWithElement(invCoef); if (ParallelUtils.IsParallel) { // normalize all other columns Parallel.For(0, numColumns, j => { if (j != i) { int coefp = tmpMatrix[j].GetCoefficient(i); if (coefp != 0) { PolynomialGF2mSmallM tmpSqColumn = tmpMatrix[i].MultWithElement(coefp); PolynomialGF2mSmallM tmpInvColumn = _sqRootMatrix[i].MultWithElement(coefp); tmpMatrix[j].AddToThis(tmpSqColumn); lock (_sqRootMatrix) _sqRootMatrix[j].AddToThis(tmpInvColumn); } } }); } else { for (int j = 0; j < numColumns; j++) { if (j != i) { coef = tmpMatrix[j].GetCoefficient(i); if (coef != 0) { PolynomialGF2mSmallM tmpSqColumn = tmpMatrix[i].MultWithElement(coef); PolynomialGF2mSmallM tmpInvColumn = _sqRootMatrix[i].MultWithElement(coef); tmpMatrix[j].AddToThis(tmpSqColumn); lock (_sqRootMatrix) _sqRootMatrix[j].AddToThis(tmpInvColumn); } } } } } }
/// <summary> /// Compute the product of this polynomial and another polynomial modulo a third polynomial /// </summary> /// /// <param name="A">The polynomial</param> /// <param name="B">The reduction polynomial</param> /// /// <returns>Returns <c>this * a mod b</c></returns> public PolynomialGF2mSmallM ModMultiply(PolynomialGF2mSmallM A, PolynomialGF2mSmallM B) { int[] resultCoeff = ModMultiply(_coefficients, A._coefficients, B._coefficients, _field); return(new PolynomialGF2mSmallM(_field, resultCoeff)); }
/// <summary> /// Compute the matrix for computing square roots in this polynomial ring by inverting the squaring matrix /// </summary> private void ComputeSquareRootMatrix() { int numColumns = _poly.Degree; // clone squaring matrix PolynomialGF2mSmallM[] tmpMatrix = new PolynomialGF2mSmallM[numColumns]; for (int i = numColumns - 1; i >= 0; i--) { tmpMatrix[i] = new PolynomialGF2mSmallM(_sqMatrix[i]); } // initialize square root matrix as unit matrix _sqRootMatrix = new PolynomialGF2mSmallM[numColumns]; for (int i = numColumns - 1; i >= 0; i--) { _sqRootMatrix[i] = new PolynomialGF2mSmallM(_field, i); } // simultaneously compute Gaussian reduction of squaring matrix and unit matrix for (int i = 0; i < numColumns; i++) { // if diagonal element is zero if (tmpMatrix[i].GetCoefficient(i) == 0) { bool foundNonZero = false; // find a non-zero element in the same row for (int j = i + 1; j < numColumns; j++) { if (tmpMatrix[j].GetCoefficient(i) != 0) { // found it, swap columns ... foundNonZero = true; SwapColumns(tmpMatrix, i, j); SwapColumns(_sqRootMatrix, i, j); // ... and quit searching j = numColumns; continue; } } // if no non-zero element was found the matrix is not invertible if (!foundNonZero) { throw new ArithmeticException("Squaring matrix is not invertible."); } } // normalize i-th column int coef = tmpMatrix[i].GetCoefficient(i); int invCoef = _field.Inverse(coef); tmpMatrix[i].MultThisWithElement(invCoef); _sqRootMatrix[i].MultThisWithElement(invCoef); if (ParallelUtils.IsParallel) { // normalize all other columns Parallel.For(0, numColumns, j => { if (j != i) { int coefp = tmpMatrix[j].GetCoefficient(i); if (coefp != 0) { PolynomialGF2mSmallM tmpSqColumn = tmpMatrix[i].MultWithElement(coefp); PolynomialGF2mSmallM tmpInvColumn = _sqRootMatrix[i].MultWithElement(coefp); tmpMatrix[j].AddToThis(tmpSqColumn); lock (_sqRootMatrix) _sqRootMatrix[j].AddToThis(tmpInvColumn); } } }); } else { for (int j = 0; j < numColumns; j++) { if (j != i) { coef = tmpMatrix[j].GetCoefficient(i); if (coef != 0) { PolynomialGF2mSmallM tmpSqColumn = tmpMatrix[i].MultWithElement(coef); PolynomialGF2mSmallM tmpInvColumn = _sqRootMatrix[i].MultWithElement(coef); tmpMatrix[j].AddToThis(tmpSqColumn); lock (_sqRootMatrix) _sqRootMatrix[j].AddToThis(tmpInvColumn); } } } } } }
/// <summary> /// Generate an encryption Key pair /// </summary> /// /// <returns>A McElieceKeyPair containing public and private keys</returns> public IAsymmetricKeyPair GenerateKeyPair() { // finite field GF(2^m) GF2mField field = new GF2mField(_M, _fieldPoly); // irreducible Goppa polynomial PolynomialGF2mSmallM gp = new PolynomialGF2mSmallM(field, _T, PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL, _rngEngine); PolynomialRingGF2m ring = new PolynomialRingGF2m(field, gp); // matrix for computing square roots in (GF(2^m))^t PolynomialGF2mSmallM[] qInv = ring.SquareRootMatrix; // generate canonical check matrix GF2Matrix h = GoppaCode.CreateCanonicalCheckMatrix(field, gp); // compute short systematic form of check matrix GoppaCode.MaMaPe mmp = GoppaCode.ComputeSystematicForm(h, _rngEngine); GF2Matrix shortH = mmp.SecondMatrix; Permutation p = mmp.Permutation; // compute short systematic form of generator matrix GF2Matrix shortG = (GF2Matrix)shortH.ComputeTranspose(); // obtain number of rows of G (= dimension of the code) int k = shortG.RowCount; // generate keys IAsymmetricKey pubKey = new MPKCPublicKey(_N, _T, shortG); IAsymmetricKey privKey = new MPKCPrivateKey(_N, k, field, gp, p, h, qInv); // return key pair return new MPKCKeyPair(pubKey, privKey); }
private void Dispose(bool Disposing) { if (!_isDisposed && Disposing) { try { if (_gField != null) { _gField.Clear(); _gField = null; } if (_goppaPoly != null) { _goppaPoly.Clear(); _goppaPoly = null; } if (_H != null) { _H.Clear(); _H = null; } if (_P1 != null) { _P1.Clear(); _P1 = null; } if (_qInv != null) { for (int i = 0; i < _qInv.Length; i++) { _qInv[i].Clear(); _qInv[i] = null; } _qInv = null; } _K = 0; _N = 0; } catch { } _isDisposed = true; } }
/// <summary> /// Compute the result of the division of this polynomial by another polynomial modulo a third polynomial /// </summary> /// /// <param name="Divisor">The divisor</param> /// <param name="Modulus">The reduction polynomial</param> /// /// <returns>Returns <c>this * divisor^(-1) mod modulus</c></returns> public PolynomialGF2mSmallM ModDivide(PolynomialGF2mSmallM Divisor, PolynomialGF2mSmallM Modulus) { int[] resultCoeff = ModDiv(_coefficients, Divisor._coefficients, Modulus._coefficients, _field); return new PolynomialGF2mSmallM(_field, resultCoeff); }