3

1.6 (1.5 との互換性あり) でコンパイルされた署名付きアプレットがあり、いくつかの HTTPS が接続を取得します。
サーバー上の HTTPS 証明書は自己署名されていますが、アプレットは証明書チェーンを検証できるルート証明書を含む .pem ファイルを埋め込みます。
アプレットは、有効な商用証明書で署名されています。

私の単体テストでは、HTTPS 接続は問題なく行われています。
そして、この .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

しかし、Web サイトでアプレットを使用すると、HTTPS 接続が完了すると、次のセキュリティ警告ポップアップが表示されます。

警告ポップアップ

[続行] をクリックしても [キャンセル] をクリックしても、HTTPS 接続は問題なく行われ、この警告は表示されなくなりました。

この役に立たないポップアップを削除する方法はありますか?


MANIFEST.MF内に、次を追加しました。

Trusted-Library: true

これも変更せずにテストしました:

Trusted-Only: true
Permissions: all-permissions

私のJavaコードは、ここからのコードのわずかに変更されたバージョンです:

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));
}



回避策 (2013 年 9 月 30 日)

Java コントロール パネルを使用して .pem を追加すると、セキュア サイト CA に Java ポップアップが表示されなくなります。

したがって、回避策は、.pem をプログラムでこのキー ストア (jsse cacerts) に追加することです。キーストアを正しい場所に格納するために
、関数getSocketFactoryFromPEMのコードを変更しました。

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();
}
4

0 に答える 0