org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider.java Source code

Java tutorial

Introduction

Here is the source code for org.bouncycastle.pqc.jcajce.provider.BouncyCastlePQCProvider.java

Source

package org.bouncycastle.pqc.jcajce.provider;

import java.io.IOException;
import java.security.AccessController;
import java.security.PrivateKey;
import java.security.PrivilegedAction;
import java.security.Provider;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;

public class BouncyCastlePQCProvider extends Provider implements ConfigurableProvider {
    private static String info = "BouncyCastle Post-Quantum Security Provider v1.64";

    public static String PROVIDER_NAME = "BCPQC";

    public static final ProviderConfiguration CONFIGURATION = null;

    private static final Map keyInfoConverters = new HashMap();

    /*
    * Configurable symmetric ciphers
    */
    private static final String ALGORITHM_PACKAGE = "org.bouncycastle.pqc.jcajce.provider.";
    private static final String[] ALGORITHMS = { "Rainbow", "McEliece", "SPHINCS", "NH", "XMSS", "QTESLA" };

    /**
     * Construct a new provider.  This should only be required when
     * using runtime registration of the provider using the
     * <code>Security.addProvider()</code> mechanism.
     */
    public BouncyCastlePQCProvider() {
        super(PROVIDER_NAME, 1.64, info);

        AccessController.doPrivileged(new PrivilegedAction() {
            public Object run() {
                setup();
                return null;
            }
        });
    }

    private void setup() {
        loadAlgorithms(ALGORITHM_PACKAGE, ALGORITHMS);
    }

    private void loadAlgorithms(String packageName, String[] names) {
        for (int i = 0; i != names.length; i++) {
            Class clazz = loadClass(BouncyCastlePQCProvider.class, packageName + names[i] + "$Mappings");

            if (clazz != null) {
                try {
                    ((AlgorithmProvider) clazz.newInstance()).configure(this);
                } catch (Exception e) { // this should never ever happen!!
                    throw new InternalError(
                            "cannot create instance of " + packageName + names[i] + "$Mappings : " + e);
                }
            }
        }
    }

    public void setParameter(String parameterName, Object parameter) {
        synchronized (CONFIGURATION) {
            //((BouncyCastleProviderConfiguration)CONFIGURATION).setParameter(parameterName, parameter);
        }
    }

    public boolean hasAlgorithm(String type, String name) {
        return containsKey(type + "." + name) || containsKey("Alg.Alias." + type + "." + name);
    }

    public void addAlgorithm(String key, String value) {
        if (containsKey(key)) {
            throw new IllegalStateException("duplicate provider key (" + key + ") found");
        }

        put(key, value);
    }

    public void addAlgorithm(String type, ASN1ObjectIdentifier oid, String className) {
        if (!containsKey(type + "." + className)) {
            throw new IllegalStateException("primary key (" + type + "." + className + ") not found");
        }

        addAlgorithm(type + "." + oid, className);
        addAlgorithm(type + ".OID." + oid, className);
    }

    public void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter) {
        synchronized (keyInfoConverters) {
            keyInfoConverters.put(oid, keyInfoConverter);
        }
    }

    public void addAttributes(String key, Map<String, String> attributeMap) {
        for (Iterator it = attributeMap.keySet().iterator(); it.hasNext();) {
            String attributeName = (String) it.next();
            String attributeKey = key + " " + attributeName;
            if (containsKey(attributeKey)) {
                throw new IllegalStateException("duplicate provider attribute key (" + attributeKey + ") found");
            }

            put(attributeKey, attributeMap.get(attributeName));
        }
    }

    private static AsymmetricKeyInfoConverter getAsymmetricKeyInfoConverter(ASN1ObjectIdentifier algorithm) {
        synchronized (keyInfoConverters) {
            return (AsymmetricKeyInfoConverter) keyInfoConverters.get(algorithm);
        }
    }

    public static PublicKey getPublicKey(SubjectPublicKeyInfo publicKeyInfo) throws IOException {
        AsymmetricKeyInfoConverter converter = getAsymmetricKeyInfoConverter(
                publicKeyInfo.getAlgorithm().getAlgorithm());

        if (converter == null) {
            return null;
        }

        return converter.generatePublic(publicKeyInfo);
    }

    public static PrivateKey getPrivateKey(PrivateKeyInfo privateKeyInfo) throws IOException {
        AsymmetricKeyInfoConverter converter = getAsymmetricKeyInfoConverter(
                privateKeyInfo.getPrivateKeyAlgorithm().getAlgorithm());

        if (converter == null) {
            return null;
        }

        return converter.generatePrivate(privateKeyInfo);
    }

    static Class loadClass(Class sourceClass, final String className) {
        try {
            ClassLoader loader = sourceClass.getClassLoader();
            if (loader != null) {
                return loader.loadClass(className);
            } else {
                return (Class) AccessController.doPrivileged(new PrivilegedAction() {
                    public Object run() {
                        try {
                            return Class.forName(className);
                        } catch (Exception e) {
                            // ignore - maybe log?
                        }

                        return null;
                    }
                });
            }
        } catch (ClassNotFoundException e) {
            // ignore - maybe log?
        }

        return null;
    }
}