| package org.bouncycastle.pqc.crypto.mceliece; |
| |
| import java.security.SecureRandom; |
| |
| import org.bouncycastle.crypto.AsymmetricCipherKeyPair; |
| import org.bouncycastle.crypto.AsymmetricCipherKeyPairGenerator; |
| import org.bouncycastle.crypto.CryptoServicesRegistrar; |
| 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(CryptoServicesRegistrar.getSecureRandom(), new McElieceParameters()); |
| initialize(mcParams); |
| } |
| |
| private void initialize( |
| KeyGenerationParameters param) |
| { |
| this.mcElieceParams = (McElieceKeyGenerationParameters)param; |
| |
| // set source of randomness |
| this.random = param.getRandom(); |
| if (this.random == null) |
| { |
| this.random = CryptoServicesRegistrar.getSecureRandom(); |
| } |
| |
| 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(); |
| } |
| |
| } |