package uc.crypto;
import helpers.GH;
import java.io.File;
import java.io.FileInputStream;
import java.io.PrintStream;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.Date;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import logger.LoggerFactory;
import org.apache.log4j.Logger;
import uc.DCClient;
import uc.ICryptoManager;
import uc.Identity;
import uc.LanguageKeys;
import uc.PI;
public class CryptoManager implements ICryptoManager {
private static Logger logger = LoggerFactory.make();
private static final char[] PASS = new char[] {'1','2','3','4','5','6'};
private final DCClient dcc;
private final SSLContext tls;
private final boolean tlsInitialised;
private final HashValue fingerPrint;
private final Identity identity;
public CryptoManager(DCClient dcc,Identity identity) {
this.identity = identity;
this.dcc = dcc;
boolean[] bP = new boolean[]{false};
HashValue[] fPP = new HashValue[]{null};
tls = loadTLS(bP,fPP);
tlsInitialised = bP[0];
fingerPrint= fPP[0];
}
private SSLContext loadTLS(boolean[] tlsPointer,HashValue[] fingerPrintPointer) {
SSLContext tlsinit = null;
try {
TrustManager[] trustAllCerts = new TrustManager[]{
new X509TrustManager() {
public X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(X509Certificate[] certs, String authType) {
//logger.debug("checking client trusted: "+authType);
}
public void checkServerTrusted(X509Certificate[] certs, String authType) {
//logger.debug("checking server trusted: "+authType);
}
}
};
tlsinit = SSLContext.getInstance("TLSv1.2");
KeyManager[] managers = identity.getBoolean(PI.allowTLS)? loadManager(fingerPrintPointer,true):null;
tlsinit.init(managers,trustAllCerts , null);
tlsPointer[0]= managers != null && managers.length > 0 ;
logger.debug("tls initialized: "+tlsPointer[0]);
} catch (NoSuchAlgorithmException nse) {
logger.error(nse, nse);
} catch (KeyManagementException kme) {
logger.error(kme, kme);
}
return tlsinit;
}
/* (non-Javadoc)
* @see uc.crypto.ICryptoManager#getFingerPrint()
*/
public HashValue getFingerPrint() {
return fingerPrint;
}
/* (non-Javadoc)
* @see uc.crypto.ICryptoManager#isTLSInitialized()
*/
public boolean isTLSInitialized() {
return tlsInitialised;
}
/* (non-Javadoc)
* @see uc.crypto.ICryptoManager#createSSLEngine()
*/
public final SSLEngine createSSLEngine() {
return tls.createSSLEngine();
}
private KeyManager[] loadManager(HashValue[] fingerPrintPointer,boolean retry) {
FileInputStream fis = null;
try {
File f = new File(PI.getStoragePath()+File.separator+ identity.getCertFileName() );
if (!f.isFile()) {
dcc.logEvent(LanguageKeys.CreatingCertificate);
genKeypair(f,"RSA");
dcc.logEvent(LanguageKeys.CreatedCertificate);
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
fis = new FileInputStream(f);
store.load(fis, PASS );
kmf.init(store, PASS);
dcc.logEvent(LanguageKeys.LoadedCertificate);
KeyManager[] managers = kmf.getKeyManagers();
Certificate cert = store.getCertificate(aliasForAlg("RSA"));
if (cert != null) {
Date oneWeek = new Date(System.currentTimeMillis()+TimeUnit.DAYS.toMillis(7));
if (cert.getType().equals("X.509") && ((X509Certificate) cert).getNotAfter().before(oneWeek)) { // cert expiration
logger.warn("Certificat expires soon/ already expired: " + ((X509Certificate) cert).getNotAfter() +": deleting certificate.");
GH.close(fis);
if (retry && (f.renameTo(new File(f.getParentFile(),"old_keystore"))||f.delete())) {
return loadManager(fingerPrintPointer, false);
}
}
fingerPrintPointer[0] = SHA256HashValue.hashData(cert.getEncoded());
logger.debug("fingerPrint: "+fingerPrintPointer[0]);
} else {
GH.close(fis);
if (retry && (f.renameTo(new File(f.getParentFile(),"invalid_keystore"))||f.delete())) {
return loadManager(fingerPrintPointer, false);
} else {
logger.error(String.format(LanguageKeys.NoCertFound,f));
}
}
logger.debug("Managers created: "+managers.length);
return managers;
} catch(RuntimeException re) {
throw re;
} catch(Exception e) {
logger.warn(String.format(LanguageKeys.CertificateCreationFailed,e),e);
identity.put(PI.allowTLS, false);
return null;
} finally {
GH.close(fis);
}
}
/*
*
* keytool -genkey -storepass 123456 -keystore storagename -keyalg RSA -dname "CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown" -validity 999
*/
private static void genKeypair(File f,String alg) throws Exception {
String keytool = System.getProperty("java.home")+File.separator
+"bin"+File.separator+"keytool";
logger.debug("certificate created on "+f.getCanonicalPath()+" "+keytool);
final Process p = Runtime.getRuntime().exec(new String[]{
keytool ,
"-genkey", //"-genkeypair" would not work with java 1.5 though "-genkey" will work with newer java
"-storepass",
new String(PASS),
"-keyalg",
alg, //"RSA" /"DSA"
"-alias",
aliasForAlg(alg),
"-dname",
"CN=Unknown, OU=Unknown, O=Unknown, L=Unknown, ST=Unknown, C=Unknown",
"-validity",
"730",
"-keystore",
f.getCanonicalPath()});
PrintStream ps = new PrintStream(p.getOutputStream());
ps.println();
ps.println();
ps.close();
p.waitFor();
}
private static String aliasForAlg(String alg) {
return "jucy-"+alg+"-key";
}
}