blob: b511feecce7aa9392c6ca7868a4a9fda9f9d9b44 [file] [log] [blame]
package org.bouncycastle.pqc.crypto.mceliece;
import java.security.SecureRandom;
import org.bouncycastle.crypto.AsymmetricCipherKeyPair;
import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator;
import org.bouncycastle.crypto.KeyGenerationParameters;
import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix;
import org.bouncycastle.pqc.math.linearalgebra.GF2mField;
import org.bouncycastle.pqc.math.linearalgebra.GoppaCode;
import org.bouncycastle.pqc.math.linearalgebra.GoppaCode.MaMaPe;
import org.bouncycastle.pqc.math.linearalgebra.Permutation;
import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
import org.bouncycastle.pqc.math.linearalgebra.PolynomialRingGF2m;
/**
* This class implements key pair generation of the McEliece Public Key
* Cryptosystem (McEliecePKC).
*/
public class McElieceKeyPairGenerator
implements AsymmetricCipherKeyPairGenerator
{
public McElieceKeyPairGenerator()
{
}
/**
* The OID of the algorithm.
*/
private static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.1";
private McElieceKeyGenerationParameters mcElieceParams;
// the extension degree of the finite field GF(2^m)
private int m;
// the length of the code
private int n;
// the error correction capability
private int t;
// the field polynomial
private int fieldPoly;
// the source of randomness
private SecureRandom random;
// flag indicating whether the key pair generator has been initialized
private boolean initialized = false;
/**
* Default initialization of the key pair generator.
*/
private void initializeDefault()
{
McElieceKeyGenerationParameters mcParams = new McElieceKeyGenerationParameters(new SecureRandom(), new McElieceParameters());
initialize(mcParams);
}
private void initialize(
KeyGenerationParameters param)
{
this.mcElieceParams = (McElieceKeyGenerationParameters)param;
// set source of randomness
this.random = new SecureRandom();
this.m = this.mcElieceParams.getParameters().getM();
this.n = this.mcElieceParams.getParameters().getN();
this.t = this.mcElieceParams.getParameters().getT();
this.fieldPoly = this.mcElieceParams.getParameters().getFieldPoly();
this.initialized = true;
}
private AsymmetricCipherKeyPair genKeyPair()
{
if (!initialized)
{
initializeDefault();
}
// finite field GF(2^m)
GF2mField field = new GF2mField(m, fieldPoly);
// irreducible Goppa polynomial
PolynomialGF2mSmallM gp = new PolynomialGF2mSmallM(field, t,
PolynomialGF2mSmallM.RANDOM_IRREDUCIBLE_POLYNOMIAL, random);
PolynomialRingGF2m ring = new PolynomialRingGF2m(field, gp);
// matrix used to compute square roots in (GF(2^m))^t
PolynomialGF2mSmallM[] sqRootMatrix = ring.getSquareRootMatrix();
// generate canonical check matrix
GF2Matrix h = GoppaCode.createCanonicalCheckMatrix(field, gp);
// compute short systematic form of check matrix
MaMaPe mmp = GoppaCode.computeSystematicForm(h, random);
GF2Matrix shortH = mmp.getSecondMatrix();
Permutation p1 = mmp.getPermutation();
// compute short systematic form of generator matrix
GF2Matrix shortG = (GF2Matrix)shortH.computeTranspose();
// extend to full systematic form
GF2Matrix gPrime = shortG.extendLeftCompactForm();
// obtain number of rows of G (= dimension of the code)
int k = shortG.getNumRows();
// generate random invertible (k x k)-matrix S and its inverse S^-1
GF2Matrix[] matrixSandInverse = GF2Matrix
.createRandomRegularMatrixAndItsInverse(k, random);
// generate random permutation P2
Permutation p2 = new Permutation(n, random);
// compute public matrix G=S*G'*P2
GF2Matrix g = (GF2Matrix)matrixSandInverse[0].rightMultiply(gPrime);
g = (GF2Matrix)g.rightMultiply(p2);
// generate keys
McEliecePublicKeyParameters pubKey = new McEliecePublicKeyParameters(n, t, g);
McEliecePrivateKeyParameters privKey = new McEliecePrivateKeyParameters(n, k, field, gp, p1, p2, matrixSandInverse[1]);
// return key pair
return new AsymmetricCipherKeyPair(pubKey, privKey);
}
public void init(KeyGenerationParameters param)
{
this.initialize(param);
}
public AsymmetricCipherKeyPair generateKeyPair()
{
return genKeyPair();
}
}