package net.i2p.crypto.provider; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.Provider; import java.security.Security; /** * @since 0.9.15 */ public final class I2PProvider extends Provider { public static final String PROVIDER_NAME = "I2P"; private static final String INFO = "I2P Security Provider v0.1, implementing" + "several algorithms used by I2P."; private static boolean _installed; /** * Construct a new provider. This should only be required when * using runtime registration of the provider using the * <code>Security.addProvider()</code> mechanism. */ public I2PProvider() { super(PROVIDER_NAME, 0.1, INFO); AccessController.doPrivileged(new PrivilegedAction<Void>() { @Override public Void run() { setup(); return null; } }); } private void setup() { // TODO: Implement SPIs for existing code // However - // quote // http://docs.oracle.com/javase/7/docs/technotes/guides/security/crypto/HowToImplAProvider.html // // If your provider is supplying encryption algorithms through the // Cipher, KeyAgreement, KeyGenerator, Mac, or SecretKeyFactory classes, // you will need to sign your JAR file so that the JCA can authenticate the code at runtime. // If you are NOT providing an implementation of this type you can skip this step. // //put("Cipher.AES", "net.i2p.crypto.provider.CipherSpi$aesCBC"); //put("Cipher.ElGamal", "net.i2p.crypto.provider.CipherSpi$elGamal"); //put("Mac.HmacMD5-I2P", "net.i2p.crypto.provider.MacSpi"); put("MessageDigest.SHA-1", "net.i2p.crypto.SHA1"); //put("Signature.SHA1withDSA", "net.i2p.crypto.provider.SignatureSpi"); // EdDSA // Key OID: 1.3.101.100; Sig OID: 1.3.101.101 put("KeyFactory.EdDSA", "net.i2p.crypto.eddsa.KeyFactory"); put("KeyPairGenerator.EdDSA", "net.i2p.crypto.eddsa.KeyPairGenerator"); put("Signature.SHA512withEdDSA", "net.i2p.crypto.eddsa.EdDSAEngine"); // Didn't find much documentation on these at all, // see http://docs.oracle.com/javase/7/docs/technotes/guides/security/crypto/HowToImplAProvider.html // section "Mapping from OID to name" // without these, Certificate.verify() fails put("Alg.Alias.KeyFactory.1.3.101.100", "EdDSA"); put("Alg.Alias.KeyFactory.OID.1.3.101.100", "EdDSA"); // Without these, keytool fails with: // keytool error: java.security.NoSuchAlgorithmException: unrecognized algorithm name: SHA512withEdDSA put("Alg.Alias.KeyPairGenerator.1.3.101.100", "EdDSA"); put("Alg.Alias.KeyPairGenerator.OID.1.3.101.100", "EdDSA"); // with this setting, keytool keygen doesn't work // java.security.cert.CertificateException: Signature algorithm mismatch // it must match the key setting (1.3.101.100) to work // but this works fine with programmatic cert generation put("Alg.Alias.Signature.1.3.101.101", "SHA512withEdDSA"); put("Alg.Alias.Signature.OID.1.3.101.101", "SHA512withEdDSA"); // TODO Ed25519ph // OID: 1.3.101.101 // ElGamal // OID: 1.3.14.7.2.1.1 put("KeyFactory.DH", "net.i2p.crypto.elgamal.KeyFactory"); put("KeyFactory.DiffieHellman", "net.i2p.crypto.elgamal.KeyFactory"); put("KeyFactory.ElGamal", "net.i2p.crypto.elgamal.KeyFactory"); put("KeyPairGenerator.DH", "net.i2p.crypto.elgamal.KeyPairGenerator"); put("KeyPairGenerator.DiffieHellman", "net.i2p.crypto.elgamal.KeyPairGenerator"); put("KeyPairGenerator.ElGamal", "net.i2p.crypto.elgamal.KeyPairGenerator"); put("Signature.SHA256withElGamal", "net.i2p.crypto.elgamal.ElGamalSigEngine"); put("Alg.Alias.KeyFactory.1.3.14.7.2.1.1", "ElGamal"); put("Alg.Alias.KeyFactory.OID.1.3.14.7.2.1.1", "ElGamal"); put("Alg.Alias.KeyPairGenerator.1.3.14.7.2.1.1", "ElGamal"); put("Alg.Alias.KeyPairGenerator.OID.1.3.14.7.2.1.1", "ElGamal"); put("Alg.Alias.Signature.1.3.14.7.2.1.1", "SHA256withElGamal"); put("Alg.Alias.Signature.OID.1.3.14.7.2.1.1", "SHA256withElGamal"); } /** * Install the I2PProvider. * Harmless to call multiple times. * @since 0.9.25 */ public static void addProvider() { synchronized(I2PProvider.class) { if (!_installed) { try { Provider us = new I2PProvider(); // put ours ahead of BC, if installed, because our ElGamal // implementation may not be fully compatible with BC Provider[] provs = Security.getProviders(); for (int i = 0; i < provs.length; i++) { if (provs[i].getName().equals("BC")) { Security.insertProviderAt(us, i); _installed = true; return; } } Security.addProvider(us); _installed = true; } catch (SecurityException se) { System.out.println("WARN: Could not install I2P provider: " + se); } } } } }