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=all
sinalizador para ativar a depuração da conexão SSL estabelecida. Com a depuração ativada, você pode identificar qual atividade do handshake falhou.
Atualizar
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 cacerts
arquivo 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 Merchant
turma 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:
keyStore is :
keyStore type is : jks
keyStore provider is :
init keystore
init keymanager of type SunX509
trustStore is: C:\Java\jdk1.6.0_21\jre\lib\security\cacerts
trustStore type is : jks
trustStore provider is :
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:
adding as trusted cert:
Subject: CN=blah, O=blah, C=blah
Issuer: CN=biggerblah, O=biggerblah, C=biggerblah
Algorithm: RSA; Serial number: yadda
Valid from SomeDate until SomeDate
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.
1. ClientHello
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:
*** ClientHello, TLSv1
RandomCookie: GMT: 1291302508 bytes = { some byte array }
Session ID: {}
Cipher Suites: [SSL_RSA_WITH_RC4_128_MD5, SSL_RSA_WITH_RC4_128_SHA, TLS_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, TLS_DHE_DSS_WITH_AES_128_CBC_SHA, SSL_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA, SSL_DHE_DSS_WITH_3DES_EDE_CBC_SHA, SSL_RSA_WITH_DES_CBC_SHA, SSL_DHE_RSA_WITH_DES_CBC_SHA, SSL_DHE_DSS_WITH_DES_CBC_SHA, SSL_RSA_EXPORT_WITH_RC4_40_MD5, SSL_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA, SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA]
Compression Methods: { 0 }
***
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.
2. ServerHello
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:
*** ServerHello, TLSv1
RandomCookie: GMT: 1291302499 bytes = { some byte array}
Cipher Suite: SSL_RSA_WITH_RC4_128_SHA
Compression Method: 0
***
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:
*** Certificate chain
chain [0] = [
[
Version: V3
Subject: CN=server, O=server's org, L=server's location, ST =Server's state, C=Server's country
Signature Algorithm: SHA1withRSA, OID = some identifer
.... the rest of the certificate
***
Se a verificação do certificado for bem-sucedida, você encontrará uma entrada semelhante a:
Found trusted certificate:
[
[
Version: V1
Subject: OU=Server's CA, O="Server's CA's company name", C=CA's country
Signature Algorithm: SHA1withRSA, OID = some identifier
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).