Package freenet.crypt

Source Code of freenet.crypt.JceLoader$BouncyCastleLoader

package freenet.crypt;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Constructor;
import java.security.Provider;
import java.security.Security;
import java.security.Signature;

import javax.crypto.KeyAgreement;

import freenet.support.Logger;
import freenet.support.io.Closer;

public class JceLoader {
  static public final Provider BouncyCastle;
  static public final Provider NSS; // optional, may be null
  static public final Provider SUN; // optional, may be null
  static public final Provider SunJCE; // optional, may be null
  static private boolean checkUse(String prop)
  {
    return checkUse(prop, "true");
  }
  static private boolean checkUse(String prop, String def)
  {
    return "true".equalsIgnoreCase(System.getProperty("freenet.jce."+prop, def));
  }
  static {
    Provider p;
    // NSS is preferred over BC, add it first
    p = null;
    if (checkUse("use.NSS","false")) {
      try {
        p = (new NSSLoader()).load(checkUse("prefer.NSS"));
      } catch(Throwable e) {
        // FIXME what about Windows/MacOSX/etc?
        final String msg = "Unable to load SunPKCS11-NSScrypto provider. This is NOT fatal error, Freenet will work, but some performance degradation possible. Consider installing libnss3 package.";
        Logger.warning(NSSLoader.class, msg, e);
      }
    }
    NSS = p;
    p = null;
    if (checkUse("use.BC.I.know.what.I.am.doing")) {
      try {
        p = (new BouncyCastleLoader()).load();
      } catch(Throwable e) {
        final String msg = "SERIOUS PROBLEM: Unable to load or use BouncyCastle provider.";
        System.err.println(msg);
        e.printStackTrace();
        Logger.error(JceLoader.class, msg, e);
      }
    }
    BouncyCastle = p;
    // optional
    SUN = checkUse("use.SUN") ? Security.getProvider("SUN") : null;
    SunJCE = checkUse("use.SunJCE") ? Security.getProvider("SunJCE") : null;
  }
  static private class BouncyCastleLoader {
    private BouncyCastleLoader() {}
    private Provider load() throws Throwable {
      Provider p = Security.getProvider("BC");
      if (p == null) {
        try {
          Class<?> c = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider");
          p = (Provider)c.newInstance();
          Security.addProvider(p);
        } catch(Throwable e) {
          throw e;
        }
        Logger.debug(BouncyCastleLoader.class, "Loaded BouncyCastle provider: " + p);
      } else {
        Logger.debug(BouncyCastleLoader.class, "Found BouncyCastle provider: " + p);
      }
      try {
        // We don't want totally unusable provider
        KeyAgreement.getInstance("ECDH", p);
        Signature.getInstance("SHA256withECDSA", p);
      } catch(Throwable e) {
        throw new Error("Cannot use required algorithm from BouncyCaste provider", e);
      }
      return p;
    }
  }
  static private class NSSLoader {
    private NSSLoader() {}
    private Provider load(boolean atfirst) throws Throwable {
      Provider nssProvider = null;
      for(Provider p: java.security.Security.getProviders()) {
        if (p.getName().matches("^SunPKCS11-(?i)NSS.*$")) {
          nssProvider = p;
          break;
        }
      }
      if(nssProvider == null) {
        File nssFile = File.createTempFile("nss",".cfg");
        nssFile.deleteOnExit();
        OutputStream os = null;
        try {
          // More robust than PrintWriter(file), which can hang on out of disk space.
          os = new FileOutputStream(nssFile);
          OutputStreamWriter osw = new OutputStreamWriter(os, "ISO-8859-1");
          BufferedWriter bw = new BufferedWriter(osw);
          bw.write("name=NSScrypto\n");
          bw.write("nssDbMode=noDb\n");
          bw.write("attributes=compatibility\n");
          bw.close();
          os = null;
        } finally {
          Closer.close(os);
        }
        Class<?> c = Class.forName("sun.security.pkcs11.SunPKCS11");
        Constructor<?> constructor = c.getConstructor(String.class);
        nssProvider = (Provider)constructor.newInstance(nssFile.getPath());
        if (atfirst)
          Security.insertProviderAt(nssProvider, 1);
        else
          Security.addProvider(nssProvider);
        Logger.debug(NSSLoader.class, "Loaded NSS provider " + nssProvider);
      } else {
        Logger.debug(NSSLoader.class, "Found NSS provider " + nssProvider);
      }
      return nssProvider;
    }
  }
  static public void main(String[] args) {
    dumpLoaded();
  }
 
  static public void dumpLoaded() {
    System.out.println("BouncyCastle: "+BouncyCastle);
    System.out.println("SunPKCS11-NSS: "+NSS);
    System.out.println("SUN: "+SUN);
    System.out.println("SunJCE: "+SunJCE);
  }
}
TOP

Related Classes of freenet.crypt.JceLoader$BouncyCastleLoader

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.