3

I have a signed applet compiled in 1.6 (with 1.5 compatibility) that make some HTTPS get connections.
The HTTPS certificate on the server is selfsigned, but the applet embeds a .pem file containing the root certificate that allows to validate the certification chain.
The applet is signed with a valid commercial certificate.

In my unit tests, the HTTPS connection is done without any problem.
And there is an expected connection error without this .pem import :

javax.net.ssl.SSLHandshakeException - sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

But when I use the applet in my website, there is the following security warning popup when the HTTPS connection is done:

Warning popup

Whether I click on Continue or Cancel, the HTTPS connection is done without any problem, and this warning never shows anymore.

Is there a way to remove this useless popup?


Inside my MANIFEST.MF, I have added:

Trusted-Library: true

I also tested this, without any changes:

Trusted-Only: true
Permissions: all-permissions

My java code is a slightly modified version of the code from here :

InputStream pemStream = getClass().getResourceAsStream("/Resources/cacert.pem");
HttpsURLConnection con = (HttpsURLConnection) new URL(url).openConnection();
con.setSSLSocketFactory(getSocketFactoryFromPEM(pemStream));
con.setRequestMethod("GET");
con.setDoInput(true);
con.setDoOutput(false);
con.connect();
InputStream connectionStream = con.getInputStream();


private SSLSocketFactory getSocketFactoryFromPEM(InputStream pemStream) throws Exception
{
    byte[] certAndKey = streamToBytes(pemStream);
    byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
    X509Certificate cert = generateCertificateFromDER(certBytes);
    KeyStore keystore = KeyStore.getInstance("JKS");
    keystore.load(null);
    keystore.setCertificateEntry("cert-alias", cert);
    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(keystore);
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, tmf.getTrustManagers(), null);
    return context.getSocketFactory();
}

 private static byte[] streamToBytes(InputStream fileStream) throws IOException
{
    ByteArrayOutputStream ous = null;
    try
    {
        byte[] buffer = new byte[4096];
        ous = new ByteArrayOutputStream();
        int read = 0;
        while ((read = fileStream.read(buffer)) != -1)
            ous.write(buffer, 0, read);
    }
    finally
    {
        try
        {
            if (ous != null)
                ous.close();
        }
        catch (IOException e)
        {
            // swallow, since not that important
        }
        try
        {
            if (fileStream != null)
                fileStream.close();
        }
        catch (IOException e)
        {
            // swallow, since not that important
        }
    }
    return ous.toByteArray();
}

private static byte[] parseDERFromPEM(byte[] pem, String beginDelimiter, String endDelimiter)
{
    String data = new String(pem);
    String[] tokens = data.split(beginDelimiter);
    tokens = tokens[1].split(endDelimiter);
    return DatatypeConverter.parseBase64Binary(tokens[0]);
}

private static X509Certificate generateCertificateFromDER(byte[] certBytes) throws CertificateException
{
    CertificateFactory factory = CertificateFactory.getInstance("X.509");
    return (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(certBytes));
}



Workaround (09/30/2013)

If the .pem is added via the Java Control Panel, in the Secure Site CA, there is no more Java popup.

So, the workaround is to add the .pem programmatically to this key store (jsse cacerts).
I modified the code of the function getSocketFactoryFromPEM in order to store the keystore at the correct place:

private SSLSocketFactory getSocketFactoryFromPEM(InputStream pemStream) throws Exception
{
    byte[] certAndKey = streamToBytes(pemStream);
    byte[] certBytes = parseDERFromPEM(certAndKey, "-----BEGIN CERTIFICATE-----", "-----END CERTIFICATE-----");
    X509Certificate cert = generateCertificateFromDER(certBytes);

    KeyStore keystore = KeyStore.getInstance("JKS");

    String userHome = System.getProperty("user.home");
    String certPath = userHome + File.separator;
    int os = getOperatingSystem();
    switch (os)
    {
        case WINDOWS:
            //  <User Application Data Folder>\LocalLow\Sun\Java\Deployment\security\trusted.jssecacerts
            certPath += "AppData" + File.separator + "LocalLow" + File.separator + "Sun" + File.separator + "Java" + File.separator + "Deployment";
            break;
        case MAC:
            // ~/Library/Application Support/Oracle/Java/Deployment/security/trusted.jssecacerts
            certPath += "Library" + File.separator + "Application Support" + File.separator + "Oracle" + File.separator + "Java" + File.separator + "Deployment";
            break;
        case LINUX:
            // ${user.home}/.java/deployment/security/trusted.jssecacerts
            certPath += ".java" + File.separator + "deployment";
            break;
        default:
            break;
    }
    certPath += File.separator + "security" + File.separator + "trusted.jssecacerts";

    File certInputFile = new File(certPath);
    FileInputStream certInputStream = null;
    if (certInputFile.canRead())
    {
        certInputStream = new FileInputStream(certInputFile);
        keystore.load(certInputStream, null);
    }
    else
    {
        keystore.load(null);
    }

    keystore.setCertificateEntry("cert-alias", cert);

    FileOutputStream certOutputFile = new FileOutputStream(certInputFile);
    keystore.store(certOutputFile, "".toCharArray());
    certOutputFile.close();

    TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    tmf.init(keystore);
    SSLContext context = SSLContext.getInstance("TLS");
    context.init(null, tmf.getTrustManagers(), null);
    return context.getSocketFactory();
}
Community
  • 1
  • 1
aba_vasc
  • 51
  • 3
  • FYI, I found a work around! More informations at the end of my original post. I noticed that if the .pem is added via the Java Control Panel, in the Secure Site CA, there is no more Java popup. The workaround is then to add the .pem programmatically to this key store (jsse cacerts) – aba_vasc Sep 30 '13 at 14:11

0 Answers0