/// <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)); }
/// <summary> /// The McEliece decryption primitive /// </summary> /// /// <param name="PrivateKey">The private key</param> /// <param name="C">The ciphertext vector <c>c = m*G + z</c></param> /// /// <returns>The message vector <c>m</c> and the error vector <c>z</c></returns> public static GF2Vector[] Decrypt(MPKCPrivateKey PrivateKey, GF2Vector C) { // obtain values from private key int k = PrivateKey.K; Permutation p = PrivateKey.P1; GF2mField field = PrivateKey.GF; PolynomialGF2mSmallM gp = PrivateKey.GP; GF2Matrix h = PrivateKey.H; PolynomialGF2mSmallM[] q = PrivateKey.QInv; // compute inverse permutation P^-1 Permutation pInv = p.ComputeInverse(); // multiply c with permutation P^-1 GF2Vector cPInv = (GF2Vector)C.Multiply(pInv); // compute syndrome of cP^-1 GF2Vector syndVec = (GF2Vector)h.RightMultiply(cPInv); // decode syndrome GF2Vector errors = GoppaCode.SyndromeDecode(syndVec, field, gp, q); GF2Vector mG = (GF2Vector)cPInv.Add(errors); // multiply codeword and error vector with P mG = (GF2Vector)mG.Multiply(p); errors = (GF2Vector)errors.Multiply(p); // extract plaintext vector (last k columns of mG) GF2Vector m = mG.ExtractRightVector(k); // return vectors return(new GF2Vector[] { m, errors }); }
/// <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) { m_N = N; m_K = K; m_gField = Gf; m_goppaPoly = Gp; m_P1 = P; m_H = H; m_qInv = QInv; }
/// <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 m_N = reader.ReadInt32(); // dimension m_K = reader.ReadInt32(); // gf byte[] gf = reader.ReadBytes(GF_LENGTH); m_gField = new GF2mField(gf); // gp len = reader.ReadInt32(); byte[] gp = reader.ReadBytes(len); m_goppaPoly = new PolynomialGF2mSmallM(m_gField, gp); // p1 len = reader.ReadInt32(); byte[] p1 = reader.ReadBytes(len); m_P1 = new Permutation(p1); // check matrix len = reader.ReadInt32(); byte[] h = reader.ReadBytes(len); m_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 m_qInv = new PolynomialGF2mSmallM[qi.Length]; for (int i = 0; i < QInv.Length; i++) { m_qInv[i] = new PolynomialGF2mSmallM(m_gField, qi[i]); } } catch (Exception ex) { throw new CryptoAsymmetricException("MPKCPrivateKey:CTor", "The Private key could not be loaded!", ex); } }
/// <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) { m_N = N; m_K = K; m_gField = new GF2mField(Gf); m_goppaPoly = new PolynomialGF2mSmallM(m_gField, Gp); m_P1 = new Permutation(P); m_H = new GF2Matrix(H); m_qInv = new PolynomialGF2mSmallM[QInv.Length]; for (int i = 0; i < QInv.Length; i++) { m_qInv[i] = new PolynomialGF2mSmallM(m_gField, QInv[i]); } }
private void Dispose(bool Disposing) { if (!m_isDisposed && Disposing) { try { if (m_gField != null) { m_gField.Clear(); m_gField = null; } if (m_goppaPoly != null) { m_goppaPoly.Clear(); m_goppaPoly = null; } if (m_H != null) { m_H.Clear(); m_H = null; } if (m_P1 != null) { m_P1.Clear(); m_P1 = null; } if (m_qInv != null) { for (int i = 0; i < m_qInv.Length; i++) { m_qInv[i].Clear(); m_qInv[i] = null; } m_qInv = null; } m_K = 0; m_N = 0; } catch { } m_isDisposed = true; } }
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; } }