Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/quite/humla-spongycastle.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece')
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcElieceCCA2PrivateKey.java307
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcElieceCCA2PublicKey.java227
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcEliecePrivateKey.java334
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcEliecePublicKey.java231
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2KeyFactorySpi.java346
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2KeysToParams.java47
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2Primitives.java131
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceFujisakiCipherSpi.java253
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeyFactorySpi.java343
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeyPairGeneratorSpi.java146
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeysToParams.java47
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKobaraImaiCipherSpi.java307
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McEliecePKCSCipherSpi.java171
-rw-r--r--prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McEliecePointchevalCipherSpi.java247
14 files changed, 3137 insertions, 0 deletions
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcElieceCCA2PrivateKey.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcElieceCCA2PrivateKey.java
new file mode 100644
index 00000000..0a22dd6f
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcElieceCCA2PrivateKey.java
@@ -0,0 +1,307 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.io.IOException;
+import java.security.PrivateKey;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.pqc.asn1.McElieceCCA2PrivateKey;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyPairGenerator;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2Parameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2PrivateKeyParameters;
+import org.spongycastle.pqc.jcajce.spec.McElieceCCA2PrivateKeySpec;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
+
+/**
+ * This class implements a McEliece CCA2 private key and is usually instantiated
+ * by the {@link McElieceCCA2KeyPairGenerator} or {@link McElieceCCA2KeyFactorySpi}.
+ *
+ * @see McElieceCCA2KeyPairGenerator
+ */
+public class BCMcElieceCCA2PrivateKey
+ 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, k>=n-mt
+ private int k;
+
+ // the finte field GF(2^m)
+ private GF2mField field;
+
+ // the irreducible Goppa polynomial
+ private PolynomialGF2mSmallM goppaPoly;
+
+ // the permutation
+ private Permutation p;
+
+ // the canonical check matrix
+ private GF2Matrix h;
+
+ // the matrix used to compute square roots in (GF(2^m))^t
+ private PolynomialGF2mSmallM[] qInv;
+
+ private McElieceCCA2Parameters mcElieceCCA2Params;
+
+ /**
+ * Constructor (used by the {@link McElieceCCA2KeyPairGenerator}).
+ *
+ * @param n the length of the code
+ * @param k the dimension of the code
+ * @param field the field polynomial
+ * @param gp the irreducible Goppa polynomial
+ * @param p the permutation
+ * @param h the canonical check matrix
+ * @param qInv the matrix used to compute square roots in
+ * <tt>(GF(2^m))^t</tt>
+ */
+ public BCMcElieceCCA2PrivateKey(String oid, int n, int k, GF2mField field,
+ PolynomialGF2mSmallM gp, Permutation p, GF2Matrix h,
+ PolynomialGF2mSmallM[] qInv)
+ {
+ this.oid = oid;
+ this.n = n;
+ this.k = k;
+ this.field = field;
+ this.goppaPoly = gp;
+ this.p = p;
+ this.h = h;
+ this.qInv = qInv;
+ }
+
+ /**
+ * Constructor (used by the {@link McElieceCCA2KeyFactorySpi}).
+ *
+ * @param keySpec a {@link McElieceCCA2PrivateKeySpec}
+ */
+ public BCMcElieceCCA2PrivateKey(McElieceCCA2PrivateKeySpec keySpec)
+ {
+ this(keySpec.getOIDString(), keySpec.getN(), keySpec.getK(), keySpec.getField(), keySpec
+ .getGoppaPoly(), keySpec.getP(), keySpec.getH(), keySpec
+ .getQInv());
+ }
+
+ public BCMcElieceCCA2PrivateKey(McElieceCCA2PrivateKeyParameters params)
+ {
+ this(params.getOIDString(), params.getN(), params.getK(), params.getField(), params.getGoppaPoly(),
+ params.getP(), params.getH(), params.getQInv());
+ this.mcElieceCCA2Params = 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 degree of the Goppa polynomial (error correcting capability)
+ */
+ public int getT()
+ {
+ return goppaPoly.getDegree();
+ }
+
+ /**
+ * @return the finite field
+ */
+ public GF2mField getField()
+ {
+ return field;
+ }
+
+ /**
+ * @return the irreducible Goppa polynomial
+ */
+ public PolynomialGF2mSmallM getGoppaPoly()
+ {
+ return goppaPoly;
+ }
+
+ /**
+ * @return the permutation vector
+ */
+ public Permutation getP()
+ {
+ return p;
+ }
+
+ /**
+ * @return the canonical check matrix
+ */
+ public GF2Matrix getH()
+ {
+ return h;
+ }
+
+ /**
+ * @return the matrix used to compute square roots in <tt>(GF(2^m))^t</tt>
+ */
+ public PolynomialGF2mSmallM[] getQInv()
+ {
+ return qInv;
+ }
+
+ /**
+ * @return a human readable form of the key
+ */
+ public String toString()
+ {
+ String result = "";
+ result += " extension degree of the field : " + n + "\n";
+ result += " dimension of the code : " + k + "\n";
+ result += " irreducible Goppa polynomial : " + goppaPoly + "\n";
+ 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 == null || !(other instanceof BCMcElieceCCA2PrivateKey))
+ {
+ return false;
+ }
+
+ BCMcElieceCCA2PrivateKey otherKey = (BCMcElieceCCA2PrivateKey)other;
+
+ return (n == otherKey.n) && (k == otherKey.k)
+ && field.equals(otherKey.field)
+ && goppaPoly.equals(otherKey.goppaPoly) && p.equals(otherKey.p)
+ && h.equals(otherKey.h);
+ }
+
+ /**
+ * @return the hash code of this key
+ */
+ public int hashCode()
+ {
+ return k + n + field.hashCode() + goppaPoly.hashCode() + p.hashCode()
+ + h.hashCode();
+ }
+
+ /**
+ * @return the OID of the algorithm
+ */
+ public String getOIDString()
+ {
+ return oid;
+ }
+
+ /**
+ * @return the OID to encode in the SubjectPublicKeyInfo structure
+ */
+ protected ASN1ObjectIdentifier getOID()
+ {
+ return new ASN1ObjectIdentifier(McElieceCCA2KeyFactorySpi.OID);
+ }
+
+ /**
+ * @return the algorithm parameters to encode in the SubjectPublicKeyInfo
+ * structure
+ */
+ protected ASN1Primitive getAlgParams()
+ {
+ return null; // FIXME: needed at all?
+ }
+
+
+ /**
+ * Return the keyData to encode in the SubjectPublicKeyInfo structure.
+ * <p/>
+ * The ASN.1 definition of the key structure is
+ * <p/>
+ * <pre>
+ * McEliecePrivateKey ::= SEQUENCE {
+ * m INTEGER -- extension degree of the field
+ * k INTEGER -- dimension of the code
+ * field OCTET STRING -- field polynomial
+ * goppaPoly OCTET STRING -- irreducible Goppa polynomial
+ * p OCTET STRING -- permutation vector
+ * matrixH OCTET STRING -- canonical check matrix
+ * sqRootMatrix SEQUENCE OF OCTET STRING -- square root matrix
+ * }
+ * </pre>
+ *
+ * @return the keyData to encode in the SubjectPublicKeyInfo structure
+ */
+ public byte[] getEncoded()
+ {
+ McElieceCCA2PrivateKey privateKey = new McElieceCCA2PrivateKey(new ASN1ObjectIdentifier(oid), n, k, field, goppaPoly, p, 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 McElieceCCA2Parameters getMcElieceCCA2Parameters()
+ {
+ return mcElieceCCA2Params;
+ }
+
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcElieceCCA2PublicKey.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcElieceCCA2PublicKey.java
new file mode 100644
index 00000000..9c3361bc
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcElieceCCA2PublicKey.java
@@ -0,0 +1,227 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+
+import java.io.IOException;
+import java.security.PublicKey;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.pqc.asn1.McElieceCCA2PublicKey;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyPairGenerator;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2Parameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2PublicKeyParameters;
+import org.spongycastle.pqc.jcajce.spec.McElieceCCA2PublicKeySpec;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+
+/**
+ * This class implements a McEliece CCA2 public key and is usually instantiated
+ * by the {@link McElieceCCA2KeyPairGenerator} or {@link McElieceCCA2KeyFactorySpi}.
+ */
+public class BCMcElieceCCA2PublicKey
+ implements CipherParameters, PublicKey
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ // the OID of the algorithm
+ private String oid;
+
+ // the length of the code
+ private int n;
+
+ // the error correction capability of the code
+ private int t;
+
+ // the generator matrix
+ private GF2Matrix g;
+
+ private McElieceCCA2Parameters McElieceCCA2Params;
+
+ /**
+ * Constructor (used by the {@link McElieceCCA2KeyPairGenerator}).
+ *
+ * @param n the length of the code
+ * @param t the error correction capability of the code
+ * @param g the generator matrix
+ */
+ public BCMcElieceCCA2PublicKey(String oid, int n, int t, GF2Matrix g)
+ {
+ this.oid = oid;
+ this.n = n;
+ this.t = t;
+ this.g = g;
+ }
+
+ /**
+ * Constructor (used by the {@link McElieceCCA2KeyFactorySpi}).
+ *
+ * @param keySpec a {@link McElieceCCA2PublicKeySpec}
+ */
+ public BCMcElieceCCA2PublicKey(McElieceCCA2PublicKeySpec keySpec)
+ {
+ this(keySpec.getOIDString(), keySpec.getN(), keySpec.getT(), keySpec.getMatrixG());
+ }
+
+ public BCMcElieceCCA2PublicKey(McElieceCCA2PublicKeyParameters params)
+ {
+ this(params.getOIDString(), params.getN(), params.getT(), params.getMatrixG());
+ this.McElieceCCA2Params = 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 g.getNumRows();
+ }
+
+ /**
+ * @return the error correction capability of the code
+ */
+ public int getT()
+ {
+ return t;
+ }
+
+ /**
+ * @return the generator matrix
+ */
+ public GF2Matrix getG()
+ {
+ return g;
+ }
+
+ /**
+ * @return a human readable form of the key
+ */
+ public String toString()
+ {
+ String result = "McEliecePublicKey:\n";
+ result += " length of the code : " + n + "\n";
+ result += " error correction capability: " + t + "\n";
+ result += " generator matrix : " + g.toString();
+ 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 == null || !(other instanceof BCMcElieceCCA2PublicKey))
+ {
+ return false;
+ }
+
+ BCMcElieceCCA2PublicKey otherKey = (BCMcElieceCCA2PublicKey)other;
+
+ return (n == otherKey.n) && (t == otherKey.t) && (g.equals(otherKey.g));
+ }
+
+ /**
+ * @return the hash code of this key
+ */
+ public int hashCode()
+ {
+ return n + t + g.hashCode();
+ }
+
+ /**
+ * @return the OID of the algorithm
+ */
+ public String getOIDString()
+ {
+ return oid;
+ }
+
+ /**
+ * @return the OID to encode in the SubjectPublicKeyInfo structure
+ */
+ protected ASN1ObjectIdentifier getOID()
+ {
+ return new ASN1ObjectIdentifier(McElieceCCA2KeyFactorySpi.OID);
+ }
+
+ /**
+ * @return the algorithm parameters to encode in the SubjectPublicKeyInfo
+ * structure
+ */
+ protected ASN1Primitive getAlgParams()
+ {
+ return null; // FIXME: needed at all?
+ }
+
+ /**
+ * Return the keyData to encode in the SubjectPublicKeyInfo structure.
+ * <p/>
+ * The ASN.1 definition of the key structure is
+ * <p/>
+ * <pre>
+ * McEliecePublicKey ::= SEQUENCE {
+ * n Integer -- length of the code
+ * t Integer -- error correcting capability
+ * matrixG OctetString -- generator matrix as octet string
+ * }
+ * </pre>
+ *
+ * @return the keyData to encode in the SubjectPublicKeyInfo structure
+ */
+ public byte[] getEncoded()
+ {
+ McElieceCCA2PublicKey key = new McElieceCCA2PublicKey(new ASN1ObjectIdentifier(oid), n, t, g);
+ AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(this.getOID(), DERNull.INSTANCE);
+
+ try
+ {
+ SubjectPublicKeyInfo subjectPublicKeyInfo = new SubjectPublicKeyInfo(algorithmIdentifier, key);
+
+ return subjectPublicKeyInfo.getEncoded();
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+
+ }
+
+ public String getFormat()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public McElieceCCA2Parameters getMcElieceCCA2Parameters()
+ {
+ return McElieceCCA2Params;
+ }
+
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcEliecePrivateKey.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcEliecePrivateKey.java
new file mode 100644
index 00000000..21e778a4
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcEliecePrivateKey.java
@@ -0,0 +1,334 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.io.IOException;
+import java.security.PrivateKey;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.pqc.asn1.McEliecePrivateKey;
+import org.spongycastle.pqc.crypto.mceliece.McElieceKeyPairGenerator;
+import org.spongycastle.pqc.crypto.mceliece.McElieceParameters;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePrivateKeyParameters;
+import org.spongycastle.pqc.jcajce.spec.McEliecePrivateKeySpec;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.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 &gt;= 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&circ;m)
+ * goppaPoly OCTET STRING -- irreducible Goppa polynomial
+ * sInv OCTET STRING -- matrix S&circ;-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;
+ }
+
+
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcEliecePublicKey.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcEliecePublicKey.java
new file mode 100644
index 00000000..25c6fd14
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/BCMcEliecePublicKey.java
@@ -0,0 +1,231 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.io.IOException;
+import java.security.PublicKey;
+
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.DERNull;
+import org.spongycastle.asn1.x509.AlgorithmIdentifier;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.pqc.asn1.McEliecePublicKey;
+import org.spongycastle.pqc.crypto.mceliece.McElieceKeyPairGenerator;
+import org.spongycastle.pqc.crypto.mceliece.McElieceParameters;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePublicKeyParameters;
+import org.spongycastle.pqc.jcajce.spec.McEliecePublicKeySpec;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+
+/**
+ * This class implements a McEliece public key and is usually instantiated by
+ * the {@link McElieceKeyPairGenerator} or {@link McElieceKeyFactorySpi}.
+ */
+public class BCMcEliecePublicKey
+ implements CipherParameters, PublicKey
+{
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
+ // the OID of the algorithm
+ private String oid;
+
+ /**
+ * the length of the code
+ */
+ private int n;
+
+ /**
+ * the error correction capability of the code
+ */
+ private int t;
+
+ /**
+ * the generator matrix
+ */
+ private GF2Matrix g;
+
+ private McElieceParameters McElieceParams;
+
+ /**
+ * Constructor (used by the {@link McElieceKeyPairGenerator}).
+ *
+ * @param oid
+ * @param n the length of the code
+ * @param t the error correction capability of the code
+ * @param g the generator matrix
+ */
+ public BCMcEliecePublicKey(String oid, int n, int t, GF2Matrix g)
+ {
+ this.oid = oid;
+ this.n = n;
+ this.t = t;
+ this.g = g;
+ }
+
+ /**
+ * Constructor (used by the {@link McElieceKeyFactorySpi}).
+ *
+ * @param keySpec a {@link McEliecePublicKeySpec}
+ */
+ public BCMcEliecePublicKey(McEliecePublicKeySpec keySpec)
+ {
+ this(keySpec.getOIDString(), keySpec.getN(), keySpec.getT(), keySpec.getG());
+ }
+
+ public BCMcEliecePublicKey(McEliecePublicKeyParameters params)
+ {
+ this(params.getOIDString(), params.getN(), params.getT(), params.getG());
+ 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 g.getNumRows();
+ }
+
+ /**
+ * @return the error correction capability of the code
+ */
+ public int getT()
+ {
+ return t;
+ }
+
+ /**
+ * @return the generator matrix
+ */
+ public GF2Matrix getG()
+ {
+ return g;
+ }
+
+ /**
+ * @return a human readable form of the key
+ */
+ public String toString()
+ {
+ String result = "McEliecePublicKey:\n";
+ result += " length of the code : " + n + "\n";
+ result += " error correction capability: " + t + "\n";
+ result += " generator matrix : " + g.toString();
+ 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 BCMcEliecePublicKey))
+ {
+ return false;
+ }
+ BCMcEliecePublicKey otherKey = (BCMcEliecePublicKey)other;
+
+ return (n == otherKey.n) && (t == otherKey.t) && g.equals(otherKey.g);
+ }
+
+ /**
+ * @return the hash code of this key
+ */
+ public int hashCode()
+ {
+ return n + t + g.hashCode();
+ }
+
+
+ /**
+ * @return the OID of the algorithm
+ */
+ public String getOIDString()
+ {
+ return oid;
+ }
+
+ /**
+ * @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 keyData to encode in the SubjectPublicKeyInfo structure.
+ * <p/>
+ * The ASN.1 definition of the key structure is
+ * <p/>
+ * <pre>
+ * McEliecePublicKey ::= SEQUENCE {
+ * n Integer -- length of the code
+ * t Integer -- error correcting capability
+ * matrixG OctetString -- generator matrix as octet string
+ * }
+ * </pre>
+ *
+ * @return the keyData to encode in the SubjectPublicKeyInfo structure
+ */
+ public byte[] getEncoded()
+ {
+ McEliecePublicKey key = new McEliecePublicKey(new ASN1ObjectIdentifier(oid), n, t, g);
+ AlgorithmIdentifier algorithmIdentifier = new AlgorithmIdentifier(this.getOID(), DERNull.INSTANCE);
+
+ try
+ {
+ SubjectPublicKeyInfo subjectPublicKeyInfo = new SubjectPublicKeyInfo(algorithmIdentifier, key);
+
+ return subjectPublicKeyInfo.getEncoded();
+ }
+ catch (IOException e)
+ {
+ return null;
+ }
+ }
+
+ public String getFormat()
+ {
+ return null;
+ }
+
+ public McElieceParameters getMcElieceParameters()
+ {
+ return McElieceParams;
+ }
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2KeyFactorySpi.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2KeyFactorySpi.java
new file mode 100644
index 00000000..d3de79bf
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2KeyFactorySpi.java
@@ -0,0 +1,346 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactorySpi;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.pqc.asn1.McElieceCCA2PrivateKey;
+import org.spongycastle.pqc.asn1.McElieceCCA2PublicKey;
+import org.spongycastle.pqc.jcajce.spec.McElieceCCA2PrivateKeySpec;
+import org.spongycastle.pqc.jcajce.spec.McElieceCCA2PublicKeySpec;
+
+/**
+ * This class is used to translate between McEliece CCA2 keys and key
+ * specifications.
+ *
+ * @see BCMcElieceCCA2PrivateKey
+ * @see McElieceCCA2PrivateKeySpec
+ * @see BCMcElieceCCA2PublicKey
+ * @see McElieceCCA2PublicKeySpec
+ */
+public class McElieceCCA2KeyFactorySpi
+ extends KeyFactorySpi
+{
+
+ /**
+ * The OID of the algorithm.
+ */
+ public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.2";
+
+ /**
+ * Converts, if possible, a key specification into a
+ * {@link BCMcElieceCCA2PublicKey}. Currently, the following key
+ * specifications are supported: {@link McElieceCCA2PublicKeySpec},
+ * {@link X509EncodedKeySpec}.
+ *
+ * @param keySpec the key specification
+ * @return the McEliece CCA2 public key
+ * @throws InvalidKeySpecException if the key specification is not supported.
+ */
+ public PublicKey generatePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (keySpec instanceof McElieceCCA2PublicKeySpec)
+ {
+ return new BCMcElieceCCA2PublicKey(
+ (McElieceCCA2PublicKeySpec)keySpec);
+ }
+ else if (keySpec instanceof X509EncodedKeySpec)
+ {
+ // get the DER-encoded Key according to X.509 from the spec
+ byte[] encKey = ((X509EncodedKeySpec)keySpec).getEncoded();
+
+ // decode the SubjectPublicKeyInfo data structure to the pki object
+ SubjectPublicKeyInfo pki;
+ try
+ {
+ pki = SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(encKey));
+ }
+ catch (IOException e)
+ {
+ throw new InvalidKeySpecException(e.toString());
+ }
+
+
+ try
+ {
+ // --- Build and return the actual key.
+ ASN1Primitive innerType = pki.parsePublicKey();
+ ASN1Sequence publicKey = (ASN1Sequence)innerType;
+
+ // decode oidString (but we don't need it right now)
+ String oidString = ((ASN1ObjectIdentifier)publicKey.getObjectAt(0))
+ .toString();
+
+ // decode <n>
+ BigInteger bigN = ((ASN1Integer)publicKey.getObjectAt(1)).getValue();
+ int n = bigN.intValue();
+
+ // decode <t>
+ BigInteger bigT = ((ASN1Integer)publicKey.getObjectAt(2)).getValue();
+ int t = bigT.intValue();
+
+ // decode <matrixG>
+ byte[] matrixG = ((ASN1OctetString)publicKey.getObjectAt(3)).getOctets();
+
+ return new BCMcElieceCCA2PublicKey(new McElieceCCA2PublicKeySpec(
+ OID, n, t, matrixG));
+ }
+ catch (IOException cce)
+ {
+ throw new InvalidKeySpecException(
+ "Unable to decode X509EncodedKeySpec: "
+ + cce.getMessage());
+ }
+ }
+
+ throw new InvalidKeySpecException("Unsupported key specification: "
+ + keySpec.getClass() + ".");
+ }
+
+ /**
+ * Converts, if possible, a key specification into a
+ * {@link BCMcElieceCCA2PrivateKey}. Currently, the following key
+ * specifications are supported: {@link McElieceCCA2PrivateKeySpec},
+ * {@link PKCS8EncodedKeySpec}.
+ *
+ * @param keySpec the key specification
+ * @return the McEliece CCA2 private key
+ * @throws InvalidKeySpecException if the KeySpec is not supported.
+ */
+ public PrivateKey generatePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (keySpec instanceof McElieceCCA2PrivateKeySpec)
+ {
+ return new BCMcElieceCCA2PrivateKey(
+ (McElieceCCA2PrivateKeySpec)keySpec);
+ }
+ else if (keySpec instanceof PKCS8EncodedKeySpec)
+ {
+ // get the DER-encoded Key according to PKCS#8 from the spec
+ byte[] encKey = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
+
+ // decode the PKCS#8 data structure to the pki object
+ PrivateKeyInfo pki;
+
+ try
+ {
+ pki = PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(encKey));
+ }
+ catch (IOException e)
+ {
+ throw new InvalidKeySpecException("Unable to decode PKCS8EncodedKeySpec: " + e);
+ }
+
+ try
+ {
+ // get the inner type inside the BIT STRING
+ ASN1Primitive innerType = pki.parsePrivateKey().toASN1Primitive();
+
+ // build and return the actual key
+ ASN1Sequence privKey = (ASN1Sequence)innerType;
+
+ // decode oidString (but we don't need it right now)
+ String oidString = ((ASN1ObjectIdentifier)privKey.getObjectAt(0))
+ .toString();
+
+ // decode <n>
+ BigInteger bigN = ((ASN1Integer)privKey.getObjectAt(1)).getValue();
+ int n = bigN.intValue();
+
+ // decode <k>
+ BigInteger bigK = ((ASN1Integer)privKey.getObjectAt(2)).getValue();
+ int k = bigK.intValue();
+
+
+ // decode <fieldPoly>
+ byte[] encFieldPoly = ((ASN1OctetString)privKey.getObjectAt(3))
+ .getOctets();
+ // decode <goppaPoly>
+ byte[] encGoppaPoly = ((ASN1OctetString)privKey.getObjectAt(4))
+ .getOctets();
+ // decode <p>
+ byte[] encP = ((ASN1OctetString)privKey.getObjectAt(5)).getOctets();
+ // decode <h>
+ byte[] encH = ((ASN1OctetString)privKey.getObjectAt(6)).getOctets();
+ // decode <qInv>
+ ASN1Sequence qSeq = (ASN1Sequence)privKey.getObjectAt(7);
+ byte[][] encQInv = new byte[qSeq.size()][];
+ for (int i = 0; i < qSeq.size(); i++)
+ {
+ encQInv[i] = ((ASN1OctetString)qSeq.getObjectAt(i)).getOctets();
+ }
+
+ return new BCMcElieceCCA2PrivateKey(
+ new McElieceCCA2PrivateKeySpec(OID, n, k, encFieldPoly,
+ encGoppaPoly, encP, encH, encQInv));
+
+ }
+ catch (IOException cce)
+ {
+ throw new InvalidKeySpecException(
+ "Unable to decode PKCS8EncodedKeySpec.");
+ }
+ }
+
+ throw new InvalidKeySpecException("Unsupported key specification: "
+ + keySpec.getClass() + ".");
+ }
+
+ /**
+ * Converts, if possible, a given key into a key specification. Currently,
+ * the following key specifications are supported:
+ * <ul>
+ * <li>for McElieceCCA2PublicKey: {@link X509EncodedKeySpec},
+ * {@link McElieceCCA2PublicKeySpec}</li>
+ * <li>for McElieceCCA2PrivateKey: {@link PKCS8EncodedKeySpec},
+ * {@link McElieceCCA2PrivateKeySpec}</li>.
+ * </ul>
+ *
+ * @param key the key
+ * @param keySpec the key specification
+ * @return the specification of the McEliece CCA2 key
+ * @throws InvalidKeySpecException if the key type or the key specification is not
+ * supported.
+ * @see BCMcElieceCCA2PrivateKey
+ * @see McElieceCCA2PrivateKeySpec
+ * @see BCMcElieceCCA2PublicKey
+ * @see McElieceCCA2PublicKeySpec
+ */
+ public KeySpec getKeySpec(Key key, Class keySpec)
+ throws InvalidKeySpecException
+ {
+ if (key instanceof BCMcElieceCCA2PrivateKey)
+ {
+ if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec))
+ {
+ return new PKCS8EncodedKeySpec(key.getEncoded());
+ }
+ else if (McElieceCCA2PrivateKeySpec.class
+ .isAssignableFrom(keySpec))
+ {
+ BCMcElieceCCA2PrivateKey privKey = (BCMcElieceCCA2PrivateKey)key;
+ return new McElieceCCA2PrivateKeySpec(OID, privKey.getN(), privKey
+ .getK(), privKey.getField(), privKey.getGoppaPoly(),
+ privKey.getP(), privKey.getH(), privKey.getQInv());
+ }
+ }
+ else if (key instanceof BCMcElieceCCA2PublicKey)
+ {
+ if (X509EncodedKeySpec.class.isAssignableFrom(keySpec))
+ {
+ return new X509EncodedKeySpec(key.getEncoded());
+ }
+ else if (McElieceCCA2PublicKeySpec.class
+ .isAssignableFrom(keySpec))
+ {
+ BCMcElieceCCA2PublicKey pubKey = (BCMcElieceCCA2PublicKey)key;
+ return new McElieceCCA2PublicKeySpec(OID, pubKey.getN(), pubKey
+ .getT(), pubKey.getG());
+ }
+ }
+ else
+ {
+ throw new InvalidKeySpecException("Unsupported key type: "
+ + key.getClass() + ".");
+ }
+
+ throw new InvalidKeySpecException("Unknown key specification: "
+ + keySpec + ".");
+ }
+
+ /**
+ * Translates a key into a form known by the FlexiProvider. Currently, only
+ * the following "source" keys are supported: {@link BCMcElieceCCA2PrivateKey},
+ * {@link BCMcElieceCCA2PublicKey}.
+ *
+ * @param key the key
+ * @return a key of a known key type
+ * @throws InvalidKeyException if the key type is not supported.
+ */
+ public Key translateKey(Key key)
+ throws InvalidKeyException
+ {
+ if ((key instanceof BCMcElieceCCA2PrivateKey)
+ || (key instanceof BCMcElieceCCA2PublicKey))
+ {
+ return key;
+ }
+ throw new InvalidKeyException("Unsupported key type.");
+
+ }
+
+
+ public PublicKey generatePublic(SubjectPublicKeyInfo pki)
+ throws InvalidKeySpecException
+ {
+ // get the inner type inside the BIT STRING
+ try
+ {
+ ASN1Primitive innerType = pki.parsePublicKey();
+ McElieceCCA2PublicKey key = McElieceCCA2PublicKey.getInstance((ASN1Sequence)innerType);
+ return new BCMcElieceCCA2PublicKey(key.getOID().getId(), key.getN(), key.getT(), key.getG());
+ }
+ catch (IOException cce)
+ {
+ throw new InvalidKeySpecException("Unable to decode X509EncodedKeySpec");
+ }
+ }
+
+
+ public PrivateKey generatePrivate(PrivateKeyInfo pki)
+ throws InvalidKeySpecException
+ {
+ // get the inner type inside the BIT STRING
+ try
+ {
+ ASN1Primitive innerType = pki.parsePrivateKey().toASN1Primitive();
+ McElieceCCA2PrivateKey key = McElieceCCA2PrivateKey.getInstance(innerType);
+ return new BCMcElieceCCA2PrivateKey(key.getOID().getId(), key.getN(), key.getK(), key.getField(), key.getGoppaPoly(), key.getP(), key.getH(), key.getQInv());
+ }
+ catch (IOException cce)
+ {
+ throw new InvalidKeySpecException("Unable to decode PKCS8EncodedKeySpec");
+ }
+ }
+
+ protected PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ protected KeySpec engineGetKeySpec(Key key, Class tClass)
+ throws InvalidKeySpecException
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ protected Key engineTranslateKey(Key key)
+ throws InvalidKeyException
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2KeysToParams.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2KeysToParams.java
new file mode 100644
index 00000000..a733d2a0
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2KeysToParams.java
@@ -0,0 +1,47 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.security.InvalidKeyException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2PrivateKeyParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2PublicKeyParameters;
+
+/**
+ * utility class for converting jce/jca McElieceCCA2 objects
+ * objects into their org.spongycastle.crypto counterparts.
+ */
+public class McElieceCCA2KeysToParams
+{
+
+
+ static public AsymmetricKeyParameter generatePublicKeyParameter(
+ PublicKey key)
+ throws InvalidKeyException
+ {
+ if (key instanceof BCMcElieceCCA2PublicKey)
+ {
+ BCMcElieceCCA2PublicKey k = (BCMcElieceCCA2PublicKey)key;
+
+ return new McElieceCCA2PublicKeyParameters(k.getOIDString(), k.getN(), k.getT(), k.getG(), k.getMcElieceCCA2Parameters());
+ }
+
+ throw new InvalidKeyException("can't identify McElieceCCA2 public key: " + key.getClass().getName());
+ }
+
+
+ static public AsymmetricKeyParameter generatePrivateKeyParameter(
+ PrivateKey key)
+ throws InvalidKeyException
+ {
+ if (key instanceof BCMcElieceCCA2PrivateKey)
+ {
+ BCMcElieceCCA2PrivateKey k = (BCMcElieceCCA2PrivateKey)key;
+ return new McElieceCCA2PrivateKeyParameters(k.getOIDString(), k.getN(), k.getK(), k.getField(), k.getGoppaPoly(),
+ k.getP(), k.getH(), k.getQInv(), k.getMcElieceCCA2Parameters());
+ }
+
+ throw new InvalidKeyException("can't identify McElieceCCA2 private key.");
+ }
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2Primitives.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2Primitives.java
new file mode 100644
index 00000000..a63c1852
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceCCA2Primitives.java
@@ -0,0 +1,131 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2PrivateKeyParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2PublicKeyParameters;
+import org.spongycastle.pqc.math.linearalgebra.GF2Matrix;
+import org.spongycastle.pqc.math.linearalgebra.GF2Vector;
+import org.spongycastle.pqc.math.linearalgebra.GF2mField;
+import org.spongycastle.pqc.math.linearalgebra.GoppaCode;
+import org.spongycastle.pqc.math.linearalgebra.Permutation;
+import org.spongycastle.pqc.math.linearalgebra.PolynomialGF2mSmallM;
+import org.spongycastle.pqc.math.linearalgebra.Vector;
+
+/**
+ * Core operations for the CCA-secure variants of McEliece.
+ */
+public final class McElieceCCA2Primitives
+{
+
+ /**
+ * Default constructor (private).
+ */
+ private McElieceCCA2Primitives()
+ {
+ }
+
+ /**
+ * 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.getMatrixG();
+ Vector mG = matrixG.leftMultiplyLeftCompactForm(m);
+ return (GF2Vector)mG.add(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};
+ }
+
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceFujisakiCipherSpi.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceFujisakiCipherSpi.java
new file mode 100644
index 00000000..77e31c6a
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceFujisakiCipherSpi.java
@@ -0,0 +1,253 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.io.ByteArrayOutputStream;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceFujisakiCipher;
+import org.spongycastle.pqc.jcajce.provider.util.AsymmetricHybridCipher;
+
+public class McElieceFujisakiCipherSpi
+ extends AsymmetricHybridCipher
+ implements PKCSObjectIdentifiers, X509ObjectIdentifiers
+{
+ // TODO digest needed?
+ private Digest digest;
+ private McElieceFujisakiCipher cipher;
+
+ /**
+ * buffer to store the input data
+ */
+ private ByteArrayOutputStream buf;
+
+
+ protected McElieceFujisakiCipherSpi(Digest digest, McElieceFujisakiCipher cipher)
+ {
+ this.digest = digest;
+ this.cipher = cipher;
+ buf = new ByteArrayOutputStream();
+
+ }
+
+ /**
+ * Continue a multiple-part encryption or decryption operation.
+ *
+ * @param input byte array containing the next part of the input
+ * @param inOff index in the array where the input starts
+ * @param inLen length of the input
+ * @return the processed byte array.
+ */
+ public byte[] update(byte[] input, int inOff, int inLen)
+ {
+ buf.write(input, inOff, inLen);
+ return new byte[0];
+ }
+
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted, depending on
+ * how this cipher was initialized.
+ *
+ * @param input the input buffer
+ * @param inOff the offset in input where the input starts
+ * @param inLen the input length
+ * @return the new buffer with the result
+ * @throws BadPaddingException on deryption errors.
+ */
+ public byte[] doFinal(byte[] input, int inOff, int inLen)
+ throws BadPaddingException
+ {
+ update(input, inOff, inLen);
+ byte[] data = buf.toByteArray();
+ buf.reset();
+ if (opMode == ENCRYPT_MODE)
+ {
+
+ try
+ {
+ return cipher.messageEncrypt(data);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ }
+ else if (opMode == DECRYPT_MODE)
+ {
+
+ try
+ {
+ return cipher.messageDecrypt(data);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ }
+ return null;
+ }
+
+
+ protected int encryptOutputSize(int inLen)
+ {
+ return 0;
+ }
+
+ protected int decryptOutputSize(int inLen)
+ {
+ return 0;
+ }
+
+ protected void initCipherEncrypt(Key key, AlgorithmParameterSpec params,
+ SecureRandom sr)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+
+ CipherParameters param;
+ param = McElieceCCA2KeysToParams.generatePublicKeyParameter((PublicKey)key);
+
+ param = new ParametersWithRandom(param, sr);
+ digest.reset();
+ cipher.init(true, param);
+
+ }
+
+ protected void initCipherDecrypt(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+
+ CipherParameters param;
+ param = McElieceCCA2KeysToParams.generatePrivateKeyParameter((PrivateKey)key);
+
+ digest.reset();
+ cipher.init(false, param);
+ }
+
+ public String getName()
+ {
+ return "McElieceFujisakiCipher";
+ }
+
+ public int getKeySize(Key key)
+ throws InvalidKeyException
+ {
+ McElieceCCA2KeyParameters mcElieceCCA2KeyParameters;
+ if (key instanceof PublicKey)
+ {
+ mcElieceCCA2KeyParameters = (McElieceCCA2KeyParameters)McElieceCCA2KeysToParams.generatePublicKeyParameter((PublicKey)key);
+ }
+ else
+ {
+ mcElieceCCA2KeyParameters = (McElieceCCA2KeyParameters)McElieceCCA2KeysToParams.generatePrivateKeyParameter((PrivateKey)key);
+
+ }
+
+
+ return cipher.getKeySize(mcElieceCCA2KeyParameters);
+ }
+
+ public byte[] messageEncrypt(byte[] input)
+ throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException
+ {
+ byte[] output = null;
+ try
+ {
+ output = cipher.messageEncrypt(input);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return output;
+ }
+
+
+ public byte[] messageDecrypt(byte[] input)
+ throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException
+ {
+ byte[] output = null;
+ try
+ {
+ output = cipher.messageDecrypt(input);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return output;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////
+
+ static public class McElieceFujisaki
+ extends McElieceFujisakiCipherSpi
+ {
+ public McElieceFujisaki()
+ {
+ super(new SHA1Digest(), new McElieceFujisakiCipher());
+ }
+ }
+
+ static public class McElieceFujisaki224
+ extends McElieceFujisakiCipherSpi
+ {
+ public McElieceFujisaki224()
+ {
+ super(new SHA224Digest(), new McElieceFujisakiCipher());
+ }
+ }
+
+ static public class McElieceFujisaki256
+ extends McElieceFujisakiCipherSpi
+ {
+ public McElieceFujisaki256()
+ {
+ super(new SHA256Digest(), new McElieceFujisakiCipher());
+ }
+ }
+
+ static public class McElieceFujisaki384
+ extends McElieceFujisakiCipherSpi
+ {
+ public McElieceFujisaki384()
+ {
+ super(new SHA384Digest(), new McElieceFujisakiCipher());
+ }
+ }
+
+ static public class McElieceFujisaki512
+ extends McElieceFujisakiCipherSpi
+ {
+ public McElieceFujisaki512()
+ {
+ super(new SHA512Digest(), new McElieceFujisakiCipher());
+ }
+ }
+
+
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeyFactorySpi.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeyFactorySpi.java
new file mode 100644
index 00000000..1c2007a0
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeyFactorySpi.java
@@ -0,0 +1,343 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyFactorySpi;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.spec.InvalidKeySpecException;
+import java.security.spec.KeySpec;
+import java.security.spec.PKCS8EncodedKeySpec;
+import java.security.spec.X509EncodedKeySpec;
+
+import org.spongycastle.asn1.ASN1Integer;
+import org.spongycastle.asn1.ASN1ObjectIdentifier;
+import org.spongycastle.asn1.ASN1OctetString;
+import org.spongycastle.asn1.ASN1Primitive;
+import org.spongycastle.asn1.ASN1Sequence;
+import org.spongycastle.asn1.pkcs.PrivateKeyInfo;
+import org.spongycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.spongycastle.pqc.asn1.McEliecePrivateKey;
+import org.spongycastle.pqc.asn1.McEliecePublicKey;
+import org.spongycastle.pqc.jcajce.spec.McEliecePrivateKeySpec;
+import org.spongycastle.pqc.jcajce.spec.McEliecePublicKeySpec;
+
+/**
+ * This class is used to translate between McEliece keys and key specifications.
+ *
+ * @see BCMcEliecePrivateKey
+ * @see McEliecePrivateKeySpec
+ * @see BCMcEliecePublicKey
+ * @see McEliecePublicKeySpec
+ */
+public class McElieceKeyFactorySpi
+ extends KeyFactorySpi
+{
+ /**
+ * The OID of the algorithm.
+ */
+ public static final String OID = "1.3.6.1.4.1.8301.3.1.3.4.1";
+
+ /**
+ * Converts, if possible, a key specification into a
+ * {@link BCMcEliecePublicKey}. Currently, the following key specifications
+ * are supported: {@link McEliecePublicKeySpec}, {@link X509EncodedKeySpec}.
+ *
+ * @param keySpec the key specification
+ * @return the McEliece public key
+ * @throws InvalidKeySpecException if the key specification is not supported.
+ */
+ public PublicKey generatePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (keySpec instanceof McEliecePublicKeySpec)
+ {
+ return new BCMcEliecePublicKey((McEliecePublicKeySpec)keySpec);
+ }
+ else if (keySpec instanceof X509EncodedKeySpec)
+ {
+ // get the DER-encoded Key according to X.509 from the spec
+ byte[] encKey = ((X509EncodedKeySpec)keySpec).getEncoded();
+
+ // decode the SubjectPublicKeyInfo data structure to the pki object
+ SubjectPublicKeyInfo pki;
+ try
+ {
+ pki = SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(encKey));
+ }
+ catch (IOException e)
+ {
+ throw new InvalidKeySpecException(e.toString());
+ }
+
+ try
+ {
+ // --- Build and return the actual key.
+ ASN1Primitive innerType = pki.parsePublicKey();
+ ASN1Sequence publicKey = (ASN1Sequence)innerType;
+
+ // decode oidString (but we don't need it right now)
+ String oidString = ((ASN1ObjectIdentifier)publicKey.getObjectAt(0))
+ .toString();
+
+ // decode <n>
+ BigInteger bigN = ((ASN1Integer)publicKey.getObjectAt(1)).getValue();
+ int n = bigN.intValue();
+
+ // decode <t>
+ BigInteger bigT = ((ASN1Integer)publicKey.getObjectAt(2)).getValue();
+ int t = bigT.intValue();
+
+ // decode <matrixG>
+ byte[] matrixG = ((ASN1OctetString)publicKey.getObjectAt(3)).getOctets();
+
+
+ return new BCMcEliecePublicKey(new McEliecePublicKeySpec(OID, t, n,
+ matrixG));
+ }
+ catch (IOException cce)
+ {
+ throw new InvalidKeySpecException(
+ "Unable to decode X509EncodedKeySpec: "
+ + cce.getMessage());
+ }
+ }
+
+ throw new InvalidKeySpecException("Unsupported key specification: "
+ + keySpec.getClass() + ".");
+ }
+
+ /**
+ * Converts, if possible, a key specification into a
+ * {@link BCMcEliecePrivateKey}. Currently, the following key specifications
+ * are supported: {@link McEliecePrivateKeySpec},
+ * {@link PKCS8EncodedKeySpec}.
+ *
+ * @param keySpec the key specification
+ * @return the McEliece private key
+ * @throws InvalidKeySpecException if the KeySpec is not supported.
+ */
+ public PrivateKey generatePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ if (keySpec instanceof McEliecePrivateKeySpec)
+ {
+ return new BCMcEliecePrivateKey((McEliecePrivateKeySpec)keySpec);
+ }
+ else if (keySpec instanceof PKCS8EncodedKeySpec)
+ {
+ // get the DER-encoded Key according to PKCS#8 from the spec
+ byte[] encKey = ((PKCS8EncodedKeySpec)keySpec).getEncoded();
+
+ // decode the PKCS#8 data structure to the pki object
+ PrivateKeyInfo pki;
+
+ try
+ {
+ pki = PrivateKeyInfo.getInstance(ASN1Primitive.fromByteArray(encKey));
+ }
+ catch (IOException e)
+ {
+ throw new InvalidKeySpecException("Unable to decode PKCS8EncodedKeySpec: " + e);
+ }
+
+ try
+ {
+ ASN1Primitive innerType = pki.parsePrivateKey().toASN1Primitive();
+
+ // build and return the actual key
+ ASN1Sequence privKey = (ASN1Sequence)innerType;
+
+ // decode oidString (but we don't need it right now)
+ String oidString = ((ASN1ObjectIdentifier)privKey.getObjectAt(0))
+ .toString();
+
+ // decode <n>
+ BigInteger bigN = ((ASN1Integer)privKey.getObjectAt(1)).getValue();
+ int n = bigN.intValue();
+
+ // decode <k>
+ BigInteger bigK = ((ASN1Integer)privKey.getObjectAt(2)).getValue();
+ int k = bigK.intValue();
+
+ // decode <fieldPoly>
+ byte[] encFieldPoly = ((ASN1OctetString)privKey.getObjectAt(3))
+ .getOctets();
+ // decode <goppaPoly>
+ byte[] encGoppaPoly = ((ASN1OctetString)privKey.getObjectAt(4))
+ .getOctets();
+
+ // decode <sInv>
+ byte[] encSInv = ((ASN1OctetString)privKey.getObjectAt(5)).getOctets();
+ // decode <p1>
+ byte[] encP1 = ((ASN1OctetString)privKey.getObjectAt(6)).getOctets();
+ // decode <p2>
+ byte[] encP2 = ((ASN1OctetString)privKey.getObjectAt(7)).getOctets();
+
+ //decode <h>
+ byte[] encH = ((ASN1OctetString)privKey.getObjectAt(8)).getOctets();
+
+ // decode <qInv>
+ ASN1Sequence qSeq = (ASN1Sequence)privKey.getObjectAt(9);
+ byte[][] encQInv = new byte[qSeq.size()][];
+ for (int i = 0; i < qSeq.size(); i++)
+ {
+ encQInv[i] = ((ASN1OctetString)qSeq.getObjectAt(i)).getOctets();
+ }
+
+ return new BCMcEliecePrivateKey(new McEliecePrivateKeySpec(OID, n, k,
+ encFieldPoly, encGoppaPoly, encSInv, encP1, encP2,
+ encH, encQInv));
+
+ }
+ catch (IOException cce)
+ {
+ throw new InvalidKeySpecException(
+ "Unable to decode PKCS8EncodedKeySpec.");
+ }
+ }
+
+ throw new InvalidKeySpecException("Unsupported key specification: "
+ + keySpec.getClass() + ".");
+ }
+
+ /**
+ * Converts, if possible, a given key into a key specification. Currently,
+ * the following key specifications are supported:
+ * <ul>
+ * <li>for McEliecePublicKey: {@link X509EncodedKeySpec},
+ * {@link McEliecePublicKeySpec}</li>
+ * <li>for McEliecePrivateKey: {@link PKCS8EncodedKeySpec},
+ * {@link McEliecePrivateKeySpec}</li>.
+ * </ul>
+ *
+ * @param key the key
+ * @param keySpec the key specification
+ * @return the specification of the McEliece key
+ * @throws InvalidKeySpecException if the key type or the key specification is not
+ * supported.
+ * @see BCMcEliecePrivateKey
+ * @see McEliecePrivateKeySpec
+ * @see BCMcEliecePublicKey
+ * @see McEliecePublicKeySpec
+ */
+ public KeySpec getKeySpec(Key key, Class keySpec)
+ throws InvalidKeySpecException
+ {
+ if (key instanceof BCMcEliecePrivateKey)
+ {
+ if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec))
+ {
+ return new PKCS8EncodedKeySpec(key.getEncoded());
+ }
+ else if (McEliecePrivateKeySpec.class.isAssignableFrom(keySpec))
+ {
+ BCMcEliecePrivateKey privKey = (BCMcEliecePrivateKey)key;
+ return new McEliecePrivateKeySpec(OID, privKey.getN(), privKey
+ .getK(), privKey.getField(), privKey.getGoppaPoly(),
+ privKey.getSInv(), privKey.getP1(), privKey.getP2(),
+ privKey.getH(), privKey.getQInv());
+ }
+ }
+ else if (key instanceof BCMcEliecePublicKey)
+ {
+ if (X509EncodedKeySpec.class.isAssignableFrom(keySpec))
+ {
+ return new X509EncodedKeySpec(key.getEncoded());
+ }
+ else if (McEliecePublicKeySpec.class.isAssignableFrom(keySpec))
+ {
+ BCMcEliecePublicKey pubKey = (BCMcEliecePublicKey)key;
+ return new McEliecePublicKeySpec(OID, pubKey.getN(), pubKey.getT(),
+ pubKey.getG());
+ }
+ }
+ else
+ {
+ throw new InvalidKeySpecException("Unsupported key type: "
+ + key.getClass() + ".");
+ }
+
+ throw new InvalidKeySpecException("Unknown key specification: "
+ + keySpec + ".");
+ }
+
+ /**
+ * Translates a key into a form known by the FlexiProvider. Currently, only
+ * the following "source" keys are supported: {@link BCMcEliecePrivateKey},
+ * {@link BCMcEliecePublicKey}.
+ *
+ * @param key the key
+ * @return a key of a known key type
+ * @throws InvalidKeyException if the key type is not supported.
+ */
+ public Key translateKey(Key key)
+ throws InvalidKeyException
+ {
+ if ((key instanceof BCMcEliecePrivateKey)
+ || (key instanceof BCMcEliecePublicKey))
+ {
+ return key;
+ }
+ throw new InvalidKeyException("Unsupported key type.");
+
+ }
+
+ public PublicKey generatePublic(SubjectPublicKeyInfo pki)
+ throws InvalidKeySpecException
+ {
+ // get the inner type inside the BIT STRING
+ try
+ {
+ ASN1Primitive innerType = pki.parsePublicKey();
+ McEliecePublicKey key = McEliecePublicKey.getInstance(innerType);
+ return new BCMcEliecePublicKey(key.getOID().getId(), key.getN(), key.getT(), key.getG());
+ }
+ catch (IOException cce)
+ {
+ throw new InvalidKeySpecException("Unable to decode X509EncodedKeySpec");
+ }
+ }
+
+ public PrivateKey generatePrivate(PrivateKeyInfo pki)
+ throws InvalidKeySpecException
+ {
+ // get the inner type inside the BIT STRING
+ try
+ {
+ ASN1Primitive innerType = pki.parsePrivateKey().toASN1Primitive();
+ McEliecePrivateKey key = McEliecePrivateKey.getInstance(innerType);
+ return new BCMcEliecePrivateKey(key.getOID().getId(), key.getN(), key.getK(), key.getField(), key.getGoppaPoly(), key.getSInv(), key.getP1(), key.getP2(), key.getH(), key.getQInv());
+ }
+ catch (IOException cce)
+ {
+ throw new InvalidKeySpecException("Unable to decode PKCS8EncodedKeySpec");
+ }
+ }
+
+ protected PublicKey engineGeneratePublic(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
+ throws InvalidKeySpecException
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ protected KeySpec engineGetKeySpec(Key key, Class tClass)
+ throws InvalidKeySpecException
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ protected Key engineTranslateKey(Key key)
+ throws InvalidKeyException
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeyPairGeneratorSpi.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeyPairGeneratorSpi.java
new file mode 100644
index 00000000..9e0115fd
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeyPairGeneratorSpi.java
@@ -0,0 +1,146 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+import org.spongycastle.crypto.AsymmetricCipherKeyPair;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyGenerationParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyPairGenerator;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2Parameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2PrivateKeyParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2PublicKeyParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceKeyGenerationParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceKeyPairGenerator;
+import org.spongycastle.pqc.crypto.mceliece.McElieceParameters;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePrivateKeyParameters;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePublicKeyParameters;
+import org.spongycastle.pqc.jcajce.spec.ECCKeyGenParameterSpec;
+import org.spongycastle.pqc.jcajce.spec.McElieceCCA2ParameterSpec;
+
+public abstract class McElieceKeyPairGeneratorSpi
+ extends KeyPairGenerator
+{
+ public McElieceKeyPairGeneratorSpi(
+ String algorithmName)
+ {
+ super(algorithmName);
+ }
+
+ /**
+ *
+ *
+ *
+ */
+
+ public static class McElieceCCA2
+ extends McElieceKeyPairGeneratorSpi
+ {
+
+ McElieceCCA2KeyPairGenerator kpg;
+
+
+ public McElieceCCA2()
+ {
+ super("McElieceCCA-2");
+ }
+
+ public McElieceCCA2(String s)
+ {
+ super(s);
+ }
+
+ public void initialize(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException
+ {
+ kpg = new McElieceCCA2KeyPairGenerator();
+ super.initialize(params);
+ ECCKeyGenParameterSpec ecc = (ECCKeyGenParameterSpec)params;
+
+ McElieceCCA2KeyGenerationParameters mccca2KGParams = new McElieceCCA2KeyGenerationParameters(new SecureRandom(), new McElieceCCA2Parameters(ecc.getM(), ecc.getT()));
+ kpg.init(mccca2KGParams);
+ }
+
+ public void initialize(int keySize, SecureRandom random)
+ {
+ McElieceCCA2ParameterSpec paramSpec = new McElieceCCA2ParameterSpec();
+
+ // call the initializer with the chosen parameters
+ try
+ {
+ this.initialize(paramSpec);
+ }
+ catch (InvalidAlgorithmParameterException ae)
+ {
+ }
+ }
+
+ public KeyPair generateKeyPair()
+ {
+ AsymmetricCipherKeyPair generateKeyPair = kpg.generateKeyPair();
+ McElieceCCA2PrivateKeyParameters sk = (McElieceCCA2PrivateKeyParameters)generateKeyPair.getPrivate();
+ McElieceCCA2PublicKeyParameters pk = (McElieceCCA2PublicKeyParameters)generateKeyPair.getPublic();
+
+ return new KeyPair(new BCMcElieceCCA2PublicKey(pk), new BCMcElieceCCA2PrivateKey(sk));
+
+ }
+
+ }
+
+ /**
+ *
+ *
+ *
+ */
+
+ public static class McEliece
+ extends McElieceKeyPairGeneratorSpi
+ {
+
+ McElieceKeyPairGenerator kpg;
+
+
+ public McEliece()
+ {
+ super("McEliece");
+ }
+
+ public void initialize(AlgorithmParameterSpec params)
+ throws InvalidAlgorithmParameterException
+ {
+ kpg = new McElieceKeyPairGenerator();
+ super.initialize(params);
+ ECCKeyGenParameterSpec ecc = (ECCKeyGenParameterSpec)params;
+
+ McElieceKeyGenerationParameters mccKGParams = new McElieceKeyGenerationParameters(new SecureRandom(), new McElieceParameters(ecc.getM(), ecc.getT()));
+ kpg.init(mccKGParams);
+ }
+
+ public void initialize(int keySize, SecureRandom random)
+ {
+ ECCKeyGenParameterSpec paramSpec = new ECCKeyGenParameterSpec();
+
+ // call the initializer with the chosen parameters
+ try
+ {
+ this.initialize(paramSpec);
+ }
+ catch (InvalidAlgorithmParameterException ae)
+ {
+ }
+ }
+
+ public KeyPair generateKeyPair()
+ {
+ AsymmetricCipherKeyPair generateKeyPair = kpg.generateKeyPair();
+ McEliecePrivateKeyParameters sk = (McEliecePrivateKeyParameters)generateKeyPair.getPrivate();
+ McEliecePublicKeyParameters pk = (McEliecePublicKeyParameters)generateKeyPair.getPublic();
+
+ return new KeyPair(new BCMcEliecePublicKey(pk), new BCMcEliecePrivateKey(sk));
+ }
+
+ }
+
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeysToParams.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeysToParams.java
new file mode 100644
index 00000000..649d1d45
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKeysToParams.java
@@ -0,0 +1,47 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.security.InvalidKeyException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+
+import org.spongycastle.crypto.params.AsymmetricKeyParameter;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePrivateKeyParameters;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePublicKeyParameters;
+
+/**
+ * utility class for converting jce/jca McEliece objects
+ * objects into their org.spongycastle.crypto counterparts.
+ */
+public class McElieceKeysToParams
+{
+
+
+ static public AsymmetricKeyParameter generatePublicKeyParameter(
+ PublicKey key)
+ throws InvalidKeyException
+ {
+ if (key instanceof BCMcEliecePublicKey)
+ {
+ BCMcEliecePublicKey k = (BCMcEliecePublicKey)key;
+
+ return new McEliecePublicKeyParameters(k.getOIDString(), k.getN(), k.getT(), k.getG(), k.getMcElieceParameters());
+ }
+
+ throw new InvalidKeyException("can't identify McEliece public key: " + key.getClass().getName());
+ }
+
+
+ static public AsymmetricKeyParameter generatePrivateKeyParameter(
+ PrivateKey key)
+ throws InvalidKeyException
+ {
+ if (key instanceof BCMcEliecePrivateKey)
+ {
+ BCMcEliecePrivateKey k = (BCMcEliecePrivateKey)key;
+ return new McEliecePrivateKeyParameters(k.getOIDString(), k.getN(), k.getK(), k.getField(), k.getGoppaPoly(),
+ k.getSInv(), k.getP1(), k.getP2(), k.getH(), k.getQInv(), k.getMcElieceParameters());
+ }
+
+ throw new InvalidKeyException("can't identify McEliece private key.");
+ }
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKobaraImaiCipherSpi.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKobaraImaiCipherSpi.java
new file mode 100644
index 00000000..60e77a5c
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McElieceKobaraImaiCipherSpi.java
@@ -0,0 +1,307 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.io.ByteArrayOutputStream;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyParameters;
+import org.spongycastle.pqc.crypto.mceliece.McElieceKobaraImaiCipher;
+import org.spongycastle.pqc.jcajce.provider.util.AsymmetricHybridCipher;
+
+public class McElieceKobaraImaiCipherSpi
+ extends AsymmetricHybridCipher
+ implements PKCSObjectIdentifiers, X509ObjectIdentifiers
+{
+
+ // TODO digest needed?
+ private Digest digest;
+ private McElieceKobaraImaiCipher cipher;
+
+ /**
+ * buffer to store the input data
+ */
+ private ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+
+ public McElieceKobaraImaiCipherSpi()
+ {
+ buf = new ByteArrayOutputStream();
+ }
+
+ protected McElieceKobaraImaiCipherSpi(Digest digest, McElieceKobaraImaiCipher cipher)
+ {
+ this.digest = digest;
+ this.cipher = cipher;
+ buf = new ByteArrayOutputStream();
+ }
+
+ /**
+ * Continue a multiple-part encryption or decryption operation.
+ *
+ * @param input byte array containing the next part of the input
+ * @param inOff index in the array where the input starts
+ * @param inLen length of the input
+ * @return the processed byte array.
+ */
+ public byte[] update(byte[] input, int inOff, int inLen)
+ {
+ buf.write(input, inOff, inLen);
+ return new byte[0];
+ }
+
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted, depending on
+ * how this cipher was initialized.
+ *
+ * @param input the input buffer
+ * @param inOff the offset in input where the input starts
+ * @param inLen the input length
+ * @return the new buffer with the result
+ * @throws BadPaddingException if this cipher is in decryption mode, and (un)padding has
+ * been requested, but the decrypted data is not bounded by
+ * the appropriate padding bytes
+ */
+ public byte[] doFinal(byte[] input, int inOff, int inLen)
+ throws BadPaddingException
+ {
+ update(input, inOff, inLen);
+ if (opMode == ENCRYPT_MODE)
+ {
+
+ try
+ {
+ return cipher.messageEncrypt(this.pad());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ }
+ else if (opMode == DECRYPT_MODE)
+ {
+ byte[] inputOfDecr = buf.toByteArray();
+ buf.reset();
+
+ try
+ {
+ return unpad(cipher.messageDecrypt(inputOfDecr));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ }
+ return null;
+ }
+
+ protected int encryptOutputSize(int inLen)
+ {
+ return 0;
+ }
+
+ protected int decryptOutputSize(int inLen)
+ {
+ return 0;
+ }
+
+ protected void initCipherEncrypt(Key key, AlgorithmParameterSpec params,
+ SecureRandom sr)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+
+ buf.reset();
+ CipherParameters param;
+ param = McElieceCCA2KeysToParams.generatePublicKeyParameter((PublicKey)key);
+
+ param = new ParametersWithRandom(param, sr);
+ digest.reset();
+ cipher.init(true, param);
+ }
+
+ protected void initCipherDecrypt(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+
+ buf.reset();
+ CipherParameters param;
+ param = McElieceCCA2KeysToParams.generatePrivateKeyParameter((PrivateKey)key);
+
+ digest.reset();
+ cipher.init(false, param);
+ }
+
+ public String getName()
+ {
+ return "McElieceKobaraImaiCipher";
+ }
+
+ public int getKeySize(Key key)
+ throws InvalidKeyException
+ {
+ McElieceCCA2KeyParameters mcElieceCCA2KeyParameters;
+ if (key instanceof PublicKey)
+ {
+ mcElieceCCA2KeyParameters = (McElieceCCA2KeyParameters)McElieceCCA2KeysToParams.generatePublicKeyParameter((PublicKey)key);
+ return cipher.getKeySize(mcElieceCCA2KeyParameters);
+ }
+ else if (key instanceof PrivateKey)
+ {
+ mcElieceCCA2KeyParameters = (McElieceCCA2KeyParameters)McElieceCCA2KeysToParams.generatePrivateKeyParameter((PrivateKey)key);
+ return cipher.getKeySize(mcElieceCCA2KeyParameters);
+ }
+ else
+ {
+ throw new InvalidKeyException();
+ }
+
+
+ }
+
+ /**
+ * Pad and return the message stored in the message buffer.
+ *
+ * @return the padded message
+ */
+ private byte[] pad()
+ {
+ buf.write(0x01);
+ byte[] result = buf.toByteArray();
+ buf.reset();
+ return result;
+ }
+
+ /**
+ * Unpad a message.
+ *
+ * @param pmBytes the padded message
+ * @return the message
+ * @throws BadPaddingException if the padded message is invalid.
+ */
+ private byte[] unpad(byte[] pmBytes)
+ throws BadPaddingException
+ {
+ // find first non-zero byte
+ int index;
+ for (index = pmBytes.length - 1; index >= 0 && pmBytes[index] == 0; index--)
+ {
+ ;
+ }
+
+ // check if padding byte is valid
+ if (pmBytes[index] != 0x01)
+ {
+ throw new BadPaddingException("invalid ciphertext");
+ }
+
+ // extract and return message
+ byte[] mBytes = new byte[index];
+ System.arraycopy(pmBytes, 0, mBytes, 0, index);
+ return mBytes;
+ }
+
+
+ public byte[] messageEncrypt()
+ throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException
+ {
+ byte[] output = null;
+ try
+ {
+ output = cipher.messageEncrypt((this.pad()));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return output;
+ }
+
+
+ public byte[] messageDecrypt()
+ throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException
+ {
+ byte[] output = null;
+ byte[] inputOfDecr = buf.toByteArray();
+ buf.reset();
+ try
+ {
+ output = unpad(cipher.messageDecrypt(inputOfDecr));
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return output;
+ }
+
+
+ static public class McElieceKobaraImai
+ extends McElieceKobaraImaiCipherSpi
+ {
+ public McElieceKobaraImai()
+ {
+ super(new SHA1Digest(), new McElieceKobaraImaiCipher());
+ }
+ }
+
+ static public class McElieceKobaraImai224
+ extends McElieceKobaraImaiCipherSpi
+ {
+ public McElieceKobaraImai224()
+ {
+ super(new SHA224Digest(), new McElieceKobaraImaiCipher());
+ }
+ }
+
+ static public class McElieceKobaraImai256
+ extends McElieceKobaraImaiCipherSpi
+ {
+ public McElieceKobaraImai256()
+ {
+ super(new SHA256Digest(), new McElieceKobaraImaiCipher());
+ }
+ }
+
+ static public class McElieceKobaraImai384
+ extends McElieceKobaraImaiCipherSpi
+ {
+ public McElieceKobaraImai384()
+ {
+ super(new SHA384Digest(), new McElieceKobaraImaiCipher());
+ }
+ }
+
+ static public class McElieceKobaraImai512
+ extends McElieceKobaraImaiCipherSpi
+ {
+ public McElieceKobaraImai512()
+ {
+ super(new SHA512Digest(), new McElieceKobaraImaiCipher());
+ }
+ }
+
+
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McEliecePKCSCipherSpi.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McEliecePKCSCipherSpi.java
new file mode 100644
index 00000000..cbabfdcc
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McEliecePKCSCipherSpi.java
@@ -0,0 +1,171 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.mceliece.McElieceKeyParameters;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePKCSCipher;
+import org.spongycastle.pqc.jcajce.provider.util.AsymmetricBlockCipher;
+
+public class McEliecePKCSCipherSpi
+ extends AsymmetricBlockCipher
+ implements PKCSObjectIdentifiers, X509ObjectIdentifiers
+{
+ // TODO digest needed?
+ private Digest digest;
+ private McEliecePKCSCipher cipher;
+
+ public McEliecePKCSCipherSpi(Digest digest, McEliecePKCSCipher cipher)
+ {
+ this.digest = digest;
+ this.cipher = cipher;
+ }
+
+ protected void initCipherEncrypt(Key key, AlgorithmParameterSpec params,
+ SecureRandom sr)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+
+ CipherParameters param;
+ param = McElieceKeysToParams.generatePublicKeyParameter((PublicKey)key);
+
+ param = new ParametersWithRandom(param, sr);
+ digest.reset();
+ cipher.init(true, param);
+ this.maxPlainTextSize = cipher.maxPlainTextSize;
+ this.cipherTextSize = cipher.cipherTextSize;
+ }
+
+ protected void initCipherDecrypt(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ CipherParameters param;
+ param = McElieceKeysToParams.generatePrivateKeyParameter((PrivateKey)key);
+
+ digest.reset();
+ cipher.init(false, param);
+ this.maxPlainTextSize = cipher.maxPlainTextSize;
+ this.cipherTextSize = cipher.cipherTextSize;
+ }
+
+ protected byte[] messageEncrypt(byte[] input)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+ byte[] output = null;
+ try
+ {
+ output = cipher.messageEncrypt(input);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return output;
+ }
+
+ protected byte[] messageDecrypt(byte[] input)
+ throws IllegalBlockSizeException, BadPaddingException
+ {
+ byte[] output = null;
+ try
+ {
+ output = cipher.messageDecrypt(input);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return output;
+ }
+
+ public String getName()
+ {
+ return "McEliecePKCS";
+ }
+
+ public int getKeySize(Key key)
+ throws InvalidKeyException
+ {
+ McElieceKeyParameters mcElieceKeyParameters;
+ if (key instanceof PublicKey)
+ {
+ mcElieceKeyParameters = (McElieceKeyParameters)McElieceKeysToParams.generatePublicKeyParameter((PublicKey)key);
+ }
+ else
+ {
+ mcElieceKeyParameters = (McElieceKeyParameters)McElieceKeysToParams.generatePrivateKeyParameter((PrivateKey)key);
+
+ }
+
+
+ return cipher.getKeySize(mcElieceKeyParameters);
+ }
+
+ //////////////////////////////////////////////////////////////////////////////////
+
+ static public class McEliecePKCS
+ extends McEliecePKCSCipherSpi
+ {
+ public McEliecePKCS()
+ {
+ super(new SHA1Digest(), new McEliecePKCSCipher());
+ }
+ }
+
+ static public class McEliecePKCS224
+ extends McEliecePKCSCipherSpi
+ {
+ public McEliecePKCS224()
+ {
+ super(new SHA224Digest(), new McEliecePKCSCipher());
+ }
+ }
+
+ static public class McEliecePKCS256
+ extends McEliecePKCSCipherSpi
+ {
+ public McEliecePKCS256()
+ {
+ super(new SHA256Digest(), new McEliecePKCSCipher());
+ }
+ }
+
+ static public class McEliecePKCS384
+ extends McEliecePKCSCipherSpi
+ {
+ public McEliecePKCS384()
+ {
+ super(new SHA384Digest(), new McEliecePKCSCipher());
+ }
+ }
+
+ static public class McEliecePKCS512
+ extends McEliecePKCSCipherSpi
+ {
+ public McEliecePKCS512()
+ {
+ super(new SHA512Digest(), new McEliecePKCSCipher());
+ }
+ }
+
+
+}
diff --git a/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McEliecePointchevalCipherSpi.java b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McEliecePointchevalCipherSpi.java
new file mode 100644
index 00000000..314b7a30
--- /dev/null
+++ b/prov/src/main/java/org/spongycastle/pqc/jcajce/provider/mceliece/McEliecePointchevalCipherSpi.java
@@ -0,0 +1,247 @@
+package org.spongycastle.pqc.jcajce.provider.mceliece;
+
+import java.io.ByteArrayOutputStream;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.spec.AlgorithmParameterSpec;
+
+import javax.crypto.BadPaddingException;
+import javax.crypto.IllegalBlockSizeException;
+
+import org.spongycastle.asn1.pkcs.PKCSObjectIdentifiers;
+import org.spongycastle.asn1.x509.X509ObjectIdentifiers;
+import org.spongycastle.crypto.CipherParameters;
+import org.spongycastle.crypto.Digest;
+import org.spongycastle.crypto.digests.SHA1Digest;
+import org.spongycastle.crypto.digests.SHA224Digest;
+import org.spongycastle.crypto.digests.SHA256Digest;
+import org.spongycastle.crypto.digests.SHA384Digest;
+import org.spongycastle.crypto.digests.SHA512Digest;
+import org.spongycastle.crypto.params.ParametersWithRandom;
+import org.spongycastle.pqc.crypto.mceliece.McElieceCCA2KeyParameters;
+import org.spongycastle.pqc.crypto.mceliece.McEliecePointchevalCipher;
+import org.spongycastle.pqc.jcajce.provider.util.AsymmetricHybridCipher;
+
+public class McEliecePointchevalCipherSpi
+ extends AsymmetricHybridCipher
+ implements PKCSObjectIdentifiers, X509ObjectIdentifiers
+{
+ // TODO digest needed?
+ private Digest digest;
+ private McEliecePointchevalCipher cipher;
+
+ /**
+ * buffer to store the input data
+ */
+ private ByteArrayOutputStream buf = new ByteArrayOutputStream();
+
+
+ protected McEliecePointchevalCipherSpi(Digest digest, McEliecePointchevalCipher cipher)
+ {
+ this.digest = digest;
+ this.cipher = cipher;
+ buf = new ByteArrayOutputStream();
+ }
+
+ /**
+ * Continue a multiple-part encryption or decryption operation.
+ *
+ * @param input byte array containing the next part of the input
+ * @param inOff index in the array where the input starts
+ * @param inLen length of the input
+ * @return the processed byte array.
+ */
+ public byte[] update(byte[] input, int inOff, int inLen)
+ {
+ buf.write(input, inOff, inLen);
+ return new byte[0];
+ }
+
+
+ /**
+ * Encrypts or decrypts data in a single-part operation, or finishes a
+ * multiple-part operation. The data is encrypted or decrypted, depending on
+ * how this cipher was initialized.
+ *
+ * @param input the input buffer
+ * @param inOff the offset in input where the input starts
+ * @param inLen the input length
+ * @return the new buffer with the result
+ * @throws BadPaddingException on deryption errors.
+ */
+ public byte[] doFinal(byte[] input, int inOff, int inLen)
+ throws BadPaddingException
+ {
+ update(input, inOff, inLen);
+ byte[] data = buf.toByteArray();
+ buf.reset();
+ if (opMode == ENCRYPT_MODE)
+ {
+
+ try
+ {
+ return cipher.messageEncrypt(data);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ }
+ else if (opMode == DECRYPT_MODE)
+ {
+
+ try
+ {
+ return cipher.messageDecrypt(data);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+
+ }
+ return null;
+ }
+
+ protected int encryptOutputSize(int inLen)
+ {
+ return 0;
+ }
+
+ protected int decryptOutputSize(int inLen)
+ {
+ return 0;
+ }
+
+ protected void initCipherEncrypt(Key key, AlgorithmParameterSpec params,
+ SecureRandom sr)
+ throws InvalidKeyException,
+ InvalidAlgorithmParameterException
+ {
+ CipherParameters param;
+ param = McElieceCCA2KeysToParams.generatePublicKeyParameter((PublicKey)key);
+
+ param = new ParametersWithRandom(param, sr);
+ digest.reset();
+ cipher.init(true, param);
+ }
+
+ protected void initCipherDecrypt(Key key, AlgorithmParameterSpec params)
+ throws InvalidKeyException, InvalidAlgorithmParameterException
+ {
+ CipherParameters param;
+ param = McElieceCCA2KeysToParams.generatePrivateKeyParameter((PrivateKey)key);
+
+ digest.reset();
+ cipher.init(false, param);
+ }
+
+ public String getName()
+ {
+ return "McEliecePointchevalCipher";
+ }
+
+
+ public int getKeySize(Key key)
+ throws InvalidKeyException
+ {
+ McElieceCCA2KeyParameters mcElieceCCA2KeyParameters;
+ if (key instanceof PublicKey)
+ {
+ mcElieceCCA2KeyParameters = (McElieceCCA2KeyParameters)McElieceCCA2KeysToParams.generatePublicKeyParameter((PublicKey)key);
+ }
+ else
+ {
+ mcElieceCCA2KeyParameters = (McElieceCCA2KeyParameters)McElieceCCA2KeysToParams.generatePrivateKeyParameter((PrivateKey)key);
+ }
+
+ return cipher.getKeySize(mcElieceCCA2KeyParameters);
+ }
+
+ public byte[] messageEncrypt(byte[] input)
+ throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException
+ {
+ byte[] output = null;
+ try
+ {
+ output = cipher.messageEncrypt(input);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return output;
+ }
+
+
+ public byte[] messageDecrypt(byte[] input)
+ throws IllegalBlockSizeException, BadPaddingException, NoSuchAlgorithmException
+ {
+ byte[] output = null;
+ try
+ {
+ output = cipher.messageDecrypt(input);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return output;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////////////77
+
+ static public class McEliecePointcheval
+ extends McEliecePointchevalCipherSpi
+ {
+ public McEliecePointcheval()
+ {
+ super(new SHA1Digest(), new McEliecePointchevalCipher());
+ }
+ }
+
+ static public class McEliecePointcheval224
+ extends McEliecePointchevalCipherSpi
+ {
+ public McEliecePointcheval224()
+ {
+ super(new SHA224Digest(), new McEliecePointchevalCipher());
+ }
+ }
+
+ static public class McEliecePointcheval256
+ extends McEliecePointchevalCipherSpi
+ {
+ public McEliecePointcheval256()
+ {
+ super(new SHA256Digest(), new McEliecePointchevalCipher());
+ }
+ }
+
+ static public class McEliecePointcheval384
+ extends McEliecePointchevalCipherSpi
+ {
+ public McEliecePointcheval384()
+ {
+ super(new SHA384Digest(), new McEliecePointchevalCipher());
+ }
+ }
+
+ static public class McEliecePointcheval512
+ extends McEliecePointchevalCipherSpi
+ {
+ public McEliecePointcheval512()
+ {
+ super(new SHA512Digest(), new McEliecePointchevalCipher());
+ }
+ }
+
+
+}