/// <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> /// 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 }; }
private void TestEncode() { MPKCParameters mpar = (MPKCParameters)MPKCParamSets.MPKCFM11T40S256.DeepCopy(); MPKCKeyGenerator mkgen = new MPKCKeyGenerator(mpar); IAsymmetricKeyPair akp = mkgen.GenerateKeyPair(); MPKCPublicKey pub = (MPKCPublicKey)akp.PublicKey; byte[] enc = pub.ToBytes(); using (MPKCPublicKey pub2 = MPKCPublicKey.From(enc)) { if (!pub.Equals(pub2)) { throw new Exception("EncryptionKey: public key comparison test failed!"); } if (pub.GetHashCode() != pub2.GetHashCode()) { throw new Exception("EncryptionKey: public key hash test failed!"); } } OnProgress(new TestEventArgs("Passed public key serialization")); MemoryStream pubstr = pub.ToStream(); using (MPKCPublicKey pub2 = MPKCPublicKey.From(pubstr)) { if (!pub.Equals(pub2)) { throw new Exception("EncryptionKey: public key comparison test failed!"); } if (pub.GetHashCode() != pub2.GetHashCode()) { throw new Exception("EncryptionKey: public key hash test failed!"); } } pubstr.Dispose(); OnProgress(new TestEventArgs("Passed public key stream test")); MPKCPrivateKey pri = (MPKCPrivateKey)akp.PrivateKey; enc = pri.ToBytes(); using (MPKCPrivateKey pri2 = new MPKCPrivateKey(enc)) { if (!pri.Equals(pri2)) { throw new Exception("EncryptionKey: private key comparison test failed!"); } if (pri.GetHashCode() != pri2.GetHashCode()) { throw new Exception("EncryptionKey: private key hash test failed!"); } } OnProgress(new TestEventArgs("Passed private key serialization")); MemoryStream pristr = pri.ToStream(); using (MPKCPrivateKey pri2 = MPKCPrivateKey.From(pristr)) { if (!pri.Equals(pri2)) { throw new Exception("EncryptionKey: private key comparison test failed!"); } if (pri.GetHashCode() != pri2.GetHashCode()) { throw new Exception("EncryptionKey: private key hash test failed!"); } } pristr.Dispose(); OnProgress(new TestEventArgs("Passed private key stream test")); using (MPKCEncrypt mpe = new MPKCEncrypt(mpar)) { mpe.Initialize(akp.PublicKey); int sz = mpe.MaxPlainText - 1; byte[] data = new byte[sz]; new VTDev.Libraries.CEXEngine.Crypto.Prng.CSPPrng().GetBytes(data); enc = mpe.Encrypt(data); mpe.Initialize(akp.PrivateKey); byte[] dec = mpe.Decrypt(enc); if (!Evaluate.AreEqual(dec, data)) { throw new Exception("EncryptionKey: decryption failure!"); } OnProgress(new TestEventArgs("Passed encryption test")); } pri.Dispose(); pub.Dispose(); }