Quando faço uma conexão SSL com alguns servidores IRC (mas não outros - provavelmente devido ao método de criptografia preferido do servidor), recebo a seguinte exceção:
Caused by: java.lang.RuntimeException: Could not generate DH keypair
at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:106)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverKeyExchange(ClientHandshaker.java:556)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:183)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:593)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:529)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:893)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1138)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:1165)
... 3 more
Causa final:
Caused by: java.security.InvalidAlgorithmParameterException: Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive)
at com.sun.crypto.provider.DHKeyPairGenerator.initialize(DashoA13*..)
at java.security.KeyPairGenerator$Delegate.initialize(KeyPairGenerator.java:627)
at com.sun.net.ssl.internal.ssl.DHCrypt.<init>(DHCrypt.java:100)
... 10 more
Um exemplo de servidor que demonstra esse problema é a abertura.esper.net:6697 (este é um servidor IRC). Um exemplo de servidor que não demonstra o problema é kornbluth.freenode.net:6697. [Não é de surpreender que todos os servidores em cada rede compartilhem o mesmo comportamento respectivo.]
Meu código (que conforme observado funciona quando se conecta a alguns servidores SSL) é:
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new SecureRandom());
s = (SSLSocket)sslContext.getSocketFactory().createSocket();
s.connect(new InetSocketAddress(host, port), timeout);
s.setSoTimeout(0);
((SSLSocket)s).startHandshake();
É esse último startHandshake que lança a exceção. E sim, há alguma mágica acontecendo com o 'trustAllCerts'; esse código força o sistema SSL a não validar certs. (Então ... não é um problema de certificação.)
Obviamente, uma possibilidade é que o servidor do esper esteja configurado incorretamente, mas eu procurei e não encontrei outras referências a pessoas com problemas nas portas SSL do esper, e o 'openssl' se conecta a ele (veja abaixo). Então, eu estou querendo saber se isso é uma limitação do suporte SSL Java padrão, ou algo assim. Alguma sugestão?
Aqui está o que acontece quando eu me conecto ao aperture.esper.net 6697 usando 'openssl' na linha de comando:
~ $ openssl s_client -connect aperture.esper.net:6697
CONNECTED(00000003)
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
verify error:num=18:self signed certificate
verify return:1
depth=0 /C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
verify return:1
---
Certificate chain
0 s:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
i:/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
---
Server certificate
-----BEGIN CERTIFICATE-----
[There was a certificate here, but I deleted it to save space]
-----END CERTIFICATE-----
subject=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
issuer=/C=GB/ST=England/L=London/O=EsperNet/OU=aperture.esper.net/CN=*.esper.net/emailAddress=support@esper.net
---
No client certificate CA names sent
---
SSL handshake has read 2178 bytes and written 468 bytes
---
New, TLSv1/SSLv3, Cipher is DHE-RSA-AES256-SHA
Server public key is 2048 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
SSL-Session:
Protocol : TLSv1
Cipher : DHE-RSA-AES256-SHA
Session-ID: 51F1D40A1B044700365D3BD1C61ABC745FB0C347A334E1410946DCB5EFE37AFD
Session-ID-ctx:
Master-Key: DF8194F6A60B073E049C87284856B5561476315145B55E35811028C4D97F77696F676DB019BB6E271E9965F289A99083
Key-Arg : None
Start Time: 1311801833
Timeout : 300 (sec)
Verify return code: 18 (self signed certificate)
---
Como observado, depois de tudo isso, ele se conecta com êxito, o que é mais do que você pode dizer para o meu aplicativo Java.
Caso seja relevante, estou usando o OS X 10.6.8, versão Java 1.6.0_26.
opensslsaída na pergunta: "A cifra é DHE-RSA-AES256-SHA, a chave pública do servidor é de 2048 bits". E 2048> 1024 :-).
Server public key (size)foi e é a chave do certificado. s_clientem 2011 não mostrou chave efêmera; 1.0.2 em 2015 e acima faz Server Temp Keyvárias linhas mais altas. Embora um bom servidor geralmente deva ter o tamanho DHE igual ao tamanho da autenticação RSA.
Prime size must be multiple of 64, and can only range from 512 to 1024 (inclusive). Não faço ideia de qual tamanho foi enviado pelo servidor aqui e o que a especificação diz sobre isso.