Estou com um problema de conexão SSL autorizada. Criei o Struts Action que se conecta ao servidor externo com o certificado SSL autorizado pelo cliente. Na minha ação, estou tentando enviar alguns dados para o servidor do banco, mas sem sorte, porque, como resultado do servidor, tenho o seguinte erro:
Meu método da classe Action que envia dados para o servidor
Meu arquivo merchant.properties:
Pela primeira vez, pensei que fosse um problema de certificado, converti-o de .pfx para .jks, mas tenho o mesmo erro, sem alterações.
você adicionou o certificado SSL do servidor ao seu armazenamento confiável?
— happymeal 15/06
desculpe, eu não entendo o que isso significa, eu sou novo no SSL
Assumirei que seu aplicativo está usando o armazenamento confiável padrão do java. O armazenamento confiável padrão é <java-home> / lib / security / cacerts. abra a URL do servidor com o seu navegador e baixe todos os certificados SSL; incluindo quaisquer cadeias / certificados intermediários. adicione todos esses certificados ao armazenamento confiável.
— 21711 happymeal
Não consigo abrir o URL no navegador, por causa do certificado de autenticação do cliente, posso enviar para este link apenas parâmetros específicos que recebo dos clientes.
basta abrir o URL. ignore todos os erros que você vê no seu navegador. ao acessar o URL, você verá um ícone de cadeado na barra de endereços do seu navegador. clique nele e faça o download do certificado SSL do servidor.
A falha do aperto de mão pode ter ocorrido devido a vários motivos:
Conjuntos de cifras incompatíveis em uso pelo cliente e pelo servidor. Isso exigiria que o cliente usasse (ou habilitasse) um conjunto de criptografia suportado pelo servidor.
Versões incompatíveis de SSL em uso (o servidor pode aceitar apenas TLS v1, enquanto o cliente é capaz de usar apenas SSL v3). Novamente, o cliente pode precisar garantir uma versão compatível do protocolo SSL / TLS.
Caminho de confiança incompleto para o certificado do servidor; o certificado do servidor provavelmente não é confiável pelo cliente. Isso normalmente resultaria em um erro mais detalhado, mas é bem possível. Geralmente, a correção é importar o certificado CA do servidor no armazenamento confiável do cliente.
O certificado é emitido para um domínio diferente. Novamente, isso resultaria em uma mensagem mais detalhada, mas vou indicar a correção aqui, caso essa seja a causa. A resolução nesse caso seria obter o servidor (não parece ser seu) para usar o certificado correto.
Como a falha subjacente não pode ser identificada, é melhor ativar o -Djavax.net.debug=allsinalizador para ativar a depuração da conexão SSL estabelecida. Com a depuração ativada, você pode identificar qual atividade do handshake falhou.
Com base nos detalhes agora disponíveis, parece que o problema ocorre devido a um caminho incompleto de confiança do certificado entre o certificado emitido para o servidor e uma CA raiz. Na maioria dos casos, isso ocorre porque o certificado da CA raiz está ausente no armazenamento confiável, levando à situação em que um caminho de confiança do certificado não pode existir; o certificado é essencialmente não confiável pelo cliente. Os navegadores podem apresentar um aviso para que os usuários possam ignorar isso, mas o mesmo não acontece com clientes SSL (como a classe HttpsURLConnection ou qualquer biblioteca de clientes HTTP como Apache HttpComponents Client ).
A maioria dessas classes / bibliotecas cliente dependeria do armazenamento confiável usado pela JVM para validação de certificado. Na maioria dos casos, esse será o cacertsarquivo no diretório JRE_HOME / lib / security. Se o local do armazenamento confiável tiver sido especificado usando a propriedade do sistema JVM javax.net.ssl.trustStore, o armazenamento nesse caminho geralmente será o usado pela biblioteca do cliente. Em caso de dúvida, dê uma olhada na sua Merchantturma e descubra a turma / biblioteca que ela está usando para fazer a conexão.
Adicionar o certificado do servidor que emite a CA a esse armazenamento confiável deve resolver o problema. Você pode consultar minha resposta em uma pergunta relacionada sobre como obter ferramentas para essa finalidade, mas o utilitário Java keytool é suficiente para essa finalidade.
Aviso : O armazenamento confiável é essencialmente a lista de todas as CAs em que você confia. Se você inserir um certificado que não pertence a uma CA na qual não confia, as conexões SSL / TLS com sites com certificados emitidos por essa entidade poderão ser descriptografadas se a chave privada estiver disponível.
Atualização # 2: Compreendendo a saída do rastreamento JSSE
O keystore e os truststores usados ​​pela JVM são geralmente listados no início, algo como o seguinte:
Se o armazenamento confiável errado for usado, será necessário reimportar o certificado do servidor para o correto ou reconfigurar o servidor para usar o listado (não recomendado se você tiver várias JVMs e todas elas forem usadas para diferentes necessidades).
Se você deseja verificar se a lista de certificados confiáveis ​​contém os certificados necessários, existe uma seção para o mesmo, que começa como:
Você precisará procurar se a autoridade de certificação do servidor é um assunto.
O processo de handshake terá algumas entradas salientes (você precisará conhecer o SSL para entendê-las em detalhes, mas, para fins de depuração do problema atual, será suficiente saber que um handshake_failure geralmente é relatado no ServerHello.
Uma série de entradas será relatada quando a conexão estiver sendo inicializada. A primeira mensagem enviada pelo cliente em uma configuração de conexão SSL / TLS é a mensagem ClientHello, geralmente relatada nos logs como:
Observe os conjuntos de criptografia usados. Este pode ter que concordar com a entrada em seu arquivo merchant.properties, para a mesma convenção pode ser empregado por biblioteca do banco. Se a convenção usada for diferente, não haverá motivo de preocupação, pois o ServerHello indicará isso, se o conjunto de criptografia for incompatível.
O servidor responde com um ServerHello, que indicará se a configuração da conexão pode continuar. As entradas nos logs geralmente são do seguinte tipo:
Observe o conjunto de cifras que ele escolheu; esse é o melhor pacote disponível para o servidor e o cliente. Normalmente, o conjunto de criptografia não é especificado se houver um erro. O certificado do servidor (e opcionalmente toda a cadeia) é enviado pelo servidor e pode ser encontrado nas entradas como:
Se a verificação do certificado for bem-sucedida, você encontrará uma entrada semelhante a:
Uma das etapas acima não teria êxito, resultando no handshake_failure, pois o handshake normalmente está completo nesse estágio (na verdade não, mas os estágios subsequentes do handshake normalmente não causam falha no handshake). Você precisará descobrir qual etapa falhou e postar a mensagem apropriada como uma atualização para a pergunta (a menos que você já tenha entendido a mensagem e saiba o que fazer para resolvê-la).
Por favor, poste o que tiver, se puder, para que eu possa atualizar a resposta com uma resposta mais específica.
Ok Vineet, não consigo descobrir como lidar com isso, já estou exausto. Eu encontrei uma maneira de verificar a URL do servidor com o openssl "openssl s_client -connect servername: 4402" e veja o que eu consegui: img225.imageshack.us/img225/8999/screenshoturr.png
@hoss, parece que o certificado do servidor foi emitido por uma entidade que não está presente no armazenamento confiável usado pelo OpenSSL e também possivelmente não está presente no armazenamento confiável usado pelo seu servidor (o cliente), quando ele se conecta ao o servidor. Nesse caso, você precisará importar o certificado da CA que emitiu o certificado ( e não o servidor ) para o armazenamento confiável do seu cliente (OpenSSL / seu servidor).
Bem, pode ser que isso dependa de cacerts. Mas você pode determinar isso apenas se entender a saída da depuração da rede. Se você quiser verificar isso, precisará usar o keytool -list -v -keystore $JAVA_HOME/jre/lib/security/cacertscomando para imprimir o conteúdo. Em seguida, verifique se os certificados em cacerts correspondem à CA do certificado do banco.
O padrão é geralmente changeit. A menos que tenha sido alterado.
A instalação da força ilimitada do Java Cryptography Extension (JCE) ( para JDK7 | for JDK8 ) pode corrigir esse erro. Descompacte o arquivo e siga o leia-me para instalá-lo.
— Simon Yu
A falha do handshake pode ser uma implementação de protocolo TLSv1 com erros.
No nosso caso, isso ajudou no java 7:
A jvm negociará nesta ordem. Os servidores com a atualização mais recente farão o 1.2, os de buggy descerão para a v1 e isso funciona com a v1 semelhante no java 7.
— Bela Vizy
Isso me ajudou. Havia o meu ClientHello, mas nenhum servidor, o final foi bastante abrupto. Isso corrigiu para mim no Java 7. Muito obrigado.
Isso também pode acontecer quando o cliente precisa apresentar um certificado. Depois que o servidor lista a cadeia de certificados, pode acontecer o seguinte:
3. Solicitação de certificado O servidor emitirá uma solicitação de certificado do cliente. A solicitação listará todos os certificados que o servidor aceita.
4. Cadeia de Certificados de Clientes Este é o certificado que o cliente está enviando para o servidor.
Se não houver um certificado na cadeia e o servidor exigir um, você receberá o erro de handshake aqui. Uma causa provável é que o caminho para o seu certificado não foi encontrado.
5. Verificação de certificado O cliente solicita ao servidor que verifique o certificado
Esta etapa acontecerá apenas se você estiver enviando um certificado.
6. Concluído O servidor responderá com uma resposta de verificação
no meu caso, parece que todas as etapas estão bem, mas ainda assim recebemos o erro do aperto de mão.
— Tib 11/02
resposta muito boa ... mas tudo isso está bem na minha falha de aperto de mão, mas ainda assim eu tenho a falha. você poderia dar uma olhada na minha pergunta semelhante?
Falha na apresentação de um certificado de cliente não representa nenhum tipo de erro no TLS. Se o servidor exigir um certificado de cliente e um não for apresentado, ele fechará a conexão.
@EJP isso é verdade, não é um erro no TLS, no entanto, a falha na conexão aparece como um erro no código Java.
@ Brig Mas não como um alerta, que é o que esta resposta diz e o que é a pergunta.
Não acho que isso resolva o problema para o primeiro interlocutor, mas para os googlers que vêm aqui em busca de respostas:
Na atualização 51, o java 1.8 proíbe cifras [1] RC4 por padrão, como podemos ver na página Notas da versão:
Correção de bug: Proibir conjuntos de cifras RC4
O RC4 agora é considerado como uma cifra comprometida.
Os conjuntos de cifras RC4 foram removidos da lista de conjuntos de cifras ativada por padrão do cliente e do servidor na implementação do Oracle JSSE. Esses conjuntos de criptografia ainda podem ser ativados por SSLEngine.setEnabledCipherSuites()e SSLSocket.setEnabledCipherSuites()métodos. Consulte JDK-8077109 (não público).
Se o seu servidor tiver uma forte preferência por essa cifra (ou usar apenas essa cifra), isso poderá ativar um handshake_failurejava.
Você pode testar a conexão com o servidor ativando as cifras RC4 (primeiro, tente sem enabledargumento para ver se dispara a e handshake_failure, em seguida, defina enabled:
Eu tenho esse erro enquanto tentava usar o JDK 1.7. Quando atualizei meu JDK para jdk1.8.0_66, tudo começou a funcionar bem.
Portanto, a solução mais simples para esse problema pode ser: atualize seu JDK e ele poderá começar a funcionar bem.
— Maxim Votyakov
Agradável. A solução mais simples é atualizar o JDK? : D Você sabe o quão complicado isso pode ser, dependendo do ambiente em que isso está sendo feito? Suponha que a Amazon execute o JDK 7 e agora precise atualizar para o JDK 8 de repente ... Bom!
Uma atualização de versão secundária simples resolveu esse problema para mim .. de JDK 11.0.1 para 11.0.6
No meu caso, cert é importado, o erro permanece, resolvido isso adicionando System.setProperty("https.protocols", "TLSv1.2,TLSv1.1,SSLv3");antes de conectar
— Molly Gu
Trabalhou para mim em java 1.8. Obrigado :)
— Supun Amarasinghe
Supondo que você esteja usando os protocolos SSL / TLS adequados, configurando seu keyStoree corretamente trustStoree confirmando que não existem problemas com os próprios certificados, pode ser necessário reforçar seus algoritmos de segurança .
Conforme mencionado na resposta do Vineet , um possível motivo para você receber esse erro é o uso de conjuntos de códigos incompatíveis. Atualizando my local_policye US_export_policyjars na securitypasta do meu JDK com os fornecidos na Java Cryptography Extension (JCE) , consegui concluir o handshake com êxito.
— heez
Hoje, encontro o mesmo problema com o cliente OkHttp para obter um URL baseado em https. Foi causado pela incompatibilidade da versão do protocolo Https e do método Cipher entre o servidor e o cliente .
1) verifique o site https versão do protocolo e método de cifra.
Você obterá muitas informações detalhadas, as principais informações estão listadas a seguir:
2) configure seu cliente http, por exemplo, no caso do cliente OkHttp :
Isso vai conseguir o que queremos.
— Armstrongya
Encontrei um servidor HTTPS que falhou dessa maneira se meu processo do cliente Java foi configurado com
A conexão falhou handshake_failureapós a ServerHelloconclusão com êxito, mas antes do início do fluxo de dados.
Não havia uma mensagem de erro clara que identificasse o problema, o erro parecia
Eu isolei o problema tentando com e sem a -Djsse.enableSNIExtension=falseopção " "
Estou recebendo o mesmo erro ao conectar-me ao sandbox GDAX, alguma solução para isso?
— Nitin Vavdiya
O meu foi um TLSerro de versão incompatível.
Anteriormente, TLSv1eu mudei TLSV1.2isso resolveu o meu problema.
Estou usando o cliente http com.google.api. Quando me comunico com um site interno da empresa, recebi esse problema ao usar por engano https, em vez de http.
— thebiggestlebowski
Não, você não pode. O servidor não pode enviar um alerta TLS se não estiver falando TLS.
Eu atualizei meu comentário para mostrar a saída do meu programa. Isso é real. Agradeceria se você removesse o voto negativo.
É real, mas não é causado pela conversação do TLS com um servidor de texto sem formatação. Um servidor de texto sem formatação não está falando de TLS, por definição, e, portanto, você não pode receber um alerta de TLS por definição. Você não tem nenhuma informação sobre quem rebaixou sua resposta.
Presumi que você votou mal - minhas desculpas, se não for esse o caso. Minha mensagem de erro corresponde exatamente ao título desta pergunta. É um caminho válido / caso de teste para receber essa mensagem de erro e eu tenho uma solução que pode ajudar outras pessoas. Respeitosamente, acho que não importa se foi causado por uma resposta de erro do servidor TLS ou não. Alguém chegará aqui do google e minha resposta pode ajudar se cometerem o mesmo erro.
Eu não disse nada sobre sua mensagem de erro. Estou comentando sua alegação incorreta de que ela se deve ao "uso incorreto de HTTPS em vez de HTTP". Não é, e não pode ser, por razões que afirmei e que você não abordou de forma alguma. O uso do HTTP certamente fará com que ele desapareça, obviamente, pois não há alertas TLS em texto sem formatação, mas não soluciona o problema subjacente.
Eu tive uma questão semelhante; a atualização para o Apache HTTPClient 4.5.3 o corrigiu.
Ugg! Acabou sendo simplesmente um problema de versão do Java para mim. Eu recebi o erro de aperto de mão usando o JRE 1.6 e tudo funcionou perfeitamente usando o JRE 1.8.0_144.
Isenção de responsabilidade: não sei se a resposta será útil para muitas pessoas, apenas compartilhando porque pode.
Eu estava recebendo esse erro ao usar o Parasoft SOATest para enviar solicitação XML (SOAP).
O problema foi que eu selecionei o alias errado no menu suspenso depois de adicionar o certificado e autenticá-lo.
No meu caso, o site apenas pode usar o TLSv1.2. e eu uso o apache httpclient 4.5.6, eu uso esse código e instalo o jce para resolver isso (JDK1.7):
— Tianmu
Para solucionar problemas da perspectiva do desenvolvedor (item 1) e do administrador do sistema (itens 2 e 3):
Ative a depuração do handshake SSL no Java via -Djavax.net.debug=ssl:handshake:verbose.
Instale o ssldump no servidor via sudo apt install ssldumpou compile a partir da fonte seguindo este link se você observar Unknown valuena cifra quando executar a etapa abaixo.
No servidor, sudo ssldump -k <your-private-key> -i <your-network-interface>
Verifique o log sobre o real motivo da falha.
Exemplo de aperto de mão do log ssldump:
Exemplo de handshake bem-sucedido do log ssldump
Exemplo de log Java não funcionando
No meu caso, tive um problema com a versão 1.1. Eu estava reproduzindo o problema facilmente com curl. O servidor não suporta versões inferiores ao TLS1.2.
Este problema de handshake recebido:
Com a versão 1.2, estava funcionando bem:
O servidor estava executando um Weblogic e a inclusão desse argumento no setEnvDomain.sh fez com que ele funcionasse com o TLSv1.1:
Este problema está ocorrendo devido à versão java. Eu estava usando o JDK 1.8.0.231 e recebendo esse erro. Eu degradei minha versão java de 1.8.0.231 para 1.8.0.171, agora está funcionando bem.