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 logAllow unsafe renegotiation: true
(era" falso " obviamente) - usando
KeyManagerFactory.getDefaultAlgorithm()
comoalgorithm
ParaKeyManagerFactory.getInstance()
chamada. Isso levanta exceçãoGet 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 viaSystem.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 emkeytool
Depois do que confirmou o certificado de confiança comyes
); 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.
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.
1 answers
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.