package org.bouncycastle.pqc.crypto.util;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

import org.bouncycastle.asn1.ASN1InputStream;
import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.ASN1Primitive;
import org.bouncycastle.asn1.x509.AlgorithmIdentifier;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.pqc.asn1.PQCObjectIdentifiers;
import org.bouncycastle.pqc.asn1.SPHINCS256KeyParams;
import org.bouncycastle.pqc.asn1.XMSSKeyParams;
import org.bouncycastle.pqc.asn1.XMSSMTKeyParams;
import org.bouncycastle.pqc.asn1.XMSSPublicKey;
import org.bouncycastle.pqc.crypto.newhope.NHPublicKeyParameters;
import org.bouncycastle.pqc.crypto.qtesla.QTESLAPublicKeyParameters;
import org.bouncycastle.pqc.crypto.sphincs.SPHINCSPublicKeyParameters;
import org.bouncycastle.pqc.crypto.xmss.XMSSMTParameters;
import org.bouncycastle.pqc.crypto.xmss.XMSSMTPublicKeyParameters;
import org.bouncycastle.pqc.crypto.xmss.XMSSParameters;
import org.bouncycastle.pqc.crypto.xmss.XMSSPublicKeyParameters;

Factory to create asymmetric public key parameters for asymmetric ciphers from range of ASN.1 encoded SubjectPublicKeyInfo objects.
/** * Factory to create asymmetric public key parameters for asymmetric ciphers from range of * ASN.1 encoded SubjectPublicKeyInfo objects. */
public class PublicKeyFactory { private static Map converters = new HashMap(); static { converters.put(PQCObjectIdentifiers.qTESLA_I, new QTeslaConverter()); converters.put(PQCObjectIdentifiers.qTESLA_III_size, new QTeslaConverter()); converters.put(PQCObjectIdentifiers.qTESLA_III_speed, new QTeslaConverter()); converters.put(PQCObjectIdentifiers.qTESLA_p_I, new QTeslaConverter()); converters.put(PQCObjectIdentifiers.qTESLA_p_III, new QTeslaConverter()); converters.put(PQCObjectIdentifiers.sphincs256, new SPHINCSConverter()); converters.put(PQCObjectIdentifiers.newHope, new NHConverter()); converters.put(PQCObjectIdentifiers.xmss, new XMSSConverter()); converters.put(PQCObjectIdentifiers.xmss_mt, new XMSSMTConverter()); }
Create a public key from a SubjectPublicKeyInfo encoding
Params:
  • keyInfoData – the SubjectPublicKeyInfo encoding
Throws:
Returns:the appropriate key parameter
/** * Create a public key from a SubjectPublicKeyInfo encoding * * @param keyInfoData the SubjectPublicKeyInfo encoding * @return the appropriate key parameter * @throws IOException on an error decoding the key */
public static AsymmetricKeyParameter createKey(byte[] keyInfoData) throws IOException { return createKey(SubjectPublicKeyInfo.getInstance(ASN1Primitive.fromByteArray(keyInfoData))); }
Create a public key from a SubjectPublicKeyInfo encoding read from a stream
Params:
  • inStr – the stream to read the SubjectPublicKeyInfo encoding from
Throws:
Returns:the appropriate key parameter
/** * Create a public key from a SubjectPublicKeyInfo encoding read from a stream * * @param inStr the stream to read the SubjectPublicKeyInfo encoding from * @return the appropriate key parameter * @throws IOException on an error decoding the key */
public static AsymmetricKeyParameter createKey(InputStream inStr) throws IOException { return createKey(SubjectPublicKeyInfo.getInstance(new ASN1InputStream(inStr).readObject())); }
Create a public key from the passed in SubjectPublicKeyInfo
Params:
  • keyInfo – the SubjectPublicKeyInfo containing the key data
Throws:
Returns:the appropriate key parameter
/** * Create a public key from the passed in SubjectPublicKeyInfo * * @param keyInfo the SubjectPublicKeyInfo containing the key data * @return the appropriate key parameter * @throws IOException on an error decoding the key */
public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo) throws IOException { return createKey(keyInfo, null); }
Create a public key from the passed in SubjectPublicKeyInfo
Params:
  • keyInfo – the SubjectPublicKeyInfo containing the key data
  • defaultParams – default parameters that might be needed.
Throws:
Returns:the appropriate key parameter
/** * Create a public key from the passed in SubjectPublicKeyInfo * * @param keyInfo the SubjectPublicKeyInfo containing the key data * @param defaultParams default parameters that might be needed. * @return the appropriate key parameter * @throws IOException on an error decoding the key */
public static AsymmetricKeyParameter createKey(SubjectPublicKeyInfo keyInfo, Object defaultParams) throws IOException { AlgorithmIdentifier algId = keyInfo.getAlgorithm(); SubjectPublicKeyInfoConverter converter = (SubjectPublicKeyInfoConverter)converters.get(algId.getAlgorithm()); if (converter != null) { return converter.getPublicKeyParameters(keyInfo, defaultParams); } else { throw new IOException("algorithm identifier in public key not recognised: " + algId.getAlgorithm()); } } private static abstract class SubjectPublicKeyInfoConverter { abstract AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) throws IOException; } private static class QTeslaConverter extends SubjectPublicKeyInfoConverter { AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) throws IOException { return new QTESLAPublicKeyParameters(Utils.qTeslaLookupSecurityCategory(keyInfo.getAlgorithm()), keyInfo.getPublicKeyData().getOctets()); } } private static class SPHINCSConverter extends SubjectPublicKeyInfoConverter { AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) throws IOException { return new SPHINCSPublicKeyParameters(keyInfo.getPublicKeyData().getBytes(), Utils.sphincs256LookupTreeAlgName(SPHINCS256KeyParams.getInstance(keyInfo.getAlgorithm().getParameters()))); } } private static class NHConverter extends SubjectPublicKeyInfoConverter { AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) throws IOException { return new NHPublicKeyParameters(keyInfo.getPublicKeyData().getBytes()); } } private static class XMSSConverter extends SubjectPublicKeyInfoConverter { AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) throws IOException { XMSSKeyParams keyParams = XMSSKeyParams.getInstance(keyInfo.getAlgorithm().getParameters()); ASN1ObjectIdentifier treeDigest = keyParams.getTreeDigest().getAlgorithm(); XMSSPublicKey xmssPublicKey = XMSSPublicKey.getInstance(keyInfo.parsePublicKey()); return new XMSSPublicKeyParameters .Builder(new XMSSParameters(keyParams.getHeight(), Utils.getDigest(treeDigest))) .withPublicSeed(xmssPublicKey.getPublicSeed()) .withRoot(xmssPublicKey.getRoot()).build(); } } private static class XMSSMTConverter extends SubjectPublicKeyInfoConverter { AsymmetricKeyParameter getPublicKeyParameters(SubjectPublicKeyInfo keyInfo, Object defaultParams) throws IOException { XMSSMTKeyParams keyParams = XMSSMTKeyParams.getInstance(keyInfo.getAlgorithm().getParameters()); ASN1ObjectIdentifier treeDigest = keyParams.getTreeDigest().getAlgorithm(); XMSSPublicKey xmssMtPublicKey = XMSSPublicKey.getInstance(keyInfo.parsePublicKey()); return new XMSSMTPublicKeyParameters .Builder(new XMSSMTParameters(keyParams.getHeight(), keyParams.getLayers(), Utils.getDigest(treeDigest))) .withPublicSeed(xmssMtPublicKey.getPublicSeed()) .withRoot(xmssMtPublicKey.getRoot()).build(); } } }