Esse artigo faz parte da revista Java Magazine edição 22. Clique aqui para ler todos os artigos desta edição

Atenção: por essa edição ser muito antiga não há arquivo PDF para download.Os artigos dessa edição estão disponíveis somente através do formato HTML. 

A vida, o Universo e Tudo mais

Começando com Criptografia

Confidencialidade e Autenticidade de Informações

Conheça algoritmos e use APIs de criptografia e certificação digital na suas aplicações Java

Bruno Souza

Segurança é um item prioritário na maioria dos projetos, com firewalls e HTTPS figurando em quase todos os diagramas de arquitetura de rede desenhados. Mas é o típico conceito amplo que nunca deveria ser mencionado sem qualificação. Usar HTTPS é segurança, assim como é o verificador de bytecodes de Java, mas são tipos e objetivos tão distintos de segurança que fica difícil encaixá-los no mesmo item de projeto.

Dado que grande parte dos projetos em Java hoje são de ambiente web, é normal que a principal preocupação seja nos protocolos seguros para acesso à aplicação. O uso de HTTPS ("secure http", ou http via SSL) em aplicações web é em geral responsabilidade do servidor de aplicações, sendo basicamente transparente para o desenvolvedor. Da mesma forma, é transparente a proteção fornecida por um firewall.

E quando o projeto tem outros requisitos de segurança que precisam ser tratados pelo desenvolvedor? Se você está desenvolvendo uma aplicação desktop ou um servidor específico, ou se há requisitos de assinaturas digitais e certificação do cliente, quais bibliotecas Java você pode usar para garantir a segurança?

Esse artigo trata das tecnologias Java para lidar com certificados digitais, assinaturas eletrônicas e criptografia de mensagens. Como motivação, vamos analisar como essas tecnologias podem ser usadas para tirar proveito de uma legislação brasileira relativamente recente – que talvez seja a solução que você procurava para seu próximo projeto.

 

Nota: Gostaria de agradecer aos meus amigos no Serpro, em especial ao José Maurílio Dias e Evaldo Gomes, que estão usando o e-CPF em aplicações Java e me obrigando a ficar sempre por dentro dessas tecnologias.

e-CPF: assinatura real em documentos digitais

Com a promulgação da medida provisória 2.200-2, em vigor desde 2001, documentos eletrônicos passaram a ser equivalentes aos documentos em papel, possibilitando sua tramitação. Dessa forma, documentos eletrônicos são agora legalmente equivalentes e isonômicos aos documentos em papel. Isso significa que toda a legislação que se aplica aos documentos em papel vale, de forma idêntica, para os documentos digitais – desde que estes sejam certificados por uma entidade certificadora vinculada à Infra-Estrutura de Chaves Públicas Brasileira (ICP-Brasil). Diversos documentos oficiais do governo brasileiro já tramitam hoje certificados pela ICP-Brasil, e essa infra-estrutura, que já conta com diversas entidades certificadoras, está disponível para uso em suas aplicações.

A certificação é baseada no CPF Eletrônico (e-CPF) e no CNPJ Eletrônico (e-CNPJ), que podem ser requeridos por qualquer cidadão ou empresa no país. Ambos são certificados digitais, que podem ser protegidos por hardware (com smartcards) e permitem a qualquer cidadão confirmar legalmente sua identidade em transações eletrônicas. Em um projeto em andamento, o e-CPF está sendo usado para permitir que o usuário “assine” os documentos enviados ao governo, sendo reconhecido legalmente como se fosse sua assinatura propriamente dita.

Não seria interessante que seus usuários fossem autenticados em seus sistemas, não por uma senha num formulário web, mas por seu certificado nacional? E se esse certificado fosse armazenado em um smartcard, quem sabe até no cartão do telefone celular que eles carregam? Utilizando o e-CNPJ, aplicações podem trocar documentos eletrônicos oficiais entre empresas; e com o e-CPF clientes podem assinar contratos sem sair de casa ou recorrer a um cartório para reconhecimento de firma. Com a validade técnica e jurídica garantida por certificados digitais, é possível realizar transações que exigem assinaturas físicas, como firmar contratos de aluguel, empréstimos e procurações, entre outros.

Essas transações podem ser feitas com segurança, mesmo em ambientes não seguros, como quiosques em shoppings e máquinas Windows. Se você só conhecia certificados digitais associados aos servidores web, já pode ver que servem para muito mais: eles são parte importante de sistemas de segurança. Bem-vindo ao mundo da certificação digital!

JCA e JCE: tecnologias Java por trás dos certificados

Para entender os certificados digitais, precisamos conhecer alguns conceitos de criptografia que nos darão a base para desenvolver aplicações seguras. Faremos isso utilizando as bibliotecas Java para a manipulação das primitivas de criptografia e os certificados. Temos a Java Cryptography Architecture (JCA) e a Java Cryptography Extensions (JCE), além de outras bibliotecas importantes, como a que adiciona o suporte a SSL na plataforma Java, Java Secure Socket Extensions (JSSE), e a Java Certification Path API (CertPath), que trata da verificação de certificados.

