Problemas com certificados de uma socket SSL

0 respostas
S

Saudações programadores. :)

Devido a motivos academicos , eu tenho de desnvolver um programa em java que use sockets SSL. Como so conhecia essa materia na pratica eu invetiguei na internet como usar as sockets SSL em java. De inicio eu copiei alguns codigos de net para testar o funcionamento dessas sockets, no entanto para pelo o que eu li nos sites que investiguei , para que as sockets SSL funcionem é necessario usar certificados.

Mais uma vez voltei a investigar na internet como é que poderia criar um certificado , nessa pesquisa eu encontrei varios sites , no entanto para gerar um certificado eu usei o seguinte site.

[url]http://pedro-costa.wikidot.com/keytool

Seguindo as intrucoes deste site eu usei o programa keytool para gerar um certificado.Em seguida usando os sites que encontrei nas minhas investigações eu criei o seguinte codigo.

O objectivo destes programas é ter uma aplicacao cliente - servidor que use as sockets SSL. De um lado o cliente vai enviar uma mensagem "ola Mundo" e do outro lado o servidor vai ler essa mensagem , e vai imprimi-la no ecra. A aplicacao Cliente e a aplicacao Servidor usam certificados diferentes.

Aqui esta o codigo do cliente.

package socket_seguro_cliente;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.KeyStore;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;


public class Main {

      public static SSLSocket createSSLContext() throws Exception
    {

          KeyStore ks =  Utils.getKeyStore("JKS");
          ks.load(new FileInputStream("c:\\cliente.jks"), "servidor".toCharArray());

          KeyManagerFactory kmf = Utils.getKMFactory("SunX509");
          kmf.init(ks, "servidor".toCharArray());

          SSLContext sslcontext = Utils.criaSSLContext("SSLv3");
          sslcontext.init(kmf.getKeyManagers(), null, null);

          SSLSocketFactory ssf = sslcontext.getSocketFactory();
          SSLSocket socket = (SSLSocket) ssf.createSocket("localhost",9999);

          socket.setEnabledCipherSuites(socket.getEnabledCipherSuites());

          return socket;

    }


    public static void main(String[] args) throws IOException, Exception {

//            System.setProperty("javax.net.ssl.keyStore", "c:\\servidor.jks");
//            System.setProperty("javax.net.ssl.keyStorePassword", "servidor");

           SSLSocket socket;
           ObjectInputStream dataInput;
           ObjectOutputStream dataOutput;

            System.out.println("Bem vindo ao Cliente\n");

            System.out.println("A estabelecer conexoes\n\n");

            socket = createSSLContext();
            

//          socket.startHandshake();

            dataInput = new ObjectInputStream(socket.getInputStream());
            dataOutput = new ObjectOutputStream(socket.getOutputStream());

            System.out.println("A enviar mensagens\n\n");

            dataOutput.writeUTF("ola mundo");
            dataOutput.flush();

            System.out.println("Mensagem enviada\n\n");

    }

}

Aqui esta o codigo do servidor
package socket_seguro_servidor;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;

import java.net.Socket;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.cert.CertificateException;
import javax.net.ServerSocketFactory;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.SSLSessionContext;

public class Main {

public static void showPropSSLContext(SSLContext contextoSSL){

System.out.println("-------Informaçoes de contexto SSL-------");

String protocol = contextoSSL.getProtocol();
System.out.println("Protocolo : "+protocol);

Provider provider = contextoSSL.getProvider();
System.out.println("Nome do provedor : "+provider.getName());
System.out.println("Versao do provedor : "+provider.getVersion());
SSLSessionContext sslsessioncontext = contextoSSL.getServerSessionContext();

}

public static ServerSocket criaSSLServerSocket() throws Exception{

KeyStore ks = Utils.getKeyStore("JKS");
ks.load(new FileInputStream("c:\\servidor.jks"), "servidor".toCharArray());

KeyManagerFactory kmf = Utils.getKMFactory("SunX509");
kmf.init(ks, "servidor".toCharArray());

SSLContext contextoSSL = Utils.criaSSLContext("SSLv3");
contextoSSL.init(kmf.getKeyManagers(), null, null);

showPropSSLContext(contextoSSL);

ServerSocketFactory ssf = contextoSSL.getServerSocketFactory();
SSLServerSocket servidorSSL = (SSLServerSocket) ssf.createServerSocket(9999);
//Se necessário, autentica o cliente

servidorSSL.setEnabledCipherSuites(servidorSSL.getSupportedCipherSuites());

servidorSSL.setNeedClientAuth(false);

return servidorSSL;
}

public static void main(String[] args) throws IOException, KeyStoreException, NoSuchAlgorithmException, CertificateException, Exception {

// System.setProperty("javax.net.ssl.keyStore", "c:\\servidor.jks");
// System.setProperty("javax.net.ssl.keyStorePassword", "servidor");

ObjectInputStream dataInput;
ObjectOutputStream dataOutput;

System.out.println("Bem vindo ao servidor\n\n");

System.out.println("A estabelecer conexoes\n\n");

ServerSocket servidorSSL = criaSSLServerSocket();

// sSock.

Socket socket = servidorSSL.accept();

dataOutput = new ObjectOutputStream(socket.getOutputStream());
dataInput = new ObjectInputStream(socket.getInputStream());

System.out.println("A receber mensagens\n\n");

String pedido = dataInput.readUTF();

System.out.println("Recebi isto -> " + pedido + "\n\n");

System.out.println("Mensagem recebida\n\n");
}

}

