Skip to content

Instantly share code, notes, and snippets.

@trajber
Last active May 26, 2016 13:01
Show Gist options
  • Save trajber/7003d8198d4036feba8f8a83f7378ee3 to your computer and use it in GitHub Desktop.
Save trajber/7003d8198d4036feba8f8a83f7378ee3 to your computer and use it in GitHub Desktop.
Exemplo de como se conectar ao servidor EPP do Registro.br em Java

Este exemplo tem como objetivo mostrar como um cliente TLS usa um certificado de cliente e uma CA para conectar-se no servidor EPP do Registro.br. É um código exemplo apenas com fins didáticos. Foi usado o Java 8 e somente sua biblioteca padrão.

Os arquivos disponibilizados pelo Registro.br e usados neste exemplo podem ser encontrados em ftp://ftp.registro.br/pub/libepp-nicbr/test-certificates/

Em Java, um TrustManager gerencia as CAs e um KeyManager gerencia o certificado e a chave privada. Neste exemplo usamos estes mecanismos para facilitar a manipulação e validação dos certificados.

Como o Registro.br disponibiliza os certificados EPP no formato X.509, precisamos convertê-los para arquivos no formato KeyStore e TrustStore.

  1. Convertendo o certificado da raíz (CA) para um arquivo no formato TrustStore:
$ keytool -import -file root.pem -alias root -keystore root.truststore -storepass truststorepasswd

Um arquivo root.truststore será criado e está protegido com a senha truststorepasswd. Vale lembrar que o arquivo root.pem pode conter mais de um certificado raíz. Para manter este exemplo o mais simples possível estamos importando apenas o primeiro certificado.

2.1. O Registro.br disponibiliza o certificado do cliente e sua chave em um único arquivo. Precisamos separá-los:

Edite o arquivo client-pwd.pem e separe o conteúdo do certificado e da chave em dois arquivos diferentes: client-pwd.pem e client.key

2.2. A versão mais recente do keytool disponível atualmente não consegue importar uma chave privada no formato X.509. Para resolver este problema precisamos de um passo intermediário, converter o certificado do cliente e sua chave privada para o formato PKCS12.

$ openssl pkcs12 -export -in client-pwd.pem -inkey client.key -out client.p12 -name shepp -CAfile root.pem -caname root

Neste passo será requisitada uma senha para o novo arquivo PKCS12.

2.3. Agora podemos converter o PKCS12 para um KeyStore.

keytool -importkeystore -deststorepass keystorepasswd -destkeypass privkeypasswd -destkeystore client.keystore -srckeystore client.p12 -srcstoretype PKCS12 -srcstorepass <senha_usada_no_passo_anterior>

Neste passo um novo arquivo client.keystore será criado. Este arquivo está protegido com a senha keystorepasswd e contém o certificado do cliente e a chave privada do cliente - que está protegida pela senha privkeypasswd.

2.4. Temos dois arquivos: root.truststore e client.keystore. O código a seguir espera que estes arquivos estejam no pacote 'certs'.

package core;

import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.SecureRandom;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManagerFactory;
import javax.security.cert.X509Certificate;

public class Main {
	
	// pra deixar o código mais simples estamos ignorando as exceções
	public static void main(String[] args) throws Exception {
		char[] trustStorePassword = "truststorepasswd".toCharArray();
		char[] keyStorePassword = "keystorepasswd".toCharArray();
		char[] privateKeyPassword = "privkeypasswd".toCharArray();
		
		// Supondo que os certificados estão no pacote "certs".
		InputStream inputStream = 
		   ClassLoader.getSystemClassLoader().getResourceAsStream("certs/client.keystore");
		
		KeyStore keyStore = KeyStore.getInstance("JKS");
		keyStore.load(inputStream, keyStorePassword);
		
		KeyManagerFactory keyManagerFactory = 
		   KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
		keyManagerFactory.init(keyStore, privateKeyPassword);
	
		inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream("certs/root.truststore");
		keyStore.load(inputStream, trustStorePassword);
		
		TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
        tmf.init(keyStore);
        
        SSLContext context = SSLContext.getInstance("TLS");
        context.init(keyManagerFactory.getKeyManagers(), tmf.getTrustManagers(), new SecureRandom());
        
        SSLSocketFactory sslsocketfactory = context.getSocketFactory();
        SSLSocket socket = (SSLSocket) sslsocketfactory.createSocket("beta.registro.br", 700);
        
        // para debug da cadeia de certificados do servidor
        X509Certificate chain[] = socket.getSession().getPeerCertificateChain(); 
        for (int i = 0; i < chain.length; i++) { 
        	System.out.println("peer-certificate " + i); 
        	System.out.println(" Subject : " + chain[i].getSubjectDN().getName()); 
        	System.out.println(" Issuer  : " + chain[i].getIssuerDN().getName());
        	System.out.println(" Not Before  : " + chain[i].getNotBefore());
        	System.out.println(" Not After  : " + chain[i].getNotAfter());
        } 
        
        DataInputStream input = new DataInputStream(socket.getInputStream());
        
        int len = input.readInt();
        if (len <= 4 || len > 1024) {
        	throw new IOException("invalid response length");
        }
        
        len -= 4;
        byte[] bytes = new byte[len];
        input.readFully(bytes,0,len);
        
        // aqui temos o XML da resposta que veio do servidor
        String text = new String(bytes, "UTF-8");
        System.out.println(text);
	}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment