Limpando o cache de certificados Java (forçar o recarregamento de certificados)

6

Uma pergunta simples aqui.

Um aplicativo me deu essa exceção ao tentar acessar um site com um certificado expirado: java.security.cert.CertificateExpiredException

Então, eu renovei o certificado da máquina do site e reiniciei. Quando tento acessá-lo do Firefox ou do Chrome, ele carrega o novo certificado (cuja data de expiração está definida em algum lugar perto de 2040).

O problema é que os aplicativos Java não parecem renovar esse certificado, parece estar preso em algum tipo de cache interno. Eu já tentei adicioná-lo ao keystore e definir opções nas propriedades do aplicativo como -Dcom.sun.net.ssl.checkRevocation=false . Não importa o que eu faça, sempre me lança um java.security.cert.CertificateExpiredException

Alguma idéia?

    
por Alberto Fernández 26.05.2012 / 11:24

2 respostas

1

O local padrão do keystore Java é um arquivo .keystore em seu diretório inicial (propriedade do sistema user.home), a menos que você especifique de outra forma que é onde um aplicativo Java ficará.

Tente executar:

$ keytool -list -keystore ~/.keystore -storepass changeit -v

para ver se o certificado expirado está lá.

Se você quiser especificar um keystore de identidade diferente para usar, use as seguintes propriedades do sistema:

javax.net.ssl.Keystore=/path/to/identity.jks
javax.net.ssl.keyStorePassword=mykeystorepassword

Acredito que o Firefox use o NSS e você pode visualizar seu keystore usando o utilitário certutil (do pacote nss-tools ou similar) - algo como:

$ certutil -L -d sql:$HOME/.pki/nssdb

Você deve ser capaz de usar o utilitário pk12util para extrair a chave e o certificado em um arquivo PKCS12, mas provavelmente é melhor gerar apenas uma nova solicitação de assinatura de certificado usando o utilitário keytool.

Observe que um certificado revogado não é o mesmo que um certificado expirado, e é por isso que seu checkRevocation = false não funciona. A autoridade de certificação pode revogar um certificado a qualquer momento, mesmo que ainda não tenha expirado, e isso indica que não deve mais ser confiável.

    
por 18.06.2012 / 22:23
1

A questão se deve a um bug que causa o HttpsUrlConnection não usar o SNI quando um verificador de nome de host personalizado for usado.

Solução alternativa de bugs

javax.net.ssl.HttpsURLConnection connection = (javax.net.ssl.HttpsURLConnection) new java.net.URL(url).openConnection();
connection.setHostnameVerifier(... hostname verifier which indirectly causes a bug ...);

//the remaining code fixes the bug by forcing the use of SNI even with the custom hostname verifier
final javax.net.ssl.SSLSocketFactory originalSocketFactory = connection.getSSLSocketFactory();
connection.setSSLSocketFactory(new javax.net.ssl.SSLSocketFactory() {
  public String[] getDefaultCipherSuites() {
    return originalSocketFactory.getDefaultCipherSuites();
  }

  public String[] getSupportedCipherSuites() {
    return originalSocketFactory.getSupportedCipherSuites();
  }

  private java.net.Socket convertSocket(javax.net.ssl.SSLSocket socket, String host) {
    javax.net.ssl.SNIHostName serverName = new javax.net.ssl.SNIHostName(host);
    java.util.List<javax.net.ssl.SNIServerName> serverNames = new java.util.ArrayList<>(1);
    serverNames.add(serverName);
    javax.net.ssl.SSLParameters params = socket.getSSLParameters();
    params.setServerNames(serverNames);
    socket.setSSLParameters(params);
    return socket;
  }

  public java.net.Socket createSocket(java.net.Socket s, String host, int port, boolean autoClose) throws IOException {

    //host = new URL(url).getHost();
    javax.net.ssl.SSLSocket socket = (javax.net.ssl.SSLSocket) originalSocketFactory.createSocket(s,host,port,autoClose);
    return convertSocket(socket, host);
  }

  public java.net.Socket createSocket(java.net.InetAddress host, int port) throws IOException {
    //You may need convertSocket here, I didn't
    return originalSocketFactory.createSocket(host, port);
  }

  public java.net.Socket createSocket(java.net.InetAddress address, int port, java.net.InetAddress localAddress, int localPort) throws IOException {
    //You may need convertSocket here, I didn't
    return originalSocketFactory.createSocket(address, port, localAddress, localPort);
  }

  public java.net.Socket createSocket(String host, int port) throws IOException {
    //You may need convertSocket here, I didn't
    return originalSocketFactory.createSocket(host, port);
  }

  public java.net.Socket createSocket(String host, int port, java.net.InetAddress localHost, int localPort) throws IOException {

    //You may need convertSocket here, I didn't
    return originalSocketFactory.createSocket(host, port, localHost, localPort);
  }
});
    
por 21.06.2018 / 03:49