/// <summary> /// Compute the result of the division of two polynomials over the field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The first polynomial</param> /// <param name="F">The second polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>int[][] {q,r}</c>, where <c>a = q*f+r</c> and <c>deg(r) < deg(f)</c></returns> private static int[][] Divide(int[] A, int[] F, GF2mField GF2) { int df = ComputeDegree(F); int da = ComputeDegree(A) + 1; if (df == -1) { throw new ArithmeticException("Division by zero."); } int[][] result = new int[2][]; result[0] = new int[1]; result[1] = new int[da]; int hc = HeadCoefficient(F); hc = GF2.Inverse(hc); result[0][0] = 0; Array.Copy(A, 0, result[1], 0, result[1].Length); while (df <= ComputeDegree(result[1])) { int[] q; int[] coeff = new int[1]; coeff[0] = GF2.Multiply(HeadCoefficient(result[1]), hc); q = MultWithElement(F, coeff[0], GF2); int n = ComputeDegree(result[1]) - df; q = MultWithMonomial(q, n); coeff = MultWithMonomial(coeff, n); result[0] = Add(coeff, result[0], GF2); result[1] = Add(q, result[1], GF2); } return(result); }
/// <summary> /// Construct a monomial of the given degree over the finite field GF(2^m) /// </summary> /// /// <param name="Field">The finite field GF(2^m)</param> /// <param name="Degree">The degree of the monomial</param> public PolynomialGF2mSmallM(GF2mField Field, int Degree) { _field = Field; _degree = Degree; _coefficients = new int[Degree + 1]; _coefficients[Degree] = 1; }
/// <summary> /// Creates the vector over GF(2^m) of given length and with elements from array V (beginning at the first bit) /// </summary> /// /// <param name="Field">The finite field</param> /// <param name="V">An array with elements of vector</param> public GF2mVector(GF2mField Field, byte[] V) { _field = new GF2mField(Field); // decode vector int d = 8; int count = 1; while (Field.Degree > d) { count++; d += 8; } if ((V.Length % count) != 0) throw new ArgumentException("GF2mVector: Byte array is not an encoded vector over the given finite field!"); Length = V.Length / count; _vector = new int[Length]; count = 0; for (int i = 0; i < _vector.Length; i++) { for (int j = 0; j < d; j += 8) _vector[i] |= (V[count++] & 0xff) << j; if (!Field.IsElementOfThisField(_vector[i])) throw new ArgumentException("GF2mVector: Byte array is not an encoded vector over the given finite field!"); } }
/// <summary> /// Reduce a polynomial modulo another polynomial /// </summary> /// /// <param name="A">The polynomial</param> /// <param name="F">The reduction polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>a mod f</c></returns> private static int[] Mod(int[] A, int[] F, GF2mField GF2) { int df = ComputeDegree(F); if (df == -1) { throw new ArithmeticException("Division by zero"); } int[] result = new int[A.Length]; int hc = HeadCoefficient(F); hc = GF2.Inverse(hc); Array.Copy(A, 0, result, 0, result.Length); while (df <= ComputeDegree(result)) { int[] q; int coeff = GF2.Multiply(HeadCoefficient(result), hc); q = MultWithMonomial(F, ComputeDegree(result) - df); q = MultWithElement(q, coeff, GF2); result = Add(q, result, GF2); } return(result); }
/// <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) { m_field = Field; m_poly = Poly; ComputeSquaringMatrix(); ComputeSquareRootMatrix(); }
/// <summary> /// Create an instance using values from a field and matrix /// </summary> /// /// <param name="FieldG">A finite field GF(2^m)</param> /// <param name="MatrixN">The matrix as int array; only the reference is copied.</param> protected GF2mMatrix(GF2mField FieldG, int[][] MatrixN) { this.FieldG = FieldG; this.MatrixN = MatrixN; RowCount = MatrixN.Length; ColumnCount = MatrixN[0].Length; }
/// <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> /// Rewrite this vector as a vector over <c>GF(2^m)</c> with <c>t</c> elements /// </summary> /// /// <param name="Field">The finite field <c>GF(2<sup>m</sup>)</c></param> /// /// <returns>Returns the converted vector over <c>GF(2<sup>m</sup>)</c></returns> public GF2mVector ToExtensionFieldVector(GF2mField Field) { int m = Field.Degree; if ((Length % m) != 0) { throw new ArithmeticException("GF2Vector: Conversion is impossible!"); } int t = Length / m; int[] result = new int[t]; int count = 0; for (int i = t - 1; i >= 0; i--) { for (int j = Field.Degree - 1; j >= 0; j--) { int q = IntUtils.URShift(count, 5); int r = count & 0x1f; int e = (IntUtils.URShift(m_elements[q], r)) & 1; if (e == 1) { result[i] ^= 1 << j; } count++; } } return(new GF2mVector(Field, result)); }
/// <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> /// Create an instance using values from another GF2mMatrix instance /// </summary> /// /// <param name="G">The GF2mMatrix instance</param> public GF2mMatrix(GF2mMatrix G) { RowCount = G.RowCount; ColumnCount = G.ColumnCount; FieldG = G.FieldG; MatrixN = new int[RowCount][]; for (int i = 0; i < RowCount; i++) MatrixN[i] = IntUtils.DeepCopy(G.MatrixN[i]); }
/// <summary> /// Create a new vector over <c>GF(2^m)</c> of the given length and element array /// </summary> /// /// <param name="Field">The finite field <c>GF(2^m)</c></param> /// <param name="Vector">The element array</param> public GF2mVector(GF2mField Field, int[] Vector) { _field = Field; Length = Vector.Length; for (int i = Vector.Length - 1; i >= 0; i--) { if (!Field.IsElementOfThisField(Vector[i])) throw new ArithmeticException("Element array is not specified over the given finite field."); } _vector = IntUtils.DeepCopy(Vector); }
/// <summary> /// Reads a Private Key from a Stream /// </summary> /// /// <param name="KeyStream">An input stream containing an encoded key</param> /// /// <exception cref="CryptoAsymmetricException">Thrown if the key could not be loaded</exception> public MPKCPrivateKey(Stream KeyStream) { try { int len; BinaryReader reader = new BinaryReader(KeyStream); // length _N = reader.ReadInt32(); // dimension _K = reader.ReadInt32(); // gf byte[] gf = reader.ReadBytes(GF_LENGTH); _gField = new GF2mField(gf); // gp len = reader.ReadInt32(); byte[] gp = reader.ReadBytes(len); _goppaPoly = new PolynomialGF2mSmallM(_gField, gp); // p1 len = reader.ReadInt32(); byte[] p1 = reader.ReadBytes(len); _P1 = new Permutation(p1); // check matrix len = reader.ReadInt32(); byte[] h = reader.ReadBytes(len); _H = new GF2Matrix(h); // length of first dimension len = reader.ReadInt32(); byte[][] qi = new byte[len][]; // get the qinv encoded array for (int i = 0; i < qi.Length; i++) { len = reader.ReadInt32(); qi[i] = reader.ReadBytes(len); } // assign qinv _qInv = new PolynomialGF2mSmallM[qi.Length]; for (int i = 0; i < QInv.Length; i++) _qInv[i] = new PolynomialGF2mSmallM(_gField, qi[i]); } catch (Exception ex) { throw new CryptoAsymmetricException("MPKCPrivateKey:CTor", "The Private key could not be loaded!", ex); } }
/// <summary> /// Create an instance using values from another GF2mMatrix instance /// </summary> /// /// <param name="G">The GF2mMatrix instance</param> public GF2mMatrix(GF2mMatrix G) { RowCount = G.RowCount; ColumnCount = G.ColumnCount; FieldG = G.FieldG; MatrixN = new int[RowCount][]; for (int i = 0; i < RowCount; i++) { MatrixN[i] = IntUtils.DeepCopy(G.MatrixN[i]); } }
/// <summary> /// Create a new vector over <c>GF(2^m)</c> of the given length and element array /// </summary> /// /// <param name="Field">The finite field <c>GF(2^m)</c></param> /// <param name="Vector">The element array</param> public GF2mVector(GF2mField Field, int[] Vector) { m_field = Field; Length = Vector.Length; for (int i = Vector.Length - 1; i >= 0; i--) { if (!Field.IsElementOfThisField(Vector[i])) { throw new ArithmeticException("Element array is not specified over the given finite field."); } } m_vector = IntUtils.DeepCopy(Vector); }
/// <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> /// Checks if the given object is equal to this field /// </summary> /// /// <param name="Obj">The object for comparison</param> /// /// <returns>Returns false if the object is not equal</returns> public override bool Equals(Object Obj) { if (Obj == null) { return(false); } if (!(Obj is GF2mField)) { return(false); } GF2mField other = (GF2mField)Obj; return((m_degree == other.m_degree) && (m_polynomial == other.m_polynomial)); }
/// <summary> /// Construct a polynomial over the finite field GF(2^m) /// </summary> /// /// <param name="Field">The finite field GF(2^m)</param> /// <param name="Degree">The degree of polynomial</param> /// <param name="PolynomialType">The type of polynomial</param> /// <param name="Rand">The IRandom instance</param> public PolynomialGF2mSmallM(GF2mField Field, int Degree, char PolynomialType, IRandom Rand) { _field = Field; switch (PolynomialType) { case PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL: _coefficients = CreateRandomIrreduciblePolynomial(Degree, Rand); break; default: throw new ArgumentException(" Error: type " + PolynomialType + " is not defined for GF2smallmPolynomial"); } ComputeDegree(); }
/// <summary> /// Initialze this class with an encoded matrix /// </summary> /// /// <param name="FieldG">The finite field GF(2^m)</param> /// <param name="Encoded">The matrix in byte array form</param> public GF2mMatrix(GF2mField FieldG, byte[] Encoded) { this.FieldG = FieldG; int d = 8; int count = 1; while (FieldG.Degree > d) { count++; d += 8; } if (Encoded.Length < 5) { throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!"); } this.RowCount = ((Encoded[3] & 0xff) << 24) ^ ((Encoded[2] & 0xff) << 16) ^ ((Encoded[1] & 0xff) << 8) ^ (Encoded[0] & 0xff); int n = count * this.RowCount; if ((this.RowCount <= 0) || (((Encoded.Length - 4) % n) != 0)) { throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!"); } this.ColumnCount = (Encoded.Length - 4) / n; MatrixN = ArrayUtils.CreateJagged <int[][]>(this.RowCount, this.ColumnCount); count = 4; for (int i = 0; i < this.RowCount; i++) { for (int j = 0; j < this.ColumnCount; j++) { for (int k = 0; k < d; k += 8) { MatrixN[i][j] ^= (Encoded[count++] & 0x000000ff) << k; } if (!this.FieldG.IsElementOfThisField(MatrixN[i][j])) { throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!"); } } } }
/// <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> /// Return the greatest common divisor of two polynomials over the field <c>GF(2^m)</c> /// </summary> /// /// <param name="F">The first polynomial</param> /// <param name="G">The second polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>Gcd(f, g)</c></returns> private static int[] Gcd(int[] F, int[] G, GF2mField GF2) { int[] a = F; int[] b = G; if (ComputeDegree(a) == -1) { return(b); } while (ComputeDegree(b) != -1) { int[] c = Mod(a, b, GF2); a = new int[b.Length]; Array.Copy(b, 0, a, 0, a.Length); b = new int[c.Length]; Array.Copy(c, 0, b, 0, b.Length); } int coeff = GF2.Inverse(HeadCoefficient(a)); return(MultWithElement(a, coeff, GF2)); }
/// <summary> /// Create a polynomial over the finite field GF(2^m) /// </summary> /// /// <param name="Field">The finite field GF(2^m)</param> /// <param name="Encoded">The polynomial in byte array form</param> public PolynomialGF2mSmallM(GF2mField Field, byte[] Encoded) { _field = Field; int d = 8; int count = 1; while (Field.Degree > d) { count++; d += 8; } if ((Encoded.Length % count) != 0) { throw new ArgumentException("PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m!"); } _coefficients = new int[Encoded.Length / count]; count = 0; for (int i = 0; i < _coefficients.Length; i++) { for (int j = 0; j < d; j += 8) { _coefficients[i] ^= (Encoded[count++] & 0x000000ff) << j; } if (!this._field.IsElementOfThisField(_coefficients[i])) { throw new ArgumentException(" PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m!"); } } // if HC = 0 for non-zero polynomial, returns error if ((_coefficients.Length != 1) && (_coefficients[_coefficients.Length - 1] == 0)) { throw new ArgumentException("PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m"); } ComputeDegree(); }
/// <summary> /// Compute the product of a polynomial a with an element from the finite field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The polynomial</param> /// <param name="Element">An element of the finite field GF(2^m)</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Return <c>a * element</c></returns> private static int[] MultWithElement(int[] A, int Element, GF2mField GF2) { int degree = ComputeDegree(A); if (degree == -1 || Element == 0) { return(new int[1]); } if (Element == 1) { return(IntUtils.DeepCopy(A)); } int[] result = new int[degree + 1]; for (int i = degree; i >= 0; i--) { result[i] = GF2.Multiply(A[i], Element); } return(result); }
/// <summary> /// Compute the sum of two polynomials a and b over the finite field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The first polynomial</param> /// <param name="B">The second polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Return a + b</returns> private static int[] Add(int[] A, int[] B, GF2mField GF2) { int[] result, addend; if (A.Length < B.Length) { result = new int[B.Length]; Array.Copy(B, 0, result, 0, B.Length); addend = A; } else { result = new int[A.Length]; Array.Copy(A, 0, result, 0, A.Length); addend = B; } for (int i = addend.Length - 1; i >= 0; i--) { result[i] = GF2.Add(result[i], addend[i]); } return(result); }
/// <summary> /// Initialze this class with an encoded matrix /// </summary> /// /// <param name="FieldG">The finite field GF(2^m)</param> /// <param name="Encoded">The matrix in byte array form</param> public GF2mMatrix(GF2mField FieldG, byte[] Encoded) { this.FieldG = FieldG; int d = 8; int count = 1; while (FieldG.Degree > d) { count++; d += 8; } if (Encoded.Length < 5) throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!"); this.RowCount = ((Encoded[3] & 0xff) << 24) ^ ((Encoded[2] & 0xff) << 16) ^ ((Encoded[1] & 0xff) << 8) ^ (Encoded[0] & 0xff); int n = count * this.RowCount; if ((this.RowCount <= 0) || (((Encoded.Length - 4) % n) != 0)) throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!"); this.ColumnCount = (Encoded.Length - 4) / n; MatrixN = ArrayUtils.CreateJagged<int[][]>(this.RowCount, this.ColumnCount); count = 4; for (int i = 0; i < this.RowCount; i++) { for (int j = 0; j < this.ColumnCount; j++) { for (int k = 0; k < d; k += 8) MatrixN[i][j] ^= (Encoded[count++] & 0x000000ff) << k; if (!this.FieldG.IsElementOfThisField(MatrixN[i][j])) throw new ArgumentException("GF2mMatrix: Given array is not encoded matrix over GF(2^m)!"); } } }
/// <summary> /// Creates the vector over GF(2^m) of given length and with elements from array V (beginning at the first bit) /// </summary> /// /// <param name="Field">The finite field</param> /// <param name="V">An array with elements of vector</param> public GF2mVector(GF2mField Field, byte[] V) { m_field = new GF2mField(Field); // decode vector int d = 8; int count = 1; while (Field.Degree > d) { count++; d += 8; } if ((V.Length % count) != 0) { throw new ArgumentException("GF2mVector: Byte array is not an encoded vector over the given finite field!"); } Length = V.Length / count; m_vector = new int[Length]; count = 0; for (int i = 0; i < m_vector.Length; i++) { for (int j = 0; j < d; j += 8) { m_vector[i] |= (V[count++] & 0xff) << j; } if (!Field.IsElementOfThisField(m_vector[i])) { throw new ArgumentException("GF2mVector: Byte array is not an encoded vector over the given finite field!"); } } }
/// <summary> /// Compute the result of the division of two polynomials modulo a third polynomial over the field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The first polynomial</param> /// <param name="B">The second polynomial</param> /// <param name="G">The reduction polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>a * b^(-1) mod g</c></returns> private static int[] ModDiv(int[] A, int[] B, int[] G, GF2mField GF2) { int[] r0 = NormalForm(G); int[] r1 = Mod(B, G, GF2); int[] s0 = { 0 }; int[] s1 = Mod(A, G, GF2); int[] s2; int[][] q; while (ComputeDegree(r1) != -1) { q = Divide(r0, r1, GF2); r0 = NormalForm(r1); r1 = NormalForm(q[1]); s2 = Add(s0, ModMultiply(q[0], s1, G, GF2), GF2); s0 = NormalForm(s1); s1 = NormalForm(s2); } int hc = HeadCoefficient(r0); s0 = MultWithElement(s0, GF2.Inverse(hc), GF2); return(s0); }
/// <summary> /// Create a polynomial over the finite field GF(2^m) /// </summary> /// /// <param name="Field">The finite field GF(2^m)</param> /// <param name="Encoded">The polynomial in byte array form</param> public PolynomialGF2mSmallM(GF2mField Field, byte[] Encoded) { _field = Field; int d = 8; int count = 1; while (Field.Degree > d) { count++; d += 8; } if ((Encoded.Length % count) != 0) throw new ArgumentException("PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m!"); _coefficients = new int[Encoded.Length / count]; count = 0; for (int i = 0; i < _coefficients.Length; i++) { for (int j = 0; j < d; j += 8) _coefficients[i] ^= (Encoded[count++] & 0x000000ff) << j; if (!this._field.IsElementOfThisField(_coefficients[i])) throw new ArgumentException(" PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m!"); } // if HC = 0 for non-zero polynomial, returns error if ((_coefficients.Length != 1) && (_coefficients[_coefficients.Length - 1] == 0)) throw new ArgumentException("PolynomialGF2mSmallM: byte array is not encoded polynomial over given finite field GF2m"); ComputeDegree(); }
/// <summary> /// Compute the product of a polynomial a with an element from the finite field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The polynomial</param> /// <param name="Element">An element of the finite field GF(2^m)</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Return <c>a * element</c></returns> private static int[] MultWithElement(int[] A, int Element, GF2mField GF2) { int degree = ComputeDegree(A); if (degree == -1 || Element == 0) return new int[1]; if (Element == 1) return IntUtils.DeepCopy(A); int[] result = new int[degree + 1]; for (int i = degree; i >= 0; i--) result[i] = GF2.Multiply(A[i], Element); return result; }
/// <summary> /// Check a polynomial for irreducibility over the field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The polynomial to check</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns true if a is irreducible, false otherwise</returns> private static bool IsIrreducible(int[] A, GF2mField GF2) { if (A[0] == 0) { return(false); } bool state = true; int d = ComputeDegree(A) >> 1; int[] u = { 0, 1 }; int[] Y = { 0, 1 }; int fieldDegree = GF2.Degree; if (ParallelUtils.IsParallel) { CancellationTokenSource cts = new CancellationTokenSource(); ParallelOptions options = new ParallelOptions(); options.MaxDegreeOfParallelism = Environment.ProcessorCount; options.CancellationToken = cts.Token; options.CancellationToken.ThrowIfCancellationRequested(); try { Parallel.For(0, d, options, loopState => { if (!cts.IsCancellationRequested) { for (int j = fieldDegree - 1; j >= 0; j--) { u = ModMultiply(u, u, A, GF2); } u = NormalForm(u); int[] g = Gcd(Add(u, Y, GF2), A, GF2); if (ComputeDegree(g) != 0) { state = false; cts.Cancel(); } } }); } catch { } } else { for (int i = 0; i < d; i++) { for (int j = fieldDegree - 1; j >= 0; j--) { u = ModMultiply(u, u, A, GF2); } u = NormalForm(u); int[] g = Gcd(Add(u, Y, GF2), A, GF2); if (ComputeDegree(g) != 0) { state = false; } } } return(state); }
/// <summary> /// Rewrite this vector as a vector over <c>GF(2^m)</c> with <c>t</c> elements /// </summary> /// /// <param name="Field">The finite field <c>GF(2<sup>m</sup>)</c></param> /// /// <returns>Returns the converted vector over <c>GF(2<sup>m</sup>)</c></returns> public GF2mVector ToExtensionFieldVector(GF2mField Field) { int m = Field.Degree; if ((Length % m) != 0) throw new ArithmeticException("GF2Vector: Conversion is impossible!"); int t = Length / m; int[] result = new int[t]; int count = 0; for (int i = t - 1; i >= 0; i--) { for (int j = Field.Degree - 1; j >= 0; j--) { int q = IntUtils.URShift(count, 5); int r = count & 0x1f; int e = (IntUtils.URShift(_elements[q], r)) & 1; if (e == 1) result[i] ^= 1 << j; count++; } } return new GF2mVector(Field, result); }
/// <summary> /// Compute the result of the division of two polynomials modulo a third polynomial over the field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The first polynomial</param> /// <param name="B">The second polynomial</param> /// <param name="G">The reduction polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>a * b^(-1) mod g</c></returns> private static int[] ModDiv(int[] A, int[] B, int[] G, GF2mField GF2) { int[] r0 = NormalForm(G); int[] r1 = Mod(B, G, GF2); int[] s0 = { 0 }; int[] s1 = Mod(A, G, GF2); int[] s2; int[][] q; while (ComputeDegree(r1) != -1) { q = Divide(r0, r1, GF2); r0 = NormalForm(r1); r1 = NormalForm(q[1]); s2 = Add(s0, ModMultiply(q[0], s1, G, GF2), GF2); s0 = NormalForm(s1); s1 = NormalForm(s2); } int hc = HeadCoefficient(r0); s0 = MultWithElement(s0, GF2.Inverse(hc), GF2); return s0; }
/// <summary> /// The copy constructor /// </summary> /// /// <param name="GF">The GF2mVector to copy</param> public GF2mVector(GF2mVector GF) { _field = new GF2mField(GF._field); Length = GF.Length; _vector = IntUtils.DeepCopy(GF._vector); }
/// <summary> /// Construct the polynomial over the given finite field GF(2^m) from the given coefficient vector /// </summary> /// /// <param name="Field">The finite field GF2m</param> /// <param name="Coeffs">The coefficient vector</param> public PolynomialGF2mSmallM(GF2mField Field, int[] Coeffs) { _field = Field; _coefficients = NormalForm(Coeffs); ComputeDegree(); }
/// <summary> /// Compute the result of the division of two polynomials over the field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The first polynomial</param> /// <param name="F">The second polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>int[][] {q,r}</c>, where <c>a = q*f+r</c> and <c>deg(r) < deg(f)</c></returns> private static int[][] Divide(int[] A, int[] F, GF2mField GF2) { int df = ComputeDegree(F); int da = ComputeDegree(A) + 1; if (df == -1) throw new ArithmeticException("Division by zero."); int[][] result = new int[2][]; result[0] = new int[1]; result[1] = new int[da]; int hc = HeadCoefficient(F); hc = GF2.Inverse(hc); result[0][0] = 0; Array.Copy(A, 0, result[1], 0, result[1].Length); while (df <= ComputeDegree(result[1])) { int[] q; int[] coeff = new int[1]; coeff[0] = GF2.Multiply(HeadCoefficient(result[1]), hc); q = MultWithElement(F, coeff[0], GF2); int n = ComputeDegree(result[1]) - df; q = MultWithMonomial(q, n); coeff = MultWithMonomial(coeff, n); result[0] = Add(coeff, result[0], GF2); result[1] = Add(q, result[1], GF2); } return result; }
/// <summary> /// The copy constructor /// </summary> /// /// <param name="GF">The GF2mVector to copy</param> public GF2mVector(GF2mVector GF) { m_field = new GF2mField(GF.m_field); Length = GF.Length; m_vector = IntUtils.DeepCopy(GF.m_vector); }
/// <summary> /// Construct the zero polynomial over the finite field GF(2^m) /// </summary> /// /// <param name="Field">The finite field GF(2^m)</param> public PolynomialGF2mSmallM(GF2mField Field) { _field = Field; _degree = -1; _coefficients = new int[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> /// Create a finite field GF(2^m) using another GF2mField class /// </summary> /// /// <param name="Field">The GF2mField class to copy</param> public GF2mField(GF2mField Field) { _degree = Field._degree; _polynomial = Field._polynomial; }
/// <summary> /// Compute the product of two polynomials modulo a third polynomial over the finite field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The first polynomial</param> /// <param name="B">The second polynomial</param> /// <param name="G">The reduction polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>a * b mod g</c></returns> private static int[] ModMultiply(int[] A, int[] B, int[] G, GF2mField GF2) { return(Mod(Multiply(A, B, GF2), G, GF2)); }
/// <summary> /// Get a randome element over degree Gf2 /// </summary> /// /// <param name="SecRnd">The source of randomness</param> /// <param name="GFM">The Gf2 field</param> /// /// <returns>A random element</returns> private static int GetRandomElement(IRandom SecRnd, GF2mField GFM) { return RandomDegree.NextInt(SecRnd, 1 << GFM.Degree); }
/// <summary> /// Check a polynomial for irreducibility over the field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The polynomial to check</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns true if a is irreducible, false otherwise</returns> private static bool IsIrreducible(int[] A, GF2mField GF2) { if (A[0] == 0) return false; bool state = true; int d = ComputeDegree(A) >> 1; int[] u = { 0, 1 }; int[] Y = { 0, 1 }; int fieldDegree = GF2.Degree; if (ParallelUtils.IsParallel) { CancellationTokenSource cts = new CancellationTokenSource(); ParallelOptions options = new ParallelOptions(); options.MaxDegreeOfParallelism = Environment.ProcessorCount; options.CancellationToken = cts.Token; options.CancellationToken.ThrowIfCancellationRequested(); try { Parallel.For(0, d, options, loopState => { if (!cts.IsCancellationRequested) { for (int j = fieldDegree - 1; j >= 0; j--) u = ModMultiply(u, u, A, GF2); u = NormalForm(u); int[] g = Gcd(Add(u, Y, GF2), A, GF2); if (ComputeDegree(g) != 0) { state = false; cts.Cancel(); } } }); } catch { } } else { for (int i = 0; i < d; i++) { for (int j = fieldDegree - 1; j >= 0; j--) u = ModMultiply(u, u, A, GF2); u = NormalForm(u); int[] g = Gcd(Add(u, Y, GF2), A, GF2); if (ComputeDegree(g) != 0) state = false; } } return state; }
/// <summary> /// Compute the sum of two polynomials a and b over the finite field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The first polynomial</param> /// <param name="B">The second polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Return a + b</returns> private static int[] Add(int[] A, int[] B, GF2mField GF2) { int[] result, addend; if (A.Length < B.Length) { result = new int[B.Length]; Array.Copy(B, 0, result, 0, B.Length); addend = A; } else { result = new int[A.Length]; Array.Copy(A, 0, result, 0, A.Length); addend = B; } for (int i = addend.Length - 1; i >= 0; i--) result[i] = GF2.Add(result[i], addend[i]); return result; }
/// <summary> /// Compute the product of two polynomials over the field <c>GF(2^m)</c> using a Karatzuba like multiplication /// </summary> /// /// <param name="A">The first polynomial</param> /// <param name="B">The second polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>a * b</c></returns> private static int[] Multiply(int[] A, int[] B, GF2mField GF2) { int[] mult1, mult2; if (ComputeDegree(A) < ComputeDegree(B)) { mult1 = B; mult2 = A; } else { mult1 = A; mult2 = B; } mult1 = NormalForm(mult1); mult2 = NormalForm(mult2); if (mult2.Length == 1) { return(MultWithElement(mult1, mult2[0], GF2)); } int d1 = mult1.Length; int d2 = mult2.Length; int[] result = new int[d1 + d2 - 1]; if (d2 != d1) { int[] res1 = new int[d2]; int[] res2 = new int[d1 - d2]; Array.Copy(mult1, 0, res1, 0, res1.Length); Array.Copy(mult1, d2, res2, 0, res2.Length); res1 = Multiply(res1, mult2, GF2); res2 = Multiply(res2, mult2, GF2); res2 = MultWithMonomial(res2, d2); result = Add(res1, res2, GF2); } else { d2 = IntUtils.URShift((d1 + 1), 1); int d = d1 - d2; int[] firstPartMult1 = new int[d2]; int[] firstPartMult2 = new int[d2]; int[] secondPartMult1 = new int[d]; int[] secondPartMult2 = new int[d]; Array.Copy(mult1, 0, firstPartMult1, 0, firstPartMult1.Length); Array.Copy(mult1, d2, secondPartMult1, 0, secondPartMult1.Length); Array.Copy(mult2, 0, firstPartMult2, 0, firstPartMult2.Length); Array.Copy(mult2, d2, secondPartMult2, 0, secondPartMult2.Length); int[] helpPoly1 = Add(firstPartMult1, secondPartMult1, GF2); int[] helpPoly2 = Add(firstPartMult2, secondPartMult2, GF2); int[] res1 = Multiply(firstPartMult1, firstPartMult2, GF2); int[] res2 = Multiply(helpPoly1, helpPoly2, GF2); int[] res3 = Multiply(secondPartMult1, secondPartMult2, GF2); res2 = Add(res2, res1, GF2); res2 = Add(res2, res3, GF2); res3 = MultWithMonomial(res3, d2); result = Add(res2, res3, GF2); result = MultWithMonomial(result, d2); result = Add(result, res1, GF2); } return(result); }
/// <summary> /// Return the greatest common divisor of two polynomials over the field <c>GF(2^m)</c> /// </summary> /// /// <param name="F">The first polynomial</param> /// <param name="G">The second polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>Gcd(f, g)</c></returns> private static int[] Gcd(int[] F, int[] G, GF2mField GF2) { int[] a = F; int[] b = G; if (ComputeDegree(a) == -1) return b; while (ComputeDegree(b) != -1) { int[] c = Mod(a, b, GF2); a = new int[b.Length]; Array.Copy(b, 0, a, 0, a.Length); b = new int[c.Length]; Array.Copy(c, 0, b, 0, b.Length); } int coeff = GF2.Inverse(HeadCoefficient(a)); return MultWithElement(a, coeff, GF2); }
/// <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> /// 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 product of two polynomials modulo a third polynomial over the finite field <c>GF(2^m)</c> /// </summary> /// /// <param name="A">The first polynomial</param> /// <param name="B">The second polynomial</param> /// <param name="G">The reduction polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>a * b mod g</c></returns> private static int[] ModMultiply(int[] A, int[] B, int[] G, GF2mField GF2) { return Mod(Multiply(A, B, GF2), G, GF2); }
/// <summary> /// Reduce a polynomial modulo another polynomial /// </summary> /// /// <param name="A">The polynomial</param> /// <param name="F">The reduction polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>a mod f</c></returns> private static int[] Mod(int[] A, int[] F, GF2mField GF2) { int df = ComputeDegree(F); if (df == -1) throw new ArithmeticException("Division by zero"); int[] result = new int[A.Length]; int hc = HeadCoefficient(F); hc = GF2.Inverse(hc); Array.Copy(A, 0, result, 0, result.Length); while (df <= ComputeDegree(result)) { int[] q; int coeff = GF2.Multiply(HeadCoefficient(result), hc); q = MultWithMonomial(F, ComputeDegree(result) - df); q = MultWithElement(q, coeff, GF2); result = Add(q, result, GF2); } return result; }
/// <summary> /// Create a finite field GF(2^m) using another GF2mField class /// </summary> /// /// <param name="Field">The GF2mField class to copy</param> public GF2mField(GF2mField Field) { m_degree = Field.m_degree; m_polynomial = Field.m_polynomial; }
/// <summary> /// Get a randome element over degree Gf2 /// </summary> /// /// <param name="SecRnd">The source of randomness</param> /// <param name="GFM">The Gf2 field</param> /// /// <returns>A random element</returns> private static int GetRandomElement(IRandom SecRnd, GF2mField GFM) { return(RandomDegree.NextInt(SecRnd, 1 << GFM.Degree)); }
/// <summary> /// Compute the product of two polynomials over the field <c>GF(2^m)</c> using a Karatzuba like multiplication /// </summary> /// /// <param name="A">The first polynomial</param> /// <param name="B">The second polynomial</param> /// <param name="GF2">The GF2 field</param> /// /// <returns>Returns <c>a * b</c></returns> private static int[] Multiply(int[] A, int[] B, GF2mField GF2) { int[] mult1, mult2; if (ComputeDegree(A) < ComputeDegree(B)) { mult1 = B; mult2 = A; } else { mult1 = A; mult2 = B; } mult1 = NormalForm(mult1); mult2 = NormalForm(mult2); if (mult2.Length == 1) return MultWithElement(mult1, mult2[0], GF2); int d1 = mult1.Length; int d2 = mult2.Length; int[] result = new int[d1 + d2 - 1]; if (d2 != d1) { int[] res1 = new int[d2]; int[] res2 = new int[d1 - d2]; Array.Copy(mult1, 0, res1, 0, res1.Length); Array.Copy(mult1, d2, res2, 0, res2.Length); res1 = Multiply(res1, mult2, GF2); res2 = Multiply(res2, mult2, GF2); res2 = MultWithMonomial(res2, d2); result = Add(res1, res2, GF2); } else { d2 = IntUtils.URShift((d1 + 1), 1); int d = d1 - d2; int[] firstPartMult1 = new int[d2]; int[] firstPartMult2 = new int[d2]; int[] secondPartMult1 = new int[d]; int[] secondPartMult2 = new int[d]; Array.Copy(mult1, 0, firstPartMult1, 0, firstPartMult1.Length); Array.Copy(mult1, d2, secondPartMult1, 0, secondPartMult1.Length); Array.Copy(mult2, 0, firstPartMult2, 0, firstPartMult2.Length); Array.Copy(mult2, d2, secondPartMult2, 0, secondPartMult2.Length); int[] helpPoly1 = Add(firstPartMult1, secondPartMult1, GF2); int[] helpPoly2 = Add(firstPartMult2, secondPartMult2, GF2); int[] res1 = Multiply(firstPartMult1, firstPartMult2, GF2); int[] res2 = Multiply(helpPoly1, helpPoly2, GF2); int[] res3 = Multiply(secondPartMult1, secondPartMult2, GF2); res2 = Add(res2, res1, GF2); res2 = Add(res2, res3, GF2); res3 = MultWithMonomial(res3, d2); result = Add(res2, res3, GF2); result = MultWithMonomial(result, d2); result = Add(result, res1, GF2); } return result; }
/// <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, _rndEngine); 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, _rndEngine); 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); }