package org.bouncycastle.pqc.jcajce.provider.mceliece;

import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2PrivateKeyParameters;
import org.bouncycastle.pqc.crypto.mceliece.McElieceCCA2PublicKeyParameters;
import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
import org.bouncycastle.pqc.math.linearalgebra.GF2Vector;
import org.bouncycastle.pqc.math.linearalgebra.GF2mField;
import org.bouncycastle.pqc.math.linearalgebra.GoppaCode;
import org.bouncycastle.pqc.math.linearalgebra.Permutation;
import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
import org.bouncycastle.pqc.math.linearalgebra.Vector;

Core operations for the CCA-secure variants of McEliece.
/** * Core operations for the CCA-secure variants of McEliece. */
public final class McElieceCCA2Primitives {
Default constructor (private).
/** * Default constructor (private). */
private McElieceCCA2Primitives() { }
The McEliece encryption primitive.
Params:
  • pubKey – the public key
  • m – the message vector
  • z – the error vector
Returns:m*G + z
/** * The McEliece encryption primitive. * * @param pubKey the public key * @param m the message vector * @param z the error vector * @return <tt>m*G + z</tt> */
public static GF2Vector encryptionPrimitive(BCMcElieceCCA2PublicKey pubKey, GF2Vector m, GF2Vector z) { GF2Matrix matrixG = pubKey.getG(); Vector mG = matrixG.leftMultiplyLeftCompactForm(m); return (GF2Vector)mG.add(z); } public static GF2Vector encryptionPrimitive(McElieceCCA2PublicKeyParameters pubKey, GF2Vector m, GF2Vector z) { GF2Matrix matrixG = pubKey.getG(); Vector mG = matrixG.leftMultiplyLeftCompactForm(m); return (GF2Vector)mG.add(z); }
The McEliece decryption primitive.
Params:
  • privKey – the private key
  • c – the ciphertext vector c = m*G + z
Returns:the message vector m and the error vector z
/** * The McEliece decryption primitive. * * @param privKey the private key * @param c the ciphertext vector <tt>c = m*G + z</tt> * @return the message vector <tt>m</tt> and the error vector <tt>z</tt> */
public static GF2Vector[] decryptionPrimitive( BCMcElieceCCA2PrivateKey privKey, GF2Vector c) { // obtain values from private key int k = privKey.getK(); Permutation p = privKey.getP(); GF2mField field = privKey.getField(); PolynomialGF2mSmallM gp = privKey.getGoppaPoly(); GF2Matrix h = privKey.getH(); PolynomialGF2mSmallM[] q = privKey.getQInv(); // 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}; } public static GF2Vector[] decryptionPrimitive( McElieceCCA2PrivateKeyParameters privKey, GF2Vector c) { // obtain values from private key int k = privKey.getK(); Permutation p = privKey.getP(); GF2mField field = privKey.getField(); PolynomialGF2mSmallM gp = privKey.getGoppaPoly(); GF2Matrix h = privKey.getH(); PolynomialGF2mSmallM[] q = privKey.getQInv(); // 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}; } }