A JCA fornece apenas a arquitetura básica. Assim como o JDBC oferece uma camada de abstração que permite "plugar" diversos drivers de banco de dados, a JCA traz as interfaces e objetos fundamentais de criptografia. Permite também a utilização de diferentes providers, que farão o trabalho de criptografia propriamente dito. Dessa forma, o desenvolvedor, ou mesmo o administrador da aplicação, tem a opção de escolher as implementações dos algoritmos de criptografia que melhor atenda às suas necessidades de segurança.

Mas é a JCE que contém as implementações dos algoritmos de criptografia propriamente ditos. Cada funcionalidade de criptografia é realizada por algoritmos com cálculos matemáticos sofisticados. A literatura especializada descreve um grande número desses algoritmos, que atendem às mais diversas necessidades de desempenho e segurança.

A arquitetura de providers de Java possibilita que cada fornecedor inclua no seu produto os algoritmos que considerar mais importantes. Nesse artigo utilizamos alguns algoritmos mais comuns, que estão presentes tanto no provider padrão da Sun, o SunJCE, quanto nos incluídos em outras JVMs como a da IBM, e mesmo em providers open source como o BouncyCastle. Dessa forma você poderá executar os exemplos na maioria das JVMs existentes. Caso você queira fazer experiências com outros algoritmos, o JDK 1.4.2 da IBM inclui uma extensa lista, provavelmente a mais completa entre as JVMs.

Assim como não se faz nada apenas com o JDBC, sendo necessário ao menos um driver, é preciso pelo menos uma implementação da JCE para fazer funcionar uma aplicação que utilize criptografia via JCA. Felizmente já faz parte da JVM uma implementação padrão da JCE, e que pode ser trocada ou expandida com a instalação de outros providers. Para demonstrar conceitos de criptografia, vamos utilizar as implementações padrão da JVM.

 

Nota: Por questões de proibição de exportação de implementações de criptografia do governo dos Estados Unidos, o provider padrão, chamado “SunJCE”, só foi integrado ao JDK a partir da versão 1.4. Em versões anteriores era necessário baixar e instalar o provider da Sun como uma extensão à parte.

Criptografia

A criptografia é um ramo da ciência da computação (e da matemática aplicada) que pretende abordar um problema que nos acompanha historicamente: a troca de mensagens de forma segura. Desde os símbolos secretos utilizados pelos sacerdotes egípcios, à brincadeira da “língua do pê”, ao uso de índios Navajo pelos americanos na Segunda Guerra Mundial para ludibriar os Japoneses, estamos sempre buscando formas de disfarçar ou cifrar nossas mensagens.

Com os computadores passamos a poder fazer cálculos para transformar (“criptografar”) mensagens digitais em outras mensagens completamente irreconhecíveis – cifradas. Estas só podem ser abertas por aqueles que conhecem o segredo – a “chave” – para desfazer (“descriptografar”) essa cifragem.

Os algoritmos utilizados para criptografar e descriptografar realizam cálculos sofisticados baseados em alguns tipos de problemas matemáticos muito difíceis de resolver, mesmo com a velocidade atual dos computadores. Sairia do escopo desse artigo discutir os algoritmos em si, mas se você tem interesse em se aprofundar nesse fascinante ramo da computação, uma boa introdução é o livro “Handbook of Applied Cryptography”, disponível gratuitamente em PDF (veja links). O livro entra em detalhes sobre os principais algoritmos e a matemática por trás da criptografia.

MessageDigest

Para demonstrar o uso das APIs de criptografia vamos começar com um dos conceitos mais simples: o cálculo de um message digest criptográfico. Este cálculo visa transformar uma mensagem (conjunto de bytes) num resultado de tamanho fixo. O resultado, chamado de hash ou digest, tem as propriedades de ser muito difícil encontrar duas mensagens que gerem o mesmo hash, e que a partir do hash não deve ser possível descobrir a mensagem original. Dessa forma o hash serve para fornecer uma espécie de identificação única da mensagem.

Os algoritmos de hash mais famosos são o SHA1 e o MD5. O exemplo da Listagem 1 mostra como utilizá-los em Java; nele fazemos uso de alguns elementos comuns que veremos em toda a biblioteca. Os conceitos explicados aqui se aplicam para todos os outros exemplos.

O pacote java.security contém as chamadas “classes de serviço”, que constituem a API da JCA. Ao utilizar essas classes, sua aplicação tem acesso a todos os serviços de criptografia: message digests, assinaturas digitais, armazenamento de chaves etc. Mas a implementação desses serviços é feita pelos “Cryptography Service Providers” (CSP) ou, simplesmente, providers do JCE. Como os drivers JDBC, os providers JCE são conjuntos de classes, fornecidas pela Sun ou por terceiros, que implementam algoritmos de criptografia (veja nos links exemplos de providers open source e comerciais). ...

Quer ler esse conteúdo completo? Tenha acesso completo