IDEMPIERE-4611 Replace dependency to sun.security.tools.keytool with … (#486)
* IDEMPIERE-4611 Replace dependency to sun.security.tools.keytool with Bouncy Castle * IDEMPIERE-4611 Replace dependency to sun.security.tools.keytool with Bouncy Castle Fix error with State
This commit is contained in:
parent
da6d6b83aa
commit
3965dd68fe
|
@ -3,13 +3,12 @@
|
||||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
|
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="module" value="true"/>
|
<attribute name="module" value="true"/>
|
||||||
<attribute name="add-exports" value="java.base/sun.security.tools.keytool=ALL-UNNAMED"/>
|
|
||||||
</attributes>
|
</attributes>
|
||||||
<accessrules>
|
<accessrules>
|
||||||
<accessrule kind="accessible" pattern="sun/security/tools/*"/>
|
<accessrule kind="accessible" pattern="sun/security/tools/*"/>
|
||||||
</accessrules>
|
</accessrules>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||||
<classpathentry kind="src" path="src/"/>
|
<classpathentry kind="src" path="src"/>
|
||||||
<classpathentry kind="output" path="target/classes"/>
|
<classpathentry kind="output" path="target/classes"/>
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
@ -11,6 +11,11 @@ Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version>=11))"
|
||||||
Import-Package: javax.mail;version="1.5",
|
Import-Package: javax.mail;version="1.5",
|
||||||
javax.mail.internet;version="1.5",
|
javax.mail.internet;version="1.5",
|
||||||
org.apache.tools.ant,
|
org.apache.tools.ant,
|
||||||
|
org.bouncycastle.asn1.x500;version="1.66.0",
|
||||||
|
org.bouncycastle.cert;version="1.66.0",
|
||||||
|
org.bouncycastle.cert.jcajce;version="1.66.0",
|
||||||
|
org.bouncycastle.operator;version="1.66.0",
|
||||||
|
org.bouncycastle.operator.jcajce;version="1.66.0",
|
||||||
org.eclipse.ant.core,
|
org.eclipse.ant.core,
|
||||||
org.eclipse.core.runtime;version="3.4.0",
|
org.eclipse.core.runtime;version="3.4.0",
|
||||||
org.eclipse.equinox.app,
|
org.eclipse.equinox.app,
|
||||||
|
|
|
@ -19,22 +19,38 @@ package org.compiere.install;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.io.FileInputStream;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.math.BigInteger;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.security.Key;
|
import java.security.Key;
|
||||||
|
import java.security.KeyPair;
|
||||||
|
import java.security.KeyPairGenerator;
|
||||||
import java.security.KeyStore;
|
import java.security.KeyStore;
|
||||||
|
import java.security.KeyStore.PasswordProtection;
|
||||||
|
import java.security.KeyStore.PrivateKeyEntry;
|
||||||
|
import java.security.PrivateKey;
|
||||||
|
import java.security.SecureRandom;
|
||||||
import java.security.cert.Certificate;
|
import java.security.cert.Certificate;
|
||||||
import java.util.ArrayList;
|
import java.security.cert.X509Certificate;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.temporal.ChronoUnit;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import javax.swing.JFrame;
|
import javax.swing.JFrame;
|
||||||
|
|
||||||
|
import org.bouncycastle.asn1.x500.X500Name;
|
||||||
|
import org.bouncycastle.cert.X509CertificateHolder;
|
||||||
|
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
|
||||||
|
import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
|
||||||
|
import org.bouncycastle.operator.ContentSigner;
|
||||||
|
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
|
||||||
import org.compiere.Adempiere;
|
import org.compiere.Adempiere;
|
||||||
import org.compiere.util.CLogMgt;
|
import org.compiere.util.CLogMgt;
|
||||||
import org.compiere.util.CLogger;
|
import org.compiere.util.CLogger;
|
||||||
|
|
||||||
import sun.security.tools.keytool.Main;
|
//import sun.security.tools.keytool.Main;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class to manage SSL KeyStore
|
* Class to manage SSL KeyStore
|
||||||
|
@ -236,7 +252,6 @@ public class KeyStoreMgt
|
||||||
//
|
//
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
genkey (alias, m_password, m_file.getAbsolutePath(), dname);
|
|
||||||
selfcert (alias, m_password, m_file.getAbsolutePath(), dname);
|
selfcert (alias, m_password, m_file.getAbsolutePath(), dname);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
@ -355,7 +370,7 @@ public class KeyStoreMgt
|
||||||
if (l != null && l.length() > 0)
|
if (l != null && l.length() > 0)
|
||||||
dname.append(", L=").append(escapeCommas(l)); // locality
|
dname.append(", L=").append(escapeCommas(l)); // locality
|
||||||
if (s != null && s.length() > 0)
|
if (s != null && s.length() > 0)
|
||||||
dname.append(", S=").append(escapeCommas(s)); // state
|
dname.append(", ST=").append(escapeCommas(s)); // state
|
||||||
dname.append(", C=").append(escapeCommas(c)); // country
|
dname.append(", C=").append(escapeCommas(c)); // country
|
||||||
return dname.toString();
|
return dname.toString();
|
||||||
} // getDname
|
} // getDname
|
||||||
|
@ -382,91 +397,72 @@ public class KeyStoreMgt
|
||||||
} // escapeCommas
|
} // escapeCommas
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate Key
|
* Generate Key and Cert
|
||||||
* @param alias adempiere
|
* @param alias keystore alias
|
||||||
* @param password password
|
|
||||||
* @param fileName key store file name (may have spaces)
|
|
||||||
* @param dname distinguished name
|
|
||||||
*/
|
|
||||||
public static void genkey (String alias, char[] password, String fileName, String dname)
|
|
||||||
{
|
|
||||||
StringBuilder cmd = new StringBuilder ("-genkey -keyalg rsa");
|
|
||||||
cmd.append(" -alias ").append(alias);
|
|
||||||
cmd.append(" -dname \"").append(dname).append("\"");
|
|
||||||
cmd.append(" -keypass ").append(password).append(" -validity 999");
|
|
||||||
if (fileName.indexOf(' ') != -1)
|
|
||||||
cmd.append(" -keystore \"").append(fileName).append("\" -storepass ").append(password);
|
|
||||||
else
|
|
||||||
cmd.append(" -keystore ").append(fileName).append(" -storepass ").append(password);
|
|
||||||
keytool (cmd.toString());
|
|
||||||
} // genkey
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Generate Key
|
|
||||||
* @param alias adempiere
|
|
||||||
* @param password password
|
* @param password password
|
||||||
* @param fileName key store file name (may have spaces)
|
* @param fileName key store file name (may have spaces)
|
||||||
* @param dname distinguished name
|
* @param dname distinguished name
|
||||||
*/
|
*/
|
||||||
public static void selfcert (String alias, char[] password, String fileName, String dname)
|
public static void selfcert (String alias, char[] password, String fileName, String dname)
|
||||||
{
|
{
|
||||||
StringBuilder cmd = new StringBuilder ("-selfcert");
|
try
|
||||||
cmd.append(" -alias ").append(alias);
|
|
||||||
cmd.append(" -dname \"").append(dname).append("\"");
|
|
||||||
cmd.append(" -keypass ").append(password).append(" -validity 999");
|
|
||||||
if (fileName.indexOf(' ') != -1)
|
|
||||||
cmd.append(" -keystore \"").append(fileName).append("\" -storepass ").append(password);
|
|
||||||
else
|
|
||||||
cmd.append(" -keystore ").append(fileName).append(" -storepass ").append(password);
|
|
||||||
keytool (cmd.toString());
|
|
||||||
} // selfcert
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Submit Command to Key Tool
|
|
||||||
* @param cmd command
|
|
||||||
*/
|
|
||||||
public static void keytool(String cmd)
|
|
||||||
{
|
|
||||||
if (log.isLoggable(Level.INFO)) log.info("keytool " + cmd);
|
|
||||||
ArrayList<String> list = new ArrayList<String>();
|
|
||||||
StringTokenizer st = new StringTokenizer(cmd, " ");
|
|
||||||
String quoteBuffer = null;
|
|
||||||
while (st.hasMoreTokens())
|
|
||||||
{
|
{
|
||||||
String token = st.nextToken();
|
File storeFile = new File(fileName);
|
||||||
// System.out.println("= " + token + " = quoteBuffer=" + quoteBuffer + " - Size=" + list.size() );
|
if (storeFile.exists())
|
||||||
if (quoteBuffer == null)
|
return;
|
||||||
{
|
|
||||||
if (token.startsWith("\""))
|
CertificateKeyPair certKeyPair = createCertificate(dname);
|
||||||
quoteBuffer = token.substring(1);
|
KeyStore keyStore = KeyStore.getInstance("JKS");
|
||||||
else
|
keyStore.load(null, null);
|
||||||
list.add(token);
|
PasswordProtection protParam = new KeyStore.PasswordProtection(password);
|
||||||
}
|
KeyStore.Entry entry = new PrivateKeyEntry(certKeyPair.keyPair.getPrivate(),
|
||||||
else
|
new Certificate[] { certKeyPair.cert });
|
||||||
quoteBuffer += " " + token;
|
keyStore.setEntry(alias, entry, protParam);
|
||||||
if (token.endsWith("\""))
|
try (OutputStream fos = Files.newOutputStream(storeFile.toPath()))
|
||||||
{
|
{
|
||||||
String str = quoteBuffer.substring(0, quoteBuffer.length()-1);
|
keyStore.store(fos, password);
|
||||||
// System.out.println(" Buffer= " + str );
|
}
|
||||||
list.add(str);
|
}
|
||||||
quoteBuffer = null;
|
catch (Exception e)
|
||||||
}
|
{
|
||||||
} // all tokens
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
//
|
} // selfcert
|
||||||
String[] args = new String[list.size()];
|
|
||||||
list.toArray(args);
|
/**
|
||||||
// System.out.println(" args #" + args.length);
|
*
|
||||||
//vpj-cd add support java 6
|
* @param dname
|
||||||
try
|
* @return pair of key and cert
|
||||||
{
|
* @throws Exception
|
||||||
Main.main(args);;
|
*/
|
||||||
}
|
private static CertificateKeyPair createCertificate(String dname) throws Exception {
|
||||||
catch (Exception e)
|
// Generate the key-pair with the official Java API's
|
||||||
{
|
KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA");
|
||||||
e.printStackTrace();
|
keyGen.initialize(2048, new SecureRandom());
|
||||||
}
|
KeyPair certKeyPair = keyGen.generateKeyPair();
|
||||||
} // ketyool
|
X500Name dnName = new X500Name(dname);
|
||||||
|
BigInteger serialNumber = BigInteger.valueOf(System.currentTimeMillis());
|
||||||
|
Instant validFrom = Instant.now();
|
||||||
|
Instant validUntil = validFrom.plus(999, ChronoUnit.DAYS);
|
||||||
|
|
||||||
|
// If there is no issuer, we self-sign our certificate.
|
||||||
|
X500Name issuerName = dnName;
|
||||||
|
PrivateKey issuerKey = certKeyPair.getPrivate();
|
||||||
|
|
||||||
|
// The cert builder to build up our certificate information
|
||||||
|
JcaX509v3CertificateBuilder builder = new JcaX509v3CertificateBuilder(
|
||||||
|
issuerName,
|
||||||
|
serialNumber,
|
||||||
|
Date.from(validFrom), Date.from(validUntil),
|
||||||
|
dnName, certKeyPair.getPublic());
|
||||||
|
|
||||||
|
// Finally, sign the certificate:
|
||||||
|
ContentSigner signer = new JcaContentSignerBuilder("SHA256WithRSA").build(issuerKey);
|
||||||
|
X509CertificateHolder certHolder = builder.build(signer);
|
||||||
|
X509Certificate cert = new JcaX509CertificateConverter().getCertificate(certHolder);
|
||||||
|
|
||||||
|
return new CertificateKeyPair(certKeyPair, cert);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get Keystore File Name
|
* Get Keystore File Name
|
||||||
|
@ -484,6 +480,15 @@ public class KeyStoreMgt
|
||||||
return fileName;
|
return fileName;
|
||||||
} // getKeystoreFileName
|
} // getKeystoreFileName
|
||||||
|
|
||||||
|
private static class CertificateKeyPair {
|
||||||
|
private KeyPair keyPair;
|
||||||
|
private X509Certificate cert;
|
||||||
|
|
||||||
|
private CertificateKeyPair(KeyPair keyPair, X509Certificate cert) {
|
||||||
|
this.keyPair = keyPair;
|
||||||
|
this.cert = cert;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**************************************************************************
|
/**************************************************************************
|
||||||
* Test
|
* Test
|
||||||
|
|
Loading…
Reference in New Issue