E aqui esta a classe util que ambos os programas usam.

package socket_seguro_servidor;

import javax.net.ssl.*;
import java.security.*;

public class Utils{

 protected static KeyStore getKeyStore(String tipo) throws KeyStoreException{

   //utiliza a implementação do keystore provido pela Sun
   return KeyStore.getInstance(tipo);

 }

 protected static KeyManagerFactory getKMFactory(String algoritmo) throws NoSuchAlgorithmException{

  //cria um caminho de certificação baseado em X509
  return KeyManagerFactory.getInstance(algoritmo);

 }

 protected static SSLContext criaSSLContext(String protocolo) throws NoSuchAlgorithmException{

 //cria um SSLContext segundo o protocolo informado
  return SSLContext.getInstance(protocolo);

 }

}

No entanto ao executar estes codigos eu obtives as seguintes execpcoes. 

No servidor eu obtive isto.
Bem vindo ao servidor

A estabelecer conexoes

-------Informaçoes de contexto SSL-------
Protocolo : SSLv3
Nome do provedor : SunJSSE
Versao do provedor : 1.6
Exception in thread "main" javax.net.ssl.SSLHandshakeException: Received fatal alert: certificate_unknown
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:136)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1682)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:932)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1112)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:623)
at com.sun.net.ssl.internal.ssl.AppOutputStream.write(AppOutputStream.java:59)
at java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1838)
at java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1747)
at java.io.ObjectOutputStream.(ObjectOutputStream.java:226)
at socket_seguro_servidor.Main.main(Main.java:85)

E no cliente eu obtive isto

[code]Bem vindo ao Cliente

A estabelecer conexoes

Exception in thread "main" javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at com.sun.net.ssl.internal.ssl.Alerts.getSSLException(Alerts.java:174)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1611)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:187)
at com.sun.net.ssl.internal.ssl.Handshaker.fatalSE(Handshaker.java:181)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1035)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:124)
at com.sun.net.ssl.internal.ssl.Handshaker.processLoop(Handshaker.java:516)
at com.sun.net.ssl.internal.ssl.Handshaker.process_record(Handshaker.java:454)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:884)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1112)
at com.sun.net.ssl.internal.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:744)
at com.sun.net.ssl.internal.ssl.AppInputStream.read(AppInputStream.java:75)
at java.io.ObjectInputStream$PeekInputStream.read(ObjectInputStream.java:2266)
at java.io.ObjectInputStream$PeekInputStream.readFully(ObjectInputStream.java:2279)
at java.io.ObjectInputStream$BlockDataInputStream.readShort(ObjectInputStream.java:2750)
at java.io.ObjectInputStream.readStreamHeader(ObjectInputStream.java:780)
at java.io.ObjectInputStream.(ObjectInputStream.java:280)
at socket_seguro_cliente.Main.main(Main.java:56)
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:285)
at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:191)
at sun.security.validator.Validator.validate(Validator.java:218)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:126)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:209)
at com.sun.net.ssl.internal.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:249)
at com.sun.net.ssl.internal.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1014)
... 13 more
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:174)
at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:238)
at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:280)
... 19 more

Eu tentei investigar na internet porque é que estes erros ocorrem no entanto nao consegui encontrar resposta. Ja tentei gerar varias vezes os certificados mas o mesmo erro continua. Por favor se alguem encontrou algum erro parecido , por favor , diga.me como devo proceder. ja investiguei na net , ja testei todas as solucoes que me vieram a cabeça e mesmo assim nada.

Muito obrigado e boa sorte.

Criado 11 de julho de 2010
Respostas 0
Participantes 1