SSL: 400 não foi enviado nenhum certificado obrigatório

o código e as entradas

Estou a tentar estabelecer uma ligação SSL e estou a receber resposta do servidor. Eu estou fazendo isso de uma maneira padrão como é descrito por exemplo aqui; Eu corro Java 8.

a amostra do meu código seria:

    OkHttpClient client     = new OkHttpClient();
    KeyStore keyStoreClient = getClientKeyStore();
    KeyStore keyStoreServer = getServerKeyStore();
    String algorithm        = ALGO_DEFAULT;//this is defined as "PKIX"

    KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(algorithm);
    keyManagerFactory.init(keyStoreClient, PASSWORD_SERVER.toCharArray());

    SSLContext sslContext = SSLContext.getInstance("TLS");

    TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(algorithm);
    trustManagerFactory.init(keyStoreServer);

    sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), new SecureRandom());

    client.setSslSocketFactory(sslContext.getSocketFactory());
    client.setConnectTimeout(32, TimeUnit.SECONDS); // connect timeout
    client.setReadTimeout(32, TimeUnit.SECONDS);    // socket timeout

    return client;

e aqui está o código que uso para enviar pedido de obtenção:

public String get(String url) throws IOException
{
    String callUrl  = URL_LIVE.concat(url);
    Request request = new Request.Builder()
            .url(callUrl)
            .build();
    Response response = this.client.newCall(request).execute();
    return response.body().string();
}

habilitei:

System.setProperty("javax.net.debug", "ssl");

Então para ver as mensagens de depuração-mas não há erros/avisos/alertas lá, o único a coisa está no fim.

main, called close()
main, called closeInternal(true)
main, SEND TLSv1.2 ALERT:  warning, description = close_notify
main, WRITE: TLSv1.2 Alert, length = 26
main, called closeSocket(true)

que é a única coisa que posso tratar como "anormal" (mas duvido que seja).

eu tentei:

  • diferentes protocolos a desactivar / activar. Por exemplo, forçar TLSv1 / TLSv1.1 para o socket sem sucesso. Para tentar que eu embrulhei minha fábrica ssl em outra fábrica que desactiva / permite certos protocolos.
  • Desactivar, mas não muda a imagem.
  • Install Oracle Políticas porque antes havia avisos sobre alguns algoritmos ignorados e esta instalação "resolveu" que, mas o resultado geral ainda é o mesmo.
  • definir System.setProperty("sun.security.ssl.allowUnsafeRenegotiation", "true"); - coxo, mas também não mudou nada além da mensagem no log Allow unsafe renegotiation: true (era" falso " obviamente)
  • usando KeyManagerFactory.getDefaultAlgorithm() como algorithm Para KeyManagerFactory.getInstance() chamada. Isso levanta exceção Get Key failed: Given final block not properly padded e tanto quanto eu tive a idéia, é por causa do algoritmo errado usado (Leia Este). O meu algoritmo por omissão é: SunX509
  • adicionando o certificado directamente à minha máquina com keytool -importcert -file /path/to/certificate -keystore keystore.jks -alias "Alias" e depois usando isto no meu programa via System.setProperty("javax.net.ssl.trustStore","/path/to/keystore.jks"); com a configuração da senha: System.setProperty("javax.net.ssl.trustStorePassword","mypassword"); (Eu estabeleci a senha em keytool Depois do que confirmou o certificado de confiança com yes); ver isto e Este posts. Não se levantaram quaisquer erros nesta matéria-mas a questão persistiu.
  • adicionando o certificado à tecla global (A localizada em JAVA_PATH/jre/lib/security/cacerts) com: keytool -import -trustcacerts -keystore cacerts -storepass changeit -noprompt -alias Alias -file /path/to/certificate (ver isto); parece que a operação de importação foi bem sucedido, mas não mudou a imagem.
- Não sei se é relevante, pois não sou especialista em SSL.

Infelizmente, não consigo ver os registos do servidor, por isso não consigo ver a imagem completa.

Pergunta

qual pode ser a razão para este erro de 400 e como posso avançar mais (depurar/tentar algo mais)? Qualquer dica seria muito apreciada.

Author: Community, 2016-03-29

1 answers

O seu servidor está a pedir um certificado do lado do cliente. Você precisa instalar um certificado (assinado por uma autoridade de confiança) em sua máquina cliente, e deixar o seu programa saber sobre ele.

Normalmente, o seu servidor tem um certificado (com o objectivo chave definido para "Autenticação do servidor TLS") assinado pela segurança de TI da sua organização ou por uma AC globalmente de confiança. Você deve obter um certificado para "autenticação de cliente TLS" da mesma fonte.

Se capturares o TLS aperto de mão em Wireshark, você verá a mensagem ServerHello seguida de um "pedido de Certificado cliente", ao qual você responde com uma mensagem de "Certificado cliente" com o comprimento 0. O seu servidor opta por rejeitar isto.

 3
Author: Freezer, 2016-03-29 12:46:48