diff options
Diffstat (limited to 'bcprov/src/main/java/org/bouncycastle/pqc/jcajce/provider/mceliece/McElieceKeyFactorySpi.java')
-rw-r--r-- | bcprov/src/main/java/org/bouncycastle/pqc/jcajce/provider/mceliece/McElieceKeyFactorySpi.java | 343 |
1 files changed, 343 insertions, 0 deletions
diff --git a/bcprov/src/main/java/org/bouncycastle/pqc/jcajce/provider/mceliece/McElieceKeyFactorySpi.java b/bcprov/src/main/java/org/bouncycastle/pqc/jcajce/provider/mceliece/McElieceKeyFactorySpi.java new file mode 100644 index 0000000..c1df9e9 --- /dev/null +++ b/bcprov/src/main/java/org/bouncycastle/pqc/jcajce/provider/mceliece/McElieceKeyFactorySpi.java @@ -0,0 +1,343 @@ +package org.bouncycastle.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.bouncycastle.asn1.ASN1Integer; +import org.bouncycastle.asn1.ASN1ObjectIdentifier; +import org.bouncycastle.asn1.ASN1OctetString; +import org.bouncycastle.asn1.ASN1Primitive; +import org.bouncycastle.asn1.ASN1Sequence; +import org.bouncycastle.asn1.pkcs.PrivateKeyInfo; +import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo; +import org.bouncycastle.pqc.asn1.McEliecePrivateKey; +import org.bouncycastle.pqc.asn1.McEliecePublicKey; +import org.bouncycastle.pqc.jcajce.spec.McEliecePrivateKeySpec; +import org.bouncycastle.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. + } +} |