All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.bouncycastle.jce.provider.BouncyCastleProvider Maven / Gradle / Ivy

Go to download

The Long Term Stable (LTS) Bouncy Castle Crypto package is a Java implementation of cryptographic algorithms. This jar contains the JCA/JCE provider and low-level API for the BC LTS version 2.73.6 for Java 8 and later.

The newest version!
package org.bouncycastle.jce.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 java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.bouncycastle.asn1.ASN1ObjectIdentifier;
import org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
import org.bouncycastle.crypto.CryptoServiceConstraintsException;
import org.bouncycastle.crypto.CryptoServiceProperties;
import org.bouncycastle.crypto.CryptoServicePurpose;
import org.bouncycastle.crypto.CryptoServicesRegistrar;
import org.bouncycastle.jcajce.provider.config.ConfigurableProvider;
import org.bouncycastle.jcajce.provider.config.ProviderConfiguration;
import org.bouncycastle.jcajce.provider.symmetric.util.ClassUtil;
import org.bouncycastle.jcajce.provider.util.AlgorithmProvider;
import org.bouncycastle.jcajce.provider.util.AsymmetricKeyInfoConverter;
import org.bouncycastle.util.Strings;

/**
 * To add the provider at runtime use:
 * 
 * import java.security.Security;
 * import org.bouncycastle.jce.provider.BouncyCastleProvider;
 *
 * Security.addProvider(new BouncyCastleProvider());
 * 
* The provider can also be configured as part of your environment via * static registration by adding an entry to the java.security properties * file (found in $JAVA_HOME/jre/lib/security/java.security, where * $JAVA_HOME is the location of your JDK/JRE distribution). You'll find * detailed instructions in the file, but basically it comes down to adding * a line: *
 * 
 *    security.provider.<n>=org.bouncycastle.jce.provider.BouncyCastleProvider
 * 
 * 
* Where <n> is the preference you want the provider at (1 being the * most preferred). *

Note: JCE algorithm names should be upper-case only so the case-insensitive * test for getInstance works. */ public final class BouncyCastleProvider extends Provider implements ConfigurableProvider { private static final Logger LOG = Logger.getLogger(BouncyCastleProvider.class.getName()); private static String info = CryptoServicesRegistrar.getInfo().replace("APIs", "Security Provider"); public static final String PROVIDER_NAME = "BC"; public static final ProviderConfiguration CONFIGURATION = new BouncyCastleProviderConfiguration(); private static final Map keyInfoConverters = new HashMap(); private static final Class revChkClass = ClassUtil.loadClass(BouncyCastleProvider.class, "java.security.cert.PKIXRevocationChecker"); /* * Configurable symmetric ciphers */ private static final String SYMMETRIC_PACKAGE = "org.bouncycastle.jcajce.provider.symmetric."; private static final String[] SYMMETRIC_GENERIC = { "PBEPBKDF1", "PBEPBKDF2", "PBEPKCS12", "TLSKDF", "SCRYPT" }; private static final String[] SYMMETRIC_MACS = { "SipHash", "SipHash128", "Poly1305" }; private static final CryptoServiceProperties[] SYMMETRIC_CIPHERS = { // TODO: these numbers need a bit more work, we cap at 256 bits. service("AES", 256), service("ARC4", 20), service("ARIA", 256), service("Blowfish", 128), service("Camellia", 256), service("CAST5", 128), service("CAST6", 256), service("ChaCha", 128), service("DES", 56), service("DESede", 112), service("GOST28147", 128), service("Grainv1", 128), service("Grain128", 128), service("HC128", 128), service("HC256", 256), service("IDEA", 128), service("Noekeon", 128), service("RC2", 128), service("RC5", 128), service("RC6", 256), service("Rijndael", 256), service("Salsa20", 128), service("SEED", 128), service("Serpent", 256), service("Shacal2", 128), service("Skipjack", 80), service("SM4", 128), service("TEA", 128), service("Twofish", 256), service("Threefish", 128), service("VMPC", 128), service("VMPCKSA3", 128), service("XTEA", 128), service("XSalsa20", 128), service("OpenSSLPBKDF", 128), service("DSTU7624", 256), service("GOST3412_2015", 256), service("Zuc", 128) }; /* * Configurable asymmetric ciphers */ private static final String ASYMMETRIC_PACKAGE = "org.bouncycastle.jcajce.provider.asymmetric."; // this one is required for GNU class path - it needs to be loaded first as the // later ones configure it. private static final String[] ASYMMETRIC_GENERIC = { "X509", "IES", "COMPOSITE", "EXTERNAL" }; private static final String[] ASYMMETRIC_CIPHERS = { "DSA", "DH", "EC", "RSA", "GOST", "ECGOST", "ElGamal", "DSTU4145", "GM", "EdEC", "LMS" }; /* * Configurable digests */ private static final String DIGEST_PACKAGE = "org.bouncycastle.jcajce.provider.digest."; private static final String[] DIGESTS = { "GOST3411", "Keccak", "MD2", "MD4", "MD5", "SHA1", "RIPEMD128", "RIPEMD160", "RIPEMD256", "RIPEMD320", "SHA224", "SHA256", "SHA384", "SHA512", "SHA3", "Skein", "SM3", "Tiger", "Whirlpool", "Blake2b", "Blake2s", "DSTU7564", "Haraka", "Blake3" }; /* * Configurable keystores */ private static final String KEYSTORE_PACKAGE = "org.bouncycastle.jcajce.provider.keystore."; private static final String[] KEYSTORES = { "BC", "BCFKS", "PKCS12" }; /* * Configurable secure random */ private static final String SECURE_RANDOM_PACKAGE = "org.bouncycastle.jcajce.provider.drbg."; private static final String[] SECURE_RANDOMS = { "DRBG" }; private Map serviceMap = new ConcurrentHashMap(); /** * Construct a new provider. This should only be required when * using runtime registration of the provider using the * Security.addProvider() mechanism. */ public BouncyCastleProvider() { super(PROVIDER_NAME, 2.7304, info); AccessController.doPrivileged(new PrivilegedAction() { public Object run() { setup(); return null; } }); } private void setup() { loadAlgorithms(DIGEST_PACKAGE, DIGESTS); loadAlgorithms(SYMMETRIC_PACKAGE, SYMMETRIC_GENERIC); loadAlgorithms(SYMMETRIC_PACKAGE, SYMMETRIC_MACS); loadAlgorithms(SYMMETRIC_PACKAGE, SYMMETRIC_CIPHERS); loadAlgorithms(ASYMMETRIC_PACKAGE, ASYMMETRIC_GENERIC); loadAlgorithms(ASYMMETRIC_PACKAGE, ASYMMETRIC_CIPHERS); loadAlgorithms(KEYSTORE_PACKAGE, KEYSTORES); loadAlgorithms(SECURE_RANDOM_PACKAGE, SECURE_RANDOMS); loadPQCKeys(); // so we can handle certificates containing them. // Certification Path API if (revChkClass != null) { put("CertPathValidator.RFC5280", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi_8"); put("CertPathBuilder.RFC5280", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi_8"); put("CertPathValidator.RFC3280", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi_8"); put("CertPathBuilder.RFC3280", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi_8"); put("CertPathValidator.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi_8"); put("CertPathBuilder.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi_8"); } else { put("CertPathValidator.RFC5280", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi"); put("CertPathBuilder.RFC5280", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi"); put("CertPathValidator.RFC3280", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi"); put("CertPathBuilder.RFC3280", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi"); put("CertPathValidator.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathValidatorSpi"); put("CertPathBuilder.PKIX", "org.bouncycastle.jce.provider.PKIXCertPathBuilderSpi"); } put("CertStore.Collection", "org.bouncycastle.jce.provider.CertStoreCollectionSpi"); put("CertStore.LDAP", "org.bouncycastle.jce.provider.X509LDAPCertStoreSpi"); put("CertStore.Multi", "org.bouncycastle.jce.provider.MultiCertStoreSpi"); put("Alg.Alias.CertStore.X509LDAP", "LDAP"); getService("SecureRandom", "DEFAULT"); // prime for new SecureRandom() on 1.8 JVMs. } public final Service getService(String type, String algorithm) { String upperCaseAlgName = Strings.toUpperCase(algorithm); final String key = type + "." + upperCaseAlgName; Service service = serviceMap.get(key); if (service == null) { synchronized (this) { if (!serviceMap.containsKey(key)) { service = AccessController.doPrivileged(new PrivilegedAction() { @Override public Service run() { Service service = BouncyCastleProvider.super.getService(type, algorithm); if (service == null) { return null; } serviceMap.put(key, service); // remove legacy entry and swap to service entry BouncyCastleProvider.super.remove(service.getType() + "." + service.getAlgorithm()); BouncyCastleProvider.super.putService(service); return service; } }); } else { service = serviceMap.get(key); } } } return service; } private void loadAlgorithms(String packageName, String[] names) { for (int i = 0; i != names.length; i++) { loadServiceClass(packageName, names[i]); } } private void loadAlgorithms(String packageName, CryptoServiceProperties[] services) { for (int i = 0; i != services.length; i++) { CryptoServiceProperties service = services[i]; try { CryptoServicesRegistrar.checkConstraints(service); loadServiceClass(packageName, service.getServiceName()); } catch (CryptoServiceConstraintsException e) { if (LOG.isLoggable(Level.FINE)) { LOG.fine("service for " + service.getServiceName() + " ignored due to constraints"); } } } } private void loadServiceClass(String packageName, String serviceName) { Class clazz = ClassUtil.loadClass(BouncyCastleProvider.class, packageName + serviceName + "$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 + serviceName + "$Mappings : " + e); } } } private void loadPQCKeys() { // none for now } 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 key, String value, Map attributes) { addAlgorithm(key, value); addAttributes(key, attributes); } public void addAlgorithm(String type, ASN1ObjectIdentifier oid, String className) { addAlgorithm(type + "." + oid, className); addAlgorithm(type + ".OID." + oid, className); } public void addAlgorithm(String type, ASN1ObjectIdentifier oid, String className, Map attributes) { addAlgorithm(type, oid, className); addAttributes(type + "." + oid, attributes); addAttributes(type + ".OID." + oid, attributes); } public void addKeyInfoConverter(ASN1ObjectIdentifier oid, AsymmetricKeyInfoConverter keyInfoConverter) { synchronized (keyInfoConverters) { keyInfoConverters.put(oid, keyInfoConverter); } } public AsymmetricKeyInfoConverter getKeyInfoConverter(ASN1ObjectIdentifier oid) { return (AsymmetricKeyInfoConverter)keyInfoConverters.get(oid); } public void addAttributes(String key, Map attributeMap) { put(key + " ImplementedIn", "Software"); 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); } private static CryptoServiceProperties service(String name, int bitsOfSecurity) { return new JcaCryptoService(name, bitsOfSecurity); } private static class JcaCryptoService implements CryptoServiceProperties { private final String name; private final int bitsOfSecurity; JcaCryptoService(String name, int bitsOfSecurity) { this.name = name; this.bitsOfSecurity = bitsOfSecurity; } public int bitsOfSecurity() { return bitsOfSecurity; } public String getServiceName() { return name; } public CryptoServicePurpose getPurpose() { return CryptoServicePurpose.ANY; } public Object getParams() { return null; } } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy