forked from kivanio/brcobranca_exemplo
-
Notifications
You must be signed in to change notification settings - Fork 0
Aplicação de exemplo do uso do http://github.com/kivanio/brcobranca
rodrigosol/brcobranca_exemplo
Folders and files
Name | Name | Last commit message | Last commit date | |
---|---|---|---|---|
Repository files navigation
##Introdução ## SDK-SBIS O SDK-SBIS é uma biblioteca de software que trata dos aspectos de certificação digital do SBIS. Essa biblioteca permite a assinatura de documentos no padrão do ICP-Brasil, bem como a extração de dados do certificado para propósito de autenticação e autorização. ##Conceitos A seguir são descritos os principais conceitos relacionados. #### Certificação Digital A _Certificação Digital_ é uma tecnologia que provê mecanismos de segurança capazes de garantir autenticidade, confidencialidade e integridade às informações eletrônicas tramitadas entre cidadãos, governo e empresas através da troca de mensagens e documentos através da internet. #### Certificado O _Certificado Digital_ é uma assinatura com validade jurídica que garante proteção às transações eletrônicas e outros serviços via internet, permitindo que pessoas e empresas se identifiquem e assinem digitalmente de qualquer lugar do mundo com mais segurança e agilidade. [1] ##### Tipos de Certificado Os Certificados ICP-Brasil são classificados quanto à sua aplicabilidade e quanto aos requisitos de segurança de proteção da chave privativa. Quanto à sua aplicabilidade, os certificados ICP-Brasil são classificados pelos tipos: ######Tipo A - Certificado de Assinatura Digital Os certificados do tipo A são os certificados digitais utilizados para a <strong>assinatura de documentos</strong>, <strong>transações eletrônicas</strong>, entre outros, tendo como meta provar a autenticidade e a autoria por parte do emissor, garantindo também, a integridade do documento. ######Tipo S - Certificado de Sigilo/Confidencialidade Os certificados do tipo S são utilizados somente para proporcionar <strong>sigilo</strong> ou <strong>criptografia de dados</strong>. São os certificados digitais utilizados para o envio e/ou armazenamento destes documentos </strong>sem expor o seu conteúdo</strong>. ######Tipo T - Certificado de Tempo Também conhecido como <strong>time-stamping</strong>, é o serviço de certificação do <strong>dia</strong> e da <strong>hora</strong> em que foi assinado um documento eletrônico, com identidade do emissor. #### Assinatura Digital A assinatura digital consiste na criação de um código, através da utilização de uma chave privada, de modo que a pessoa ou entidade que receber uma mensagem contendo este código possa verificar se o remetente é mesmo quem diz ser e identificar qualquer mensagem que possa ter sido modificada. A técnica de assinatura digital é uma forma eficaz de garantir a autoria de documentos eletrônicos. Em agosto de 2001, a Medida Provisória 2.200-2 de 24 de agosto do mesmo ano garantiu a validade jurídica de documentos eletrônicos e a utilização de certificados digitais para atribuir autenticidade e integridade aos documentos. Este fato tornou a assinatura digital um instrumento válido juridicamente. #### Alias Alias é o identificador único de um certificado. O SDK lista todos os certificados disponíveis no computador (token, browser, arquivos, etc.) e o acesso a um certificado específico é realizado pelo Alias. #### Cadeia de Certificados É a cadeia de certificados dos emissores de um determinado certificado. A cadeia é usada para verificar a revogação do certificado. #### Campos do ICP-Brasil São os campos que contém dados padronizados pelo ICP-Brasil, tais como Nome, CPF/CNPJ, CRM, etc. ###Core Services O SDK é divido em camadas. A camada *Core Services* provê infraestrutura básica para acesso ao certificado e seus dados. O *Core Service* pode ser acessado pela interface fluente disponível no SDK. ####Fluent Interface É um conjunto de interfaces que permite o acesso direcionado aos recursos de um certificado. ##Instalação A seguir são detalhados os passos necessários para a Instalação do SDK. ####Requisitos - Java 1.7 ou superior - Maven 3 instalado no computador - Garanta que a variável de ambiente JAVA_HOME está configurada corretamente e apontando para a instalação do JAVA. Para utilizar o SDK em seu projeto siga os passos abaixo: - Clone o repositório git - Altere a chave de criptografia do jar no arquivo pom.xml para a chave da sua empresa ```xml <configuration> <keystore>minha_chave.jks</keystore> <alias>meu_alias</alias> <storepass>minha_storepass</storepass> <keypass>minha_keypass</keypass> </configuration> ``` - Execute o comando _mvn clean install -Dmaven.test.skip=true_ para compilar o projeto - O arquivo compilado estará disponível no diretório _target_ ####Obtendo uma instancia do SDK Para obter uma instância do SDK é necessário utilizar o método _get_ da classe _SDKService_: ```java SDKService.get() ``` ####Trabalhando com certificados A1 Para obter dados de um certificado do tipo A1 é necessário informar a localização física do arquivo: ```java SDKService.get().certificate(new File("caminho/certificado.p12")) ``` ####Trabalhando com certificados A3 Para obter dados de um certificado do tipo A3 basta não informar nenhum parâmetro no método *certificate* ```java SDKService.get().certificate() ``` ####Informando o PIN do certificando Para acessar a chave privada do certificado é necessário utilizar o método *credentials*: ```java SDKService.get().certificate().credentials('PINdoCertificado') ``` ####Ações disponíveis Após o SDK ter sido instanciado, a interface fornece diversas ações que podem ser executadas. ##### Listar Certificados ##### Obter informações de um determinado certificado Para obter as informações armazenadas no certificado do padrão ICP-Brasil a ação _userInfo_ deve ser utilizada. ```java ICPBrasilCertificate certificate = ICPBrasilSDKService.get().certificate().credentials("segredo").userInfo("alias"); System.out.println("Nome:" + certificate.getNome()); ``` #### Obter informações de um determinado certificado criptografadas O método *getEncryptedInfo* fornece todos os campos do ICP-Brasil em um JSON previamente criptografado com o algoritmo AES-128. ```java String dados = ICPBrasilSDKService.get().certificate().credentials("segredo").getEncryptedInfo("alias","chave"); System.out.println("Dados:" + dados); ``` #### Obter a chave privada O método *getPrivateKey* fornece a chave privada do certificado. ```java privateKey = ICPBrasilSDKService.get().certificate().credentials("segredo").getPrivateKey("alias"); ``` #### Obter a chave pública O método *getPublicKey* fornece a chave pública do certificado. ```java publicKey = ICPBrasilSDKService.get().certificate().credentials("segredo").getPublicKey("alias"); ``` #### Obter a cadeia de certificados O método *getCertificateChain* fornece a cadeia de certificados de um dado certificado. ```java certificates = ICPBrasilSDKService.get().certificate().credentials("segredo").getCertificateChain("alias"); ``` #### Obter o certificado no padrão X509 O método *getCertificate* fornece o certificado no padrão X509. ```java certificate = ICPBrasilSDKService.get().certificate().credentials("segredo").getCertificate("alias"); ``` #### Assinar digitalmente um conteúdo Para assinar digitalmente um conteúdo, basta utilizar a ação *sign* ```java signed = ICPBrasilSDKService.get().certificate().credentials("segredo").sign(alias, content, attached); ``` O parâmetro attached informa se o conteúdo original deve ser anexado na assinatura. ##### Validar assinatura Para validar um assinatura utiliza-se o metodo *validate*, informando o conteudo original e o conteudo da assinatura: ```java valid = ICPBrasilSDKService.validate(content,signed); ``` ##### Validar certificado Para validar um certificado utiliza-se o metodo *validate* ```java ICPBrasilSDKService.get().certificate().credentials("segredo").validate(alias); ``` ###Applets O SDK oferece dois Applets genéricos (login e assinador) que podem ser utilizados para automação do uso do SDK em projetos de arquitetura WEB. #### Login O Applet de login permite que um usuário escolha um certificado em uma lista. Quando o certificado é escolhido, o applet extrai os dados no padrão ICP-Brasil, converte-os para JSON e realiza a criptografia assimétrica. O retorno é uma string com os dados criptografadas que é inserida automaticamente em um campo do formulário HTML, enviado como parâmetro para o applet. ##### Parâmetros do Applet | Parâmetro | Descrição | | ---------------------- | ------------------------------------------------------------- | | sdk.saude.login.form | Campo name do formulário que a string será retornada | | sdk.saude.login.token | Campo name do campo do formulário que a string será retornada | ##### Exemplo ###### Lado Cliente No cliente é necessário importar o arquivo .jar do SDK utilizando a tag html applet, conforme exemplo abaixo: ```html <html> <head> <meta charset="UTF-8"> </head> <body> <h2>Exemplo de Login</h2> <applet codebase="http://localhost:8080/sample-login/" code="sebrae.com.br.saude.applets.LoginApplet" width=470 height=350 MAYSCRIPT archive="sdk.jar,plugin.jar"> <param name="sdk.saude.login.form" value="form"/> <param name="sdk.saude.login.token" value="token"/> </applet> <br> <p>Ao clicar em executar, os dados do certificado serão inseridos no campo de texto abaixo.<p> <form name="form" action="login.jsp"> <input type="text" size="100" name="token"> <input type="submit" value="Enviar dados para o servidor"> </form> </body> </html> ``` O atributo *codebase* define onde o arquivo .jar contendo o SDK está armazenado no servidor. O atributo *sdk.saude.login.form* informa ao applet para retornar o valor para um campo dentro do formulário chamado *form*. O atributo *sdk.saude.login.token* informa ao applet para retornar o valor para o campo chamado *token* dentro do formulário chamdo *form*. Ao clicar na ação executar do applet, se tudo correr bem, o campo token será preenchido com uma string representando os dados obtidos do certificado escolhido pelo usuário. Dica: > Utilize um campo do tipo hidden e faça um javascript que submeta o formulário de login automaticamente quando o valor for preenchido. ###### Lado Servidor No lado servidor é necessário criar uma rotina que receba como parâmetro a string enviada pelo cliente e aplique o algorítmo AES-128 para realizar a descriptografia dos dados. Abaixo é apresentado um exemplo em java que realiza tal tarefa: ```jsp <%@ page import="sebrae.com.br.saude.utils.*" %> <html> <head> <meta charset="UTF-8"> </head> <body> <h2>Dados do certificado</h2> <pre> <%= CipherUtil.decrypt(request.getParameter("token"),"ThisIsASecretKey") %> </pre> </body> </html> ``` Para projetos em java, basta utilizar a classe CipherUtil do próprio SDK para realizar a descriptografia dos dados. Para projetos em outras liguagens os seguintes procedimentos são necessários: - Obtenha a string enviada para o servidor; - Utilize um algoritmo AES-128 padrão do ambiente; - Use como chave a mesma utilizada na criptografia. Abaixo é apresentado um exemplo em Ruby: ```ruby require 'openssl' module AESCrypt def AESCrypt.decrypt(encrypted_data, key, iv, cipher_type) aes = OpenSSL::Cipher::Cipher.new(cipher_type) aes.decrypt aes.key = key aes.iv = iv if iv != nil aes.update(encrypted_data) + aes.final end end class LoginController < Landpage::LandpageController def new key = "ThisIsSecret".scan(/../).inject(""){|binary,hn| binary << hn.to_i(16).chr} text = params[:token].scan(/../).inject(""){|binary,hn| binary << hn.to_i(16).chr} decoded = AESCrypt.decrypt(text,key,nil,"AES-128-ECB") hash = JSON.parse(decoded) puts hash end end ``` #### Assinador O Applet de assinatura permite fornecer infraestrutura completa para assinatura de documentos. O Applet funciona com a seguinte lógica: - Parâmetros são informados ao applet com informações de quais documentos serão assinados; - O applet faz o download dos documentos a serem assinados; - O applet assina os documentos com o certificado escolhido; - O applet envia os documentos assinados para o servidor. ##### Parâmetros do Applet | Parâmetro | Descrição | | ---------------------------------------- | ------------------------------------------------------------- | | sdk.assinador.upload_url | Url que será utilizada para o envio dos documentos assinados | | sdk.assinador.numero_documentos | Número de documentos que serão assinados | | sdk.assinador.autocontido | true para anexar o documento na assinatura | | sdk.assinador.documento.X.download_url | Url para download do documento de índice X | | sdk.assinador.documento.X.nome | Nome do documento de índice X | | sdk.assinador.documento.X.tamanho | Tamanho em bytes do documento de índice X | | email | Adiciona o cabeçalho X-Usuario-Email para autenticação | | token | Adiciona o cabeçalho X-Usuario-Token para autenticação | | authenticity_token | Adiciona o parâmetro authenticity_token na requisição | ##### Exemplo ###### Lado Cliente No cliente é necessário importar o arquivo .jar do SDK utilizando a tag html applet, conforme exemplo abaixo: ```html <html> <head> <meta charset="UTF-8"> </head> <body> <h2>Exemplo de Assinatura</h2> <applet codebase="http://localhost:8080/sample-login/" code="sebrae.com.br.saude.applets.AssinadorApplet" width=470 height=350 MAYSCRIPT archive="sdk.jar,plugin.jar"> <param name="sdk.assinador.upload_url" value="http://localhost:8080/sample-login/upload"/> <param name="sdk.assinador.numero_documentos" value="2"/> <param name="sdk.assinador.autocontido" value="false"/> <param name="sdk.assinador.documento.0.nome" value="logo.png"/> <param name="sdk.assinador.documento.0.download_url" value="http://localhost:8080/sample-login/logo.png"/> <param name="sdk.assinador.documento.0.tamanho" value="25385"/> <param name="sdk.assinador.documento.1.nome" value="sdk.jar"/> <param name="sdk.assinador.documento.1.download_url" value="http://localhost:8080/sample-login/sdk.jar"/> <param name="sdk.assinador.documento.1.tamanho" value="7019262"/> </applet> <br> <p>Ao clicar em executar os arquivos serão baixados, assinados e enviados para a URL de upload informada.<p> </body> </html> ``` Ao clicar em executar os arquivos *logo.png* e *sdk.jar* serão baixados, assinados e enviados para a URL de upload informada ###### Lado Servidor No lado servidor é necessário apenas somente receber os arquivos. Abaixo é apresentado um exemplo em Java: ```java import java.io.*; import java.util.*; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileUploadException; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.apache.commons.io.output.*; public class UploadServlet extends HttpServlet { private boolean isMultipart; private String filePath; private int maxFileSize = 50 * 1024; private int maxMemSize = 4 * 1024; public void init( ){ filePath = getServletContext().getInitParameter("file-upload"); } public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { System.out.println("Requisicao recebida!"); isMultipart = ServletFileUpload.isMultipartContent(request); System.out.println(isMultipart); response.setContentType("text/html"); java.io.PrintWriter out = response.getWriter( ); if( !isMultipart ){ out.println("<html>"); out.println("<head>"); out.println("<title>Servlet upload</title>"); out.println("</head>"); out.println("<body>"); out.println("<p>No file uploaded</p>"); out.println("</body>"); out.println("</html>"); return; } DiskFileItemFactory factory = new DiskFileItemFactory(); factory.setSizeThreshold(maxMemSize); factory.setRepository(new File("/tmp")); ServletFileUpload upload = new ServletFileUpload(factory); upload.setSizeMax( maxFileSize ); try{ List fileItems = upload.parseRequest(request); System.out.println("Numero de arquivos recebidos:" + fileItems.size()); Iterator i = fileItems.iterator(); out.println("<html>"); out.println("<head>"); out.println("<title>Servlet upload</title>"); out.println("</head>"); out.println("<body>"); while ( i.hasNext () ) { FileItem fi = (FileItem)i.next(); String fieldName = fi.getFieldName(); String fileName = fi.getName(); String contentType = fi.getContentType(); boolean isInMemory = fi.isInMemory(); long sizeInBytes = fi.getSize(); System.out.println("FieldName:" + fieldName); System.out.println("fileName:" + fileName); System.out.println("contentType:" + contentType); System.out.println("isInMemory:" + isInMemory); System.out.println("sizeInBytes:" + sizeInBytes); fi.write( new File("/tmp/" + fieldName)) ; out.println("Uploaded Filename: " + fileName + "<br>"); } out.println("</body>"); out.println("</html>"); }catch(Exception ex) { ex.printStackTrace(); } } public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, java.io.IOException { throw new ServletException("GET method used with " + getClass( ).getName( )+": POST method required."); } } ``` #### Selecionando automaticamente o certificado Caso queria pular a etapa de seleção do certificado em quaisquer applets, basta informar os seguintes parâmetros: ##### Parâmetros do Applet | Parâmetro | Descrição | | ---------------------------------------- | ------------------------------------------------------------- | | sdk.saude.certificate.alias | alias do certificado a ser selecionado | | sdk.saude.certificate.type | Tipo do certificado (A1 ou A3) | | sdk.saude.certificate.file | Caminho e nome do arquivo para certificados do tipo A1 | #### Enviando informações do Applet para o Browser A classe DOMUtils fornece metódos para realizar a comunicação de dentro do browser com a árvore DOM do browser. ```java public static void setFormFieldFromCommonAPI(final Applet applet, final String formName, final String fieldName, final String value) { String result = null; try { @SuppressWarnings("restriction") DOMService service = DOMService.getService(applet); service.invokeAndWait(new DOMAction() { public Object run(DOMAccessor accessor) { HTMLDocument doc = (HTMLDocument) accessor.getDocument(applet); HTMLCollection forms = doc.getForms(); HTMLFormElement form = (HTMLFormElement) forms.namedItem(formName); HTMLCollection elements = form.getElements(); int length = elements.getLength(); for (int i = 0; i < length; i++) { Node node = elements.item(i); if (node instanceof HTMLInputElement) { HTMLInputElement element = (HTMLInputElement) node; if (element.getName().equalsIgnoreCase(fieldName)) { element.setValue(value); } } } return ""; } }); } catch (DOMUnsupportedException e1) { result = e1.getMessage(); JOptionPane.showMessageDialog(null, result); } catch (DOMAccessException e2) { result = e2.getMessage(); JOptionPane.showMessageDialog(null, result); } } ``` ##### Parâmetros da Função | Parâmetro | Descrição | | ---------------------------------------- | ------------------------------------------------------------- | | final Applet applet | Applet que irá realizar a comunicação com o Browser | | final String formName | Atributo name do formulário que será manipulado pelo applet | | final String fieldName | Campo do formulário que será manupilado pelo applet | | final String value | Valor que será para o campo do formulário |
About
Aplicação de exemplo do uso do http://github.com/kivanio/brcobranca
Resources
Stars
Watchers
Forks
Packages 0
No packages published
Languages
- Ruby 41.7%
- CSS 35.3%
- HTML 22.6%
- Other 0.4%