package org.bouncycastle.pqc.jcajce.provider.mceliece; import java.io.IOException; import java.security.PrivateKey; import org.bouncycastle.asn1.ASN1ObjectIdentifier; import org.bouncycastle.asn1.ASN1Primitive; import org.bouncycastle.asn1.DERNull; import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; import org.bouncycastle.asn1.x509.AlgorithmIdentifier; import org.bouncycastle.crypto.CipherParameters; import org.bouncycastle.pqc.asn1.McEliecePrivateKey; import org.bouncycastle.pqc.crypto.mceliece.McElieceKeyPairGenerator; import org.bouncycastle.pqc.crypto.mceliece.McElieceParameters; import org.bouncycastle.pqc.crypto.mceliece.McEliecePrivateKeyParameters; import org.bouncycastle.pqc.jcajce.spec.McEliecePrivateKeySpec; import org.bouncycastle.pqc.math.linearalgebra.GF2Matrix; import org.bouncycastle.pqc.math.linearalgebra.GF2mField; import org.bouncycastle.pqc.math.linearalgebra.Permutation; import org.bouncycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM; /** * This class implements a McEliece private key and is usually instantiated by * the {@link McElieceKeyPairGenerator} or {@link McElieceKeyFactorySpi}. */ public class BCMcEliecePrivateKey implements CipherParameters, PrivateKey { /** * */ private static final long serialVersionUID = 1L; // the OID of the algorithm private String oid; // the length of the code private int n; // the dimension of the code, where <tt>k >= n - mt</tt> private int k; // the underlying finite field private GF2mField field; // the irreducible Goppa polynomial private PolynomialGF2mSmallM goppaPoly; // the matrix S^-1 private GF2Matrix sInv; // the permutation P1 used to generate the systematic check matrix private Permutation p1; // the permutation P2 used to compute the public generator matrix private Permutation p2; // the canonical check matrix of the code private GF2Matrix h; // the matrix used to compute square roots in <tt>(GF(2^m))^t</tt> private PolynomialGF2mSmallM[] qInv; private McElieceParameters mcElieceParams; /** * Constructor (used by the {@link McElieceKeyPairGenerator}). * * @param oid * @param n the length of the code * @param k the dimension of the code * @param field the field polynomial defining the finite field * <tt>GF(2<sup>m</sup>)</tt> * @param goppaPoly the irreducible Goppa polynomial * @param sInv the matrix <tt>S<sup>-1</sup></tt> * @param p1 the permutation used to generate the systematic check * matrix * @param p2 the permutation used to compute the public generator * matrix * @param h the canonical check matrix * @param qInv the matrix used to compute square roots in * <tt>(GF(2<sup>m</sup>))<sup>t</sup></tt> */ public BCMcEliecePrivateKey(String oid, int n, int k, GF2mField field, PolynomialGF2mSmallM goppaPoly, GF2Matrix sInv, Permutation p1, Permutation p2, GF2Matrix h, PolynomialGF2mSmallM[] qInv) { this.oid = oid; this.n = n; this.k = k; this.field = field; this.goppaPoly = goppaPoly; this.sInv = sInv; this.p1 = p1; this.p2 = p2; this.h = h; this.qInv = qInv; } /** * Constructor (used by the {@link McElieceKeyFactorySpi}). * * @param keySpec a {@link McEliecePrivateKeySpec} */ public BCMcEliecePrivateKey(McEliecePrivateKeySpec keySpec) { this(keySpec.getOIDString(), keySpec.getN(), keySpec.getK(), keySpec.getField(), keySpec .getGoppaPoly(), keySpec.getSInv(), keySpec.getP1(), keySpec .getP2(), keySpec.getH(), keySpec.getQInv()); } public BCMcEliecePrivateKey(McEliecePrivateKeyParameters params) { this(params.getOIDString(), params.getN(), params.getK(), params.getField(), params.getGoppaPoly(), params.getSInv(), params.getP1(), params.getP2(), params.getH(), params.getQInv()); this.mcElieceParams = params.getParameters(); } /** * Return the name of the algorithm. * * @return "McEliece" */ public String getAlgorithm() { return "McEliece"; } /** * @return the length of the code */ public int getN() { return n; } /** * @return the dimension of the code */ public int getK() { return k; } /** * @return the finite field */ public GF2mField getField() { return field; } /** * @return the irreducible Goppa polynomial */ public PolynomialGF2mSmallM getGoppaPoly() { return goppaPoly; } /** * @return the k x k random binary non-singular matrix S */ public GF2Matrix getSInv() { return sInv; } /** * @return the permutation used to generate the systematic check matrix */ public Permutation getP1() { return p1; } /** * @return the permutation used to compute the public generator matrix */ public Permutation getP2() { return p2; } /** * @return the canonical check matrix */ public GF2Matrix getH() { return h; } /** * @return the matrix for computing square roots in <tt>(GF(2^m))^t</tt> */ public PolynomialGF2mSmallM[] getQInv() { return qInv; } /** * @return the OID of the algorithm */ public String getOIDString() { return oid; } /** * @return a human readable form of the key */ public String toString() { String result = " length of the code : " + n + "\n"; result += " dimension of the code : " + k + "\n"; result += " irreducible Goppa polynomial: " + goppaPoly + "\n"; result += " (k x k)-matrix S^-1 : " + sInv + "\n"; result += " permutation P1 : " + p1 + "\n"; result += " permutation P2 : " + p2; return result; } /** * Compare this key with another object. * * @param other the other object * @return the result of the comparison */ public boolean equals(Object other) { if (!(other instanceof BCMcEliecePrivateKey)) { return false; } BCMcEliecePrivateKey otherKey = (BCMcEliecePrivateKey)other; return (n == otherKey.n) && (k == otherKey.k) && field.equals(otherKey.field) && goppaPoly.equals(otherKey.goppaPoly) && sInv.equals(otherKey.sInv) && p1.equals(otherKey.p1) && p2.equals(otherKey.p2) && h.equals(otherKey.h); } /** * @return the hash code of this key */ public int hashCode() { return k + n + field.hashCode() + goppaPoly.hashCode() + sInv.hashCode() + p1.hashCode() + p2.hashCode() + h.hashCode(); } /** * @return the OID to encode in the SubjectPublicKeyInfo structure */ protected ASN1ObjectIdentifier getOID() { return new ASN1ObjectIdentifier(McElieceKeyFactorySpi.OID); } /** * @return the algorithm parameters to encode in the SubjectPublicKeyInfo * structure */ protected ASN1Primitive getAlgParams() { return null; // FIXME: needed at all? } /** * Return the key data to encode in the SubjectPublicKeyInfo structure. * <p/> * The ASN.1 definition of the key structure is * <p/> * <pre> * McEliecePrivateKey ::= SEQUENCE { * n INTEGER -- length of the code * k INTEGER -- dimension of the code * fieldPoly OCTET STRING -- field polynomial defining GF(2ˆm) * goppaPoly OCTET STRING -- irreducible Goppa polynomial * sInv OCTET STRING -- matrix Sˆ-1 * p1 OCTET STRING -- permutation P1 * p2 OCTET STRING -- permutation P2 * h OCTET STRING -- canonical check matrix * qInv SEQUENCE OF OCTET STRING -- matrix used to compute square roots * } * </pre> * * @return the key data to encode in the SubjectPublicKeyInfo structure */ public byte[] getEncoded() { McEliecePrivateKey privateKey = new McEliecePrivateKey(new ASN1ObjectIdentifier(oid), n, k, field, goppaPoly, sInv, p1, p2, h, qInv); PrivateKeyInfo pki; try { AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(this.getOID(), DERNull.INSTANCE); pki = new PrivateKeyInfo(algorithmIdentifier, privateKey); } catch (IOException e) { e.printStackTrace(); return null; } try { byte[] encoded = pki.getEncoded(); return encoded; } catch (IOException e) { e.printStackTrace(); return null; } } public String getFormat() { // TODO Auto-generated method stub return null; } public McElieceParameters getMcElieceParameters() { return mcElieceParams; } }