GordianKeyPairAlgId.java
/*
* GordianKnot: Security Suite
* Copyright 2012-2026. Tony Washer
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy
* of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package io.github.tonywasher.joceanus.gordianknot.impl.core.keypair;
import io.github.tonywasher.joceanus.gordianknot.api.base.GordianException;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianBIKESpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianCMCESpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianDHGroup;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianDSAElliptic;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianDSAKeyType;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianDSTU4145Elliptic;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianFRODOSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianFalconSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianGOSTElliptic;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianHQCSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianKeyPairSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianKeyPairSpecBuilder;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianLMSKeySpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianMLDSASpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianMLKEMSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianMayoSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianNTRUPrimeSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianNTRUPrimeSpec.GordianNTRUPrimeParams;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianNTRUPrimeSpec.GordianNTRUPrimeType;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianNTRUSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianPicnicSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianRSAModulus;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianSABERSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianSLHDSASpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianSM2Elliptic;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianSnovaSpec;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianXMSSKeySpec.GordianXMSSDigestType;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianXMSSKeySpec.GordianXMSSHeight;
import io.github.tonywasher.joceanus.gordianknot.api.keypair.GordianXMSSKeySpec.GordianXMSSMTLayers;
import io.github.tonywasher.joceanus.gordianknot.impl.core.exc.GordianDataException;
import io.github.tonywasher.joceanus.gordianknot.impl.core.exc.GordianIOException;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1OctetString;
import org.bouncycastle.asn1.ASN1Sequence;
import org.bouncycastle.asn1.cryptopro.ECGOST3410NamedCurves;
import org.bouncycastle.asn1.cryptopro.GOST3410PublicKeyAlgParameters;
import org.bouncycastle.asn1.edec.EdECObjectIdentifiers;
import org.bouncycastle.asn1.isara.IsaraObjectIdentifiers;
import org.bouncycastle.asn1.misc.MiscObjectIdentifiers;
import org.bouncycastle.asn1.nist.NISTObjectIdentifiers;
import org.bouncycastle.asn1.oiw.ElGamalParameter;
import org.bouncycastle.asn1.oiw.OIWObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.DHParameter;
import org.bouncycastle.asn1.pkcs.PKCSObjectIdentifiers;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.pkcs.RSAPrivateKey;
import org.bouncycastle.asn1.pkcs.RSAPublicKey;
import org.bouncycastle.asn1.rosstandart.RosstandartObjectIdentifiers;
import org.bouncycastle.asn1.ua.DSTU4145NamedCurves;
import org.bouncycastle.asn1.ua.DSTU4145Params;
import org.bouncycastle.asn1.ua.UAObjectIdentifiers;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.DSAParameter;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.asn1.x9.DomainParameters;
import org.bouncycastle.asn1.x9.ECNamedCurveTable;
import org.bouncycastle.asn1.x9.X962Parameters;
import org.bouncycastle.asn1.x9.X9ObjectIdentifiers;
import org.bouncycastle.crypto.ec.CustomNamedCurves;
import org.bouncycastle.crypto.params.DHParameters;
import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.pqc.asn1.PQCObjectIdentifiers;
import org.bouncycastle.pqc.asn1.XMSSKeyParams;
import org.bouncycastle.pqc.asn1.XMSSMTKeyParams;
import org.bouncycastle.pqc.crypto.lms.HSSPrivateKeyParameters;
import org.bouncycastle.pqc.crypto.lms.HSSPublicKeyParameters;
import org.bouncycastle.pqc.crypto.lms.LMSKeyParameters;
import org.bouncycastle.pqc.crypto.lms.LMSPrivateKeyParameters;
import org.bouncycastle.pqc.crypto.lms.LMSPublicKeyParameters;
import org.bouncycastle.pqc.crypto.util.PrivateKeyFactory;
import org.bouncycastle.pqc.crypto.util.PublicKeyFactory;
import org.bouncycastle.pqc.crypto.xmss.XMSSMTParameters;
import org.bouncycastle.pqc.crypto.xmss.XMSSParameters;
import org.bouncycastle.util.Pack;
import java.io.IOException;
import java.math.BigInteger;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
/**
* Mappings from EncodedId to KeyPairSpec.
*/
public class GordianKeyPairAlgId {
/**
* TWO as big integer.
*/
private static final BigInteger TWO = BigInteger.valueOf(2);
/**
* The algorithm error.
*/
private static final String ERROR_ALGO = "Unrecognised algorithm";
/**
* The parse error.
*/
private static final String ERROR_PARSE = "Failed to parse Key";
/**
* The namedCurve error.
*/
private static final String ERROR_NAMEDCURVE = "Not a Named Curve";
/**
* The unsupportedCurve error.
*/
private static final String ERROR_UNSUPCURVE = "Unsupported Curve: ";
/**
* The treeDigest error.
*/
private static final String ERROR_TREEDIGEST = "Unsupported treeDigest: ";
/**
* The parser map.
*/
private final Map<ASN1ObjectIdentifier, GordianEncodedParser> theParserMap;
/**
* Constructor.
*/
public GordianKeyPairAlgId() {
/* Create the map */
theParserMap = new HashMap<>();
/* Register the parsers */
GordianRSAEncodedParser.register(this);
GordianElGamalEncodedParser.register(this);
GordianDSAEncodedParser.register(this);
GordianDHEncodedParser.register(this);
GordianECEncodedParser.register(this);
GordianDSTUEncodedParser.register(this);
GordianGOSTEncodedParser.register(this);
GordianEdwardsEncodedParser.register(this);
GordianSLHDSAEncodedParser.register(this);
GordianXMSSEncodedParser.register(this);
GordianXMSSMTEncodedParser.register(this);
GordianLMSEncodedParser.register(this);
GordianNewHopeEncodedParser.register(this);
GordianCMCEEncodedParser.register(this);
GordianFrodoEncodedParser.register(this);
GordianSABEREncodedParser.register(this);
GordianMLKEMEncodedParser.register(this);
GordianMLDSAEncodedParser.register(this);
GordianHQCEncodedParser.register(this);
GordianBIKEEncodedParser.register(this);
GordianNTRUEncodedParser.register(this);
GordianNTRUPrimeEncodedParser.register(this);
GordianFalconEncodedParser.register(this);
GordianMayoEncodedParser.register(this);
GordianSnovaEncodedParser.register(this);
GordianPicnicEncodedParser.register(this);
GordianCompositeEncodedParser.register(this);
}
/**
* Obtain KeySpec from X509KeySpec.
*
* @param pEncoded X509 keySpec
* @return the keySpec
* @throws GordianException on error
*/
public GordianKeyPairSpec determineKeyPairSpec(final PKCS8EncodedKeySpec pEncoded) throws GordianException {
/* Determine the algorithm Id. */
final PrivateKeyInfo myInfo = PrivateKeyInfo.getInstance(pEncoded.getEncoded());
final AlgorithmIdentifier myId = myInfo.getPrivateKeyAlgorithm();
final ASN1ObjectIdentifier myAlgId = myId.getAlgorithm();
/* Obtain the parser */
final GordianEncodedParser myParser = theParserMap.get(myAlgId);
if (myParser != null) {
return myParser.determineKeyPairSpec(myInfo);
}
throw new GordianDataException(ERROR_ALGO);
}
/**
* Obtain KeySpec from X509KeySpec.
*
* @param pEncoded X509 keySpec
* @return the keySpec
* @throws GordianException on error
*/
public GordianKeyPairSpec determineKeyPairSpec(final X509EncodedKeySpec pEncoded) throws GordianException {
/* Determine the algorithm Id. */
final SubjectPublicKeyInfo myInfo = SubjectPublicKeyInfo.getInstance(pEncoded.getEncoded());
final AlgorithmIdentifier myId = myInfo.getAlgorithm();
final ASN1ObjectIdentifier myAlgId = myId.getAlgorithm();
/* Obtain the parser */
final GordianEncodedParser myParser = theParserMap.get(myAlgId);
if (myParser != null) {
return myParser.determineKeyPairSpec(myInfo);
}
throw new GordianDataException(ERROR_ALGO);
}
/**
* register the parser.
*
* @param pAlgId the algorithm Id.
* @param pParser the parser
*/
void registerParser(final ASN1ObjectIdentifier pAlgId,
final GordianEncodedParser pParser) {
theParserMap.put(pAlgId, pParser);
}
/**
* EncodedParser interface.
*/
private interface GordianEncodedParser {
/**
* Obtain KeySpec from PrivateKeyInfo.
*
* @param pInfo keySpec
* @return the keySpec
* @throws GordianException on error
*/
GordianKeyPairSpec determineKeyPairSpec(SubjectPublicKeyInfo pInfo) throws GordianException;
/**
* Obtain KeySpec from SubjectPublicKeyInfo.
*
* @param pInfo keySpec
* @return the keySpec
* @throws GordianException on error
*/
GordianKeyPairSpec determineKeyPairSpec(PrivateKeyInfo pInfo) throws GordianException;
}
/**
* RSA Encoded parser.
*/
private static final class GordianRSAEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(PKCSObjectIdentifiers.rsaEncryption, new GordianRSAEncodedParser());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
/* Protect against exceptions */
try {
/* Parse the publicKey */
final RSAPublicKey myPublic = RSAPublicKey.getInstance(pInfo.parsePublicKey());
return determineKeyPairSpec(myPublic.getModulus());
/* Handle exceptions */
} catch (IOException e) {
throw new GordianIOException(ERROR_PARSE, e);
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
/* Protect against exceptions */
try {
/* Parse the publicKey */
final RSAPrivateKey myPrivate = RSAPrivateKey.getInstance(pInfo.parsePrivateKey());
return determineKeyPairSpec(myPrivate.getModulus());
/* Handle exceptions */
} catch (IOException e) {
throw new GordianIOException(ERROR_PARSE, e);
}
}
/**
* Obtain keySpec from Modulus.
*
* @param pModulus the modulus
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final BigInteger pModulus) throws GordianException {
final GordianRSAModulus myModulus = GordianRSAModulus.getModulusForInteger(pModulus);
if (myModulus == null) {
throw new GordianDataException("RSA strength not supported: " + pModulus.bitLength());
}
return GordianKeyPairSpecBuilder.rsa(myModulus);
}
}
/**
* DSA Encoded parser.
*/
private static final class GordianDSAEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(X9ObjectIdentifiers.id_dsa, new GordianDSAEncodedParser());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
final AlgorithmIdentifier myId = pInfo.getAlgorithm();
final DSAParameter myParms = DSAParameter.getInstance(myId.getParameters());
return determineKeyPairSpec(myParms);
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
final AlgorithmIdentifier myId = pInfo.getPrivateKeyAlgorithm();
final DSAParameter myParms = DSAParameter.getInstance(myId.getParameters());
return determineKeyPairSpec(myParms);
}
/**
* Obtain keySpec from Parameters.
*
* @param pParms the parameters
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final DSAParameter pParms) throws GordianException {
final GordianDSAKeyType myKeyType = GordianDSAKeyType.getDSATypeForParms(pParms);
if (myKeyType == null) {
throw new GordianDataException("Unsupported DSA parameters: "
+ pParms.getP().bitLength() + ":" + pParms.getQ().bitLength());
}
return GordianKeyPairSpecBuilder.dsa(myKeyType);
}
}
/**
* DH Encoded parser.
*/
public static class GordianDHEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(PKCSObjectIdentifiers.dhKeyAgreement, new GordianDHEncodedParser());
pIdManager.registerParser(X9ObjectIdentifiers.dhpublicnumber, new GordianDHEncodedParser());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
final DHParameters myParms = determineParameters(pInfo.getAlgorithm());
return determineKeyPairSpec(myParms);
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
final DHParameters myParms = determineParameters(pInfo.getPrivateKeyAlgorithm());
return determineKeyPairSpec(myParms);
}
/**
* Obtain parameters from encoded sequence.
*
* @param pId the algorithm Identifier
* @return the parameters
*/
public static DHParameters determineParameters(final AlgorithmIdentifier pId) {
/* Access algorithmId */
final ASN1ObjectIdentifier myId = pId.getAlgorithm();
/* If this is key agreement */
if (PKCSObjectIdentifiers.dhKeyAgreement.equals(myId)) {
/* Access the DHParameter */
final DHParameter myParams = DHParameter.getInstance(pId.getParameters());
/* If we have an L value */
return myParams.getL() != null
? new DHParameters(myParams.getP(), myParams.getG(), null, myParams.getL().intValue())
: new DHParameters(myParams.getP(), myParams.getG());
} else if (X9ObjectIdentifiers.dhpublicnumber.equals(myId)) {
/* Access Domain Parameters */
final DomainParameters myParams = DomainParameters.getInstance(pId.getParameters());
return new DHParameters(myParams.getP(), myParams.getG(), myParams.getQ(), myParams.getJ(), null);
} else {
throw new IllegalArgumentException("unknown algorithm type: " + myId);
}
}
/**
* Obtain keySpec from Parameters.
*
* @param pParms the parameters
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final DHParameters pParms) throws GordianException {
final GordianDHGroup myGroup = GordianDHGroup.getGroupForParams(pParms);
if (myGroup == null) {
throw new GordianDataException("Unsupported DH parameters: "
+ pParms.getP().bitLength());
}
return GordianKeyPairSpecBuilder.dh(myGroup);
}
}
/**
* ElGamal Encoded parser.
*/
public static class GordianElGamalEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(OIWObjectIdentifiers.elGamalAlgorithm, new GordianElGamalEncodedParser());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
final DHParameters myParms = determineParameters(pInfo.getAlgorithm());
return determineKeyPairSpec(myParms);
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
final DHParameters myParms = determineParameters(pInfo.getPrivateKeyAlgorithm());
return determineKeyPairSpec(myParms);
}
/**
* Obtain parameters from encoded sequence.
*
* @param pId the algorithm Identifier
* @return the parameters
*/
public static DHParameters determineParameters(final AlgorithmIdentifier pId) {
/* Access the ElGamalParameter */
final ElGamalParameter myParams = ElGamalParameter.getInstance(pId.getParameters());
/* Convert to DH parameters */
return new DHParameters(myParams.getP(), TWO, myParams.getG());
}
/**
* Obtain keySpec from Parameters.
*
* @param pParms the parameters
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final DHParameters pParms) throws GordianException {
final GordianDHGroup myGroup = GordianDHGroup.getGroupForParams(pParms);
if (myGroup == null) {
throw new GordianDataException("Unsupported DH parameters: "
+ pParms.getP().bitLength());
}
return GordianKeyPairSpecBuilder.elGamal(myGroup);
}
}
/**
* EC Encoded parser.
*/
private static final class GordianECEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(X9ObjectIdentifiers.id_ecPublicKey, new GordianECEncodedParser());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
final AlgorithmIdentifier myId = pInfo.getAlgorithm();
final X962Parameters myParms = X962Parameters.getInstance(myId.getParameters());
return determineKeyPairSpec(myParms);
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
final AlgorithmIdentifier myId = pInfo.getPrivateKeyAlgorithm();
final X962Parameters myParms = X962Parameters.getInstance(myId.getParameters());
return determineKeyPairSpec(myParms);
}
/**
* Obtain keySpec from Parameters.
*
* @param pParms the parameters
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final X962Parameters pParms) throws GordianException {
/* Reject if not a named curve */
if (!pParms.isNamedCurve()) {
throw new GordianDataException(ERROR_NAMEDCURVE);
}
/* Check for EC named curve */
final ASN1ObjectIdentifier myId = (ASN1ObjectIdentifier) pParms.getParameters();
String myName = CustomNamedCurves.getName(myId);
if (myName == null) {
myName = ECNamedCurveTable.getName(myId);
}
if (myName != null) {
final GordianDSAElliptic myDSACurve = GordianDSAElliptic.getCurveForName(myName);
if (myDSACurve != null) {
return GordianKeyPairSpecBuilder.ec(myDSACurve);
}
final GordianSM2Elliptic mySM2Curve = GordianSM2Elliptic.getCurveForName(myName);
if (mySM2Curve != null) {
return GordianKeyPairSpecBuilder.sm2(mySM2Curve);
}
throw new GordianDataException(ERROR_UNSUPCURVE + myName);
}
/* Curve is not supported */
throw new GordianDataException(ERROR_UNSUPCURVE + pParms);
}
}
/**
* DSTU Encoded parser.
*/
private static final class GordianDSTUEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(UAObjectIdentifiers.dstu4145be, new GordianDSTUEncodedParser());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
final AlgorithmIdentifier myId = pInfo.getAlgorithm();
final DSTU4145Params myParms = DSTU4145Params.getInstance(myId.getParameters());
return determineKeyPairSpec(myParms);
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
final AlgorithmIdentifier myId = pInfo.getPrivateKeyAlgorithm();
final X962Parameters myParms = X962Parameters.getInstance(myId.getParameters());
return determineKeyPairSpec(myParms);
}
/**
* Obtain keySpec from Parameters.
*
* @param pParms the parameters
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final DSTU4145Params pParms) throws GordianException {
/* Reject if not a named curve */
if (!pParms.isNamedCurve()) {
throw new GordianDataException(ERROR_NAMEDCURVE);
}
return determineKeyPairSpec(pParms.getNamedCurve());
}
/**
* Obtain keySpec from Parameters.
*
* @param pParms the parameters
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final X962Parameters pParms) throws GordianException {
/* Reject if not a named curve */
if (!pParms.isNamedCurve()) {
throw new GordianDataException(ERROR_NAMEDCURVE);
}
return determineKeyPairSpec((ASN1ObjectIdentifier) pParms.getParameters());
}
/**
* Obtain keySpec from curveId.
*
* @param pId the curveId
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final ASN1ObjectIdentifier pId) throws GordianException {
/* Check for EC named surve */
final String myName = pId.toString();
final ECDomainParameters myParms = DSTU4145NamedCurves.getByOID(pId);
final GordianDSTU4145Elliptic myCurve = GordianDSTU4145Elliptic.getCurveForName(myName);
if (myParms == null || myCurve == null) {
throw new GordianDataException(ERROR_UNSUPCURVE + myName);
}
return GordianKeyPairSpecBuilder.dstu4145(myCurve);
}
}
/**
* GOST Encoded parser.
*/
private static final class GordianGOSTEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
final GordianGOSTEncodedParser myParser = new GordianGOSTEncodedParser();
pIdManager.registerParser(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_256, myParser);
pIdManager.registerParser(RosstandartObjectIdentifiers.id_tc26_gost_3410_12_512, myParser);
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return determineKeyPairSpec(pInfo.getAlgorithm());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return determineKeyPairSpec(pInfo.getPrivateKeyAlgorithm());
}
/**
* Obtain keySpec from Parameters.
*
* @param pId the algorithmId
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final AlgorithmIdentifier pId) throws GordianException {
/* Determine the curve name */
final GOST3410PublicKeyAlgParameters myParms = GOST3410PublicKeyAlgParameters.getInstance(pId.getParameters());
final ASN1ObjectIdentifier myId = myParms.getPublicKeyParamSet();
final String myName = ECGOST3410NamedCurves.getName(myId);
/* Determine curve */
if (myName != null) {
final GordianGOSTElliptic myCurve = GordianGOSTElliptic.getCurveForName(myName);
if (myCurve == null) {
throw new GordianDataException(ERROR_UNSUPCURVE + myName);
}
return GordianKeyPairSpecBuilder.gost2012(myCurve);
}
/* Curve is not supported */
throw new GordianDataException(ERROR_UNSUPCURVE + myParms);
}
}
/**
* SLHDSA Encoded parser.
*/
private static class GordianSLHDSAEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianSLHDSAEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianSLHDSASpec mySpec : GordianSLHDSASpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianSLHDSAEncodedParser(GordianKeyPairSpecBuilder.slhdsa(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* CMCE Encoded parser.
*/
private static class GordianCMCEEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianCMCEEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianCMCESpec mySpec : GordianCMCESpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianCMCEEncodedParser(GordianKeyPairSpecBuilder.cmce(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* Frodo Encoded parser.
*/
private static class GordianFrodoEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianFrodoEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianFRODOSpec mySpec : GordianFRODOSpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianFrodoEncodedParser(GordianKeyPairSpecBuilder.frodo(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* SABER Encoded parser.
*/
private static class GordianSABEREncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianSABEREncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianSABERSpec mySpec : GordianSABERSpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianSABEREncodedParser(GordianKeyPairSpecBuilder.saber(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* MLKEM Encoded parser.
*/
private static class GordianMLKEMEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianMLKEMEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianMLKEMSpec mySpec : GordianMLKEMSpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianMLKEMEncodedParser(GordianKeyPairSpecBuilder.mlkem(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* MLDSA Encoded parser.
*/
private static class GordianMLDSAEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianMLDSAEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianMLDSASpec mySpec : GordianMLDSASpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianMLDSAEncodedParser(GordianKeyPairSpecBuilder.mldsa(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* HQC Encoded parser.
*/
private static class GordianHQCEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianHQCEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianHQCSpec mySpec : GordianHQCSpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianHQCEncodedParser(GordianKeyPairSpecBuilder.hqc(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* BIKE Encoded parser.
*/
private static class GordianBIKEEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianBIKEEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianBIKESpec mySpec : GordianBIKESpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianBIKEEncodedParser(GordianKeyPairSpecBuilder.bike(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* NTRU Encoded parser.
*/
private static class GordianNTRUEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianNTRUEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianNTRUSpec mySpec : GordianNTRUSpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianNTRUEncodedParser(GordianKeyPairSpecBuilder.ntru(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* NTRUPrime Encoded parser.
*/
private static class GordianNTRUPrimeEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianNTRUPrimeEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianNTRUPrimeParams myParams : GordianNTRUPrimeParams.values()) {
pIdManager.registerParser(myParams.getNTRULIdentifier(),
new GordianNTRUPrimeEncodedParser(GordianKeyPairSpecBuilder.ntruprime(new GordianNTRUPrimeSpec(GordianNTRUPrimeType.NTRUL, myParams))));
pIdManager.registerParser(myParams.getSNTRUIdentifier(),
new GordianNTRUPrimeEncodedParser(GordianKeyPairSpecBuilder.ntruprime(new GordianNTRUPrimeSpec(GordianNTRUPrimeType.SNTRU, myParams))));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* Falcon Encoded parser.
*/
private static class GordianFalconEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianFalconEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianFalconSpec mySpec : GordianFalconSpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianFalconEncodedParser(GordianKeyPairSpecBuilder.falcon(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* Mayo Encoded parser.
*/
private static class GordianMayoEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianMayoEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianMayoSpec mySpec : GordianMayoSpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianMayoEncodedParser(GordianKeyPairSpecBuilder.mayo(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* Snova Encoded parser.
*/
private static class GordianSnovaEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianSnovaEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianSnovaSpec mySpec : GordianSnovaSpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianSnovaEncodedParser(GordianKeyPairSpecBuilder.snova(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* Picnic Encoded parser.
*/
private static class GordianPicnicEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianPicnicEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
for (GordianPicnicSpec mySpec : GordianPicnicSpec.values()) {
pIdManager.registerParser(mySpec.getIdentifier(), new GordianPicnicEncodedParser(GordianKeyPairSpecBuilder.picnic(mySpec)));
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* NewHope Encoded parser.
*/
private static final class GordianNewHopeEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(PQCObjectIdentifiers.newHope, new GordianNewHopeEncodedParser());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) {
return GordianKeyPairSpecBuilder.newHope();
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) {
return GordianKeyPairSpecBuilder.newHope();
}
}
/**
* XMSS Encoded parser.
*/
private static final class GordianXMSSEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(PQCObjectIdentifiers.xmss, new GordianXMSSEncodedParser());
pIdManager.registerParser(IsaraObjectIdentifiers.id_alg_xmss, new GordianXMSSEncodedParser());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
final AlgorithmIdentifier myId = pInfo.getAlgorithm();
final XMSSKeyParams myParms = XMSSKeyParams.getInstance(myId.getParameters());
if (myParms != null) {
return determineKeyPairSpec(myParms);
}
/* Protect against exceptions */
try {
final byte[] keyEnc = Objects.requireNonNull(ASN1OctetString.getInstance(pInfo.parsePublicKey())).getOctets();
final int myOID = Pack.bigEndianToInt(keyEnc, 0);
final XMSSParameters myParams = XMSSParameters.lookupByOID(myOID);
return GordianKeyPairSpecBuilder.xmss(determineKeyType(myParams.getTreeDigestOID()),
determineHeight(myParams.getHeight()));
} catch (IOException e) {
throw new GordianIOException("Failed to resolve key", e);
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
final AlgorithmIdentifier myId = pInfo.getPrivateKeyAlgorithm();
final XMSSKeyParams myParms = XMSSKeyParams.getInstance(myId.getParameters());
return determineKeyPairSpec(myParms);
}
/**
* Obtain keySpec from Parameters.
*
* @param pParms the parameters
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final XMSSKeyParams pParms) throws GordianException {
final ASN1ObjectIdentifier myDigest = pParms.getTreeDigest().getAlgorithm();
final GordianXMSSHeight myHeight = determineHeight(pParms.getHeight());
return GordianKeyPairSpecBuilder.xmss(determineKeyType(myDigest), myHeight);
}
/**
* Obtain keyType from digest.
*
* @param pDigest the treeDigest
* @return the keyType
* @throws GordianException on error
*/
static GordianXMSSDigestType determineKeyType(final ASN1ObjectIdentifier pDigest) throws GordianException {
if (pDigest.equals(NISTObjectIdentifiers.id_sha256)) {
return GordianXMSSDigestType.SHA256;
}
if (pDigest.equals(NISTObjectIdentifiers.id_sha512)) {
return GordianXMSSDigestType.SHA512;
}
if (pDigest.equals(NISTObjectIdentifiers.id_shake128)) {
return GordianXMSSDigestType.SHAKE128;
}
if (pDigest.equals(NISTObjectIdentifiers.id_shake256)) {
return GordianXMSSDigestType.SHAKE256;
}
/* Tree Digest is not supported */
throw new GordianDataException(ERROR_TREEDIGEST + pDigest);
}
/**
* Obtain height.
*
* @param pHeight the height
* @return the xmssHeight
* @throws GordianException on error
*/
static GordianXMSSHeight determineHeight(final int pHeight) throws GordianException {
/* Loo through the heights */
for (GordianXMSSHeight myHeight : GordianXMSSHeight.values()) {
if (myHeight.getHeight() == pHeight) {
return myHeight;
}
}
/* Height is not supported */
throw new GordianDataException("Inavlid height: " + pHeight);
}
}
/**
* XMSSMT Encoded parser.
*/
private static final class GordianXMSSMTEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(PQCObjectIdentifiers.xmss_mt, new GordianXMSSMTEncodedParser());
pIdManager.registerParser(IsaraObjectIdentifiers.id_alg_xmssmt, new GordianXMSSMTEncodedParser());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
final AlgorithmIdentifier myId = pInfo.getAlgorithm();
final XMSSMTKeyParams myParms = XMSSMTKeyParams.getInstance(myId.getParameters());
if (myParms != null) {
return determineKeyPairSpec(myParms);
}
/* Protect against exceptions */
try {
final byte[] keyEnc = Objects.requireNonNull(ASN1OctetString.getInstance(pInfo.parsePublicKey())).getOctets();
final int myOID = Pack.bigEndianToInt(keyEnc, 0);
final XMSSMTParameters myParams = XMSSMTParameters.lookupByOID(myOID);
return GordianKeyPairSpecBuilder.xmssmt(GordianXMSSEncodedParser.determineKeyType(myParams.getTreeDigestOID()),
GordianXMSSEncodedParser.determineHeight(myParams.getHeight()), determineLayers(myParams.getLayers()));
} catch (IOException e) {
throw new GordianIOException("Failed to resolve key", e);
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
final AlgorithmIdentifier myId = pInfo.getPrivateKeyAlgorithm();
final XMSSMTKeyParams myParms = XMSSMTKeyParams.getInstance(myId.getParameters());
return determineKeyPairSpec(myParms);
}
/**
* Obtain keySpec from Parameters.
*
* @param pParms the parameters
* @return the keySpec
* @throws GordianException on error
*/
private static GordianKeyPairSpec determineKeyPairSpec(final XMSSMTKeyParams pParms) throws GordianException {
final ASN1ObjectIdentifier myDigest = pParms.getTreeDigest().getAlgorithm();
final GordianXMSSHeight myHeight = GordianXMSSEncodedParser.determineHeight(pParms.getHeight());
final GordianXMSSMTLayers myLayers = determineLayers(pParms.getLayers());
return GordianKeyPairSpecBuilder.xmssmt(GordianXMSSEncodedParser.determineKeyType(myDigest), myHeight, myLayers);
}
/**
* Obtain layers.
*
* @param pLayers the layers
* @return the xmssMTLayers
* @throws GordianException on error
*/
static GordianXMSSMTLayers determineLayers(final int pLayers) throws GordianException {
/* Loo through the heights */
for (GordianXMSSMTLayers myLayers : GordianXMSSMTLayers.values()) {
if (myLayers.getLayers() == pLayers) {
return myLayers;
}
}
/* Layers is not supported */
throw new GordianDataException("Invalid layers: " + pLayers);
}
}
/**
* Edwards Encoded parser.
*/
private static class GordianEdwardsEncodedParser implements GordianEncodedParser {
/**
* AsymKeySpec.
*/
private final GordianKeyPairSpec theKeySpec;
/**
* Constructor.
*
* @param pKeySpec the keySpec
*/
GordianEdwardsEncodedParser(final GordianKeyPairSpec pKeySpec) {
theKeySpec = pKeySpec;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(EdECObjectIdentifiers.id_X25519, new GordianEdwardsEncodedParser(GordianKeyPairSpecBuilder.x25519()));
pIdManager.registerParser(EdECObjectIdentifiers.id_X448, new GordianEdwardsEncodedParser(GordianKeyPairSpecBuilder.x448()));
pIdManager.registerParser(EdECObjectIdentifiers.id_Ed25519, new GordianEdwardsEncodedParser(GordianKeyPairSpecBuilder.ed25519()));
pIdManager.registerParser(EdECObjectIdentifiers.id_Ed448, new GordianEdwardsEncodedParser(GordianKeyPairSpecBuilder.ed448()));
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
return theKeySpec;
}
}
/**
* LMS Encoded parser.
*/
private static final class GordianLMSEncodedParser implements GordianEncodedParser {
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(PKCSObjectIdentifiers.id_alg_hss_lms_hashsig, new GordianLMSEncodedParser());
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
/* Protect against exceptions */
try {
/* Parse public key */
final LMSKeyParameters myParms = (LMSKeyParameters) PublicKeyFactory.createKey(pInfo);
if (myParms instanceof HSSPublicKeyParameters myPublic) {
final int myDepth = myPublic.getL();
final LMSPublicKeyParameters myLMSPublicKey = myPublic.getLMSPublicKey();
final GordianLMSKeySpec myKeySpec = determineKeyPairSpec(myLMSPublicKey);
return GordianKeyPairSpecBuilder.hss(myKeySpec, myDepth);
} else {
final LMSPublicKeyParameters myPublic = (LMSPublicKeyParameters) myParms;
final GordianLMSKeySpec myKeySpec = determineKeyPairSpec(myPublic);
return GordianKeyPairSpecBuilder.lms(myKeySpec);
}
/* Handle exceptions */
} catch (IOException e) {
throw new GordianIOException(ERROR_PARSE, e);
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
/* Protect against exceptions */
try {
/* Parse public key */
final LMSKeyParameters myParms = (LMSKeyParameters) PrivateKeyFactory.createKey(pInfo);
if (myParms instanceof HSSPrivateKeyParameters) {
final HSSPrivateKeyParameters myPrivate = (HSSPrivateKeyParameters) PrivateKeyFactory.createKey(pInfo);
final int myDepth = myPrivate.getL();
final LMSPublicKeyParameters myLMSPublicKey = myPrivate.getPublicKey().getLMSPublicKey();
final GordianLMSKeySpec myKeySpec = determineKeyPairSpec(myLMSPublicKey);
return GordianKeyPairSpecBuilder.hss(myKeySpec, myDepth);
} else {
final LMSPrivateKeyParameters myPrivate = (LMSPrivateKeyParameters) PrivateKeyFactory.createKey(pInfo);
return GordianKeyPairSpecBuilder.lms(GordianLMSKeySpec.determineKeySpec(myPrivate.getSigParameters(), myPrivate.getOtsParameters()));
}
/* Handle exceptions */
} catch (IOException e) {
throw new GordianIOException(ERROR_PARSE, e);
}
}
/**
* Obtain keySpec from public key.
*
* @param pPublic the publicKeyParams
* @return the LMSKeySpec
*/
static GordianLMSKeySpec determineKeyPairSpec(final LMSPublicKeyParameters pPublic) {
return GordianLMSKeySpec.determineKeySpec(pPublic.getSigParameters(), pPublic.getOtsParameters());
}
}
/**
* Composite Encoded parser.
*/
private static class GordianCompositeEncodedParser implements GordianEncodedParser {
/**
* The KeyPairFactory.
*/
private final GordianKeyPairAlgId theIdManager;
/**
* Constructor.
*
* @param pIdManager the idManager
*/
GordianCompositeEncodedParser(final GordianKeyPairAlgId pIdManager) {
theIdManager = pIdManager;
}
/**
* Registrar.
*
* @param pIdManager the idManager
*/
static void register(final GordianKeyPairAlgId pIdManager) {
pIdManager.registerParser(MiscObjectIdentifiers.id_alg_composite, new GordianCompositeEncodedParser(pIdManager));
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final SubjectPublicKeyInfo pInfo) throws GordianException {
/* Protect against exceptions */
try {
final ASN1Sequence myKeys = ASN1Sequence.getInstance(pInfo.getPublicKeyData().getBytes());
final List<GordianKeyPairSpec> mySpecs = new ArrayList<>();
/* Build the list from the keys sequence */
final Enumeration<?> en = myKeys.getObjects();
while (en.hasMoreElements()) {
final SubjectPublicKeyInfo myPKInfo = SubjectPublicKeyInfo.getInstance(en.nextElement());
mySpecs.add(theIdManager.determineKeyPairSpec(new X509EncodedKeySpec(myPKInfo.getEncoded())));
}
return GordianKeyPairSpecBuilder.composite(mySpecs);
/* Handle exceptions */
} catch (IOException e) {
throw new GordianIOException(ERROR_PARSE, e);
}
}
@Override
public GordianKeyPairSpec determineKeyPairSpec(final PrivateKeyInfo pInfo) throws GordianException {
/* Protect against exceptions */
try {
final ASN1Sequence myKeys = ASN1Sequence.getInstance(pInfo.getPrivateKey().getOctets());
final List<GordianKeyPairSpec> mySpecs = new ArrayList<>();
/* Build the list from the keys sequence */
final Enumeration<?> en = myKeys.getObjects();
while (en.hasMoreElements()) {
final PrivateKeyInfo myPKInfo = PrivateKeyInfo.getInstance(en.nextElement());
mySpecs.add(theIdManager.determineKeyPairSpec(new PKCS8EncodedKeySpec(myPKInfo.getEncoded())));
}
return GordianKeyPairSpecBuilder.composite(mySpecs);
/* Handle exceptions */
} catch (IOException e) {
throw new GordianIOException(ERROR_PARSE, e);
}
}
}
}