Sessões laboratoriais de CA (2007/2008)


Aula 1 - Ambiente de Desenvolvimento

O objectivo principal desta aula é o de escolher/instalar o ambiente de desenvolvimento Java que será utilizado durante o curso.

Como actividade de programação (para experimentar o ambiente escolhido), deve desenvolver uma pequena aplicação que leia um ficheiro de texto (nome do ficheiro passado como argumento), e escreva para stdout o seu conteúdo com todas as letras maiúsculas.


Aula 2 - Cifra de ficheiro utilizando JCA/JCE

Pretende-se cifrar o conteudo de um ficheiro. Para tal far-se-á uso da funcionalidade oferecida pela JCA/JCE, em particular a implementação de cifras simétricas.

O objectivo é então o de definir um pequeno programa Java que permita cifrar/decifrar um ficheiro utilizando uma cifra simétrica (e.g. RC4). A sua forma de utilização pode ser análoga a:

      prog -genkey <keyfile>
      prog -enc <keyfile> <infile> <outfile>
      prog -dec <keyfile> <infile> <outfile>

Sugestões:

  • Para simplificar, pode começar por utilizar uma chave secreta fixa, definida no código na forma de um array de bytes. Nesse caso, deverá utilizar a classe SecretKeySpec para a converter para o formato adequado.
  • É também interessante verificar que o criptograma gerado é compatível com outras plataformas que implementam a mesma cifra. O comando seguinte utiliza o openssl para decifrar um ficheiro cifrado com RC4 (a chave tem de ser fornecida em hexadecimal).
               openssl enc -d -rc4 -in <infile> -out <outfile> -K <chave>

Algumas classes relevantes:


Aula 3 - Confidencialidade na comunicação Cliente-Servidor

As classes Cliente, Servidor e TServidorimplementam uma aplicação que permite a um número arbitrário de clientes comunicar com um servidor que escuta num dado port (e.g. 4567). O servidor atribui um número de ordem a cada cliente, e simplesmente faz o dump do texto enviado por cada cliente (prefixando cada linha com o respectivo número de ordem). Quando um cliente fecha a ligação, o servidor assinala o facto (e.g. imprimindo [n], onde n é o número do cliente).

Exemplo da execução do servidor (que comunica com 3 clientes):

$ java Servidor
1 : daskj djdhs slfghfjs askj
1 : asdkdh fdhss
1 : sjd
2 : iidhs
2 : asdjhf sdga
2 : sadjjd d dhhsj
3 : djsh
1 : sh dh d   d
3 : jdhd kasjdh as
2 : dsaj dasjh
3 : asdj dhdhsjsh
[3]
2 : sjdh
1 : dhgd ss
[1]
2 : djdj
[2]

Pretende-se nesta aula modificar as respectivas classes por forma a garantir a confidencialidade nas comunicações estabelecidas. Escolha para o efeito a cifra/modo que considerar mais apropriado.

Algumas classes relevantes:


Aula 4 - Confidencialidade na comunicação Cliente-Servidor (continuação)

Pretende-se nesta aula experimentar o impacto da escolha da cifra/modo na comunicação entre o cliente/servidor. Para tal é conveniente reforçar a natureza interactiva da comunicação modificando os ciclos de leitura/escrita para operarem sobre um byte de cada vez:

Cliente:

           CipherOutputStream cos = ...
	    int test;
	    while((test=System.in.read())!=-1) {
		cos.write((byte)test);
		cos.flush();
	    }
Servidor:
	    CipherInputStream cis = ...
		int test;
		while ((test=cis.read()) != -1) {
		    System.out.print((char) test);
		}

Experimente agora as seguintes cifras (e modos) e verifique qual o respectivo impacto nas questões de buffering e sincronização:

  • RC4
  • AES/CBC/NoPadding
  • AES/CBC/PKCS5Padding
  • AES/CFB8/PKCS5Padding
  • AES/CFB8/NoPadding
  • AES/CFB/NoPadding

Procure explicar a diferenças detectadas na execução da aplicação.

Obs: Note que em muitos dos modos sugeridos necessita de considerar um IV. Considere para o efeito que o IV é gerado pelo cliente e enviado em claro para o servidor (no início da comunicação).

Algumas classes relevantes (para além das já estudadas...):


Aula 5 - Acordo de Chaves Diffie-Hellman

O objectivo desta aula é implementar o acordo de chaves Diffie-Hellman. Algumas sugestões para atacar o problema:

  • Comece por utilizar a classe BigInteger e codifique cada passo do protocolo explicitamente. Pode começar por utilizar os seguintes parâmetros para o grupo (P tem 1024 bit):
P = 99494096650139337106186933977618513974146274831566768179581759037259788798151499814653951492724365471316253651463342255785311748602922458795201382445323499931625451272600173180136123245441204133515800495917242011863558721723303661523372572477211620144038809673692512025566673746993593384600667047373692203583
G = 44157404837960328768872680677686802650999163226766694797650810379076416463147265401084491113667624054557335394761604876882446924929840681990106974314935015501571333024773172440352475358750668213444607353872754650805031912866692119819377041901642732455911509867728218394542745330014071040326856846990119719675
  • No JCA, podemos gerar valores apropriados para os parâmetros necessários através de uma instância apropriada da classe AlgorithmParameterGenerator.
  • Em vez de trabalharmos directamente com a classe BigInteger, pode-se fazer uso da classe KeyAgreement.
  • No JCE Reference Guide está disponível um exemplo de codificação do protocolo.

Novas classes:


Aula 6 - Continuação da codificação do protocolo Diffie-Hellman

Nesta aula pretende-se concluir o protocolo de acordo de chaves Diffie-Hellman. Sugere-se que agora façam exclusivamente uso das funcionalidades oferecidas pela JCA, nomeadamente:

  • Classe AlgorithmParameterGenerator para gerar os parâmetros P e G do algoritmo;
  • Classe KeyPairGenerator para gerar os pares de chaves ( (x, g^x) e (y,_g^y_) para cada um dos intervenientes);
  • Classe KeyAgreement que implementa o protocolo propriamente dito.

APIs:


Aula 7 - Teste intermédio


Aula 8 - Codificação do protocolo Station-to-Station.

Pretende-se complementar o programa com o acordo de chaves Diffie-Hellman para incluir a funcionalidade do protocolo Station to Station. Recorde que nesse protocolo é adicionado uma troca de assinaturas (cifrada com a chave de sessão negociada), i.e.:

  1. Alice -> Bob : g^x
  2. Alice <- Bob : g^y, EK(SB(g^y, g^x))
  3. Alice -> Bob : EK(SA(g^x, g^y))

Um requisito adicional neste protocolo é a manipulação de pares de chaves de cifras assimétricas (e.g. RSA). Para tal deve produzir um pequeno programa que gere os pares de chaves para cada um dos intervenientes e os guarde em ficheiros que serão lidos pela aplicação Cliente/Servidor.

Novas Classes:


Aula 9 - Continuação da aula anterior.


Aula 10 - Utilização de certificados X509 em Java

Pretende-se certificar as chaves públicas utilizadas no protocolo Station-to-Station com base em certificados X509. Para tal, disponibiliza-se:

  • Certificado de chave pública do Servidor: servidor.crt
  • Chave privada do Servidor (codificada em PKCS8): servidor.pk8
  • Certificado de chave pública do Cliente: cliente.crt
  • Chave privada do Cliente (codificada em PKCS8): cliente.pk8
  • Certificado auto-assinado da autoridade de certificação: ca.crt

A utilização de certificados pressupõe a sua validação. O Java disponibiliza uma API específica que deverá utilizar para o efeito (documentação abaixo). Para facilitar esse estudo recomenda-se o estudo/adaptação de um programa de exemplo que verifica a validade de uma cadeia de certificação: ValidateCertPath.java. Utilizando esse programa, podemos verificar a validade do certificado do servidor através da linha de comando:

java ValidateCertPath ca.crt servidor.crt 

Uma segunda questão que surgirá neste trabalho é a manipulação dos formatos das chaves: as chaves privadas correspondentes aos certificados fornecidos estão codificadas num formato standard PKCS8. Para se converter esse formato num objecto Java apropriado terá de se utilizar uma instância da classe KeyFactory. O fragmento de código que se apresenta ilustra esse processo:

        byte[] encodedKey;      // read from file
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encodedKey);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        RSAPrivateKey privKey =
        (RSAPrivateKey)keyFactory.generatePrivate(keySpec);

Classes requeridas:

Outra documentação relevante:


Aula 11 - Continuação da aula anterior.


Aula 12 - Geração de Certificados X509.

Nesta sessão iremos fazer uso do openssl para construir uma pequena autoridade de certificação.

O processo de emissão de certificados X509 passa pelos seguintes passos:

  1. - O utilizador gera um par de chaves;
  2. - O utilizador produz um "pedido de certificado" que contém a sua identificação e a sua chave pública, que é assinado com a sua chave privada (o que certifica que quem solicita o certificado está na posse da respectiva chave privada);
  3. - A autoridade de certificação valida os dados contidos no certificado e, no caso de certificar positivamente esses dados, emite o certificado de chave pública correspondente.
  4. - O certificado é enviado ao utilizador e, eventualmente, publicado por outros meios (e.g. serviço de directoria).

Para cada um destes passos iremos fazer uso dos comandos respectivos do openssl.

Geração de chaves:

openssl genrsa -out grupoXPTO.key

Para utilizar a chave privada no Java é conveniente converter o seu formato para PKCS8

openssl pkcs8 -topk8 -nocrypt -in grupoXPTO.key -outform der -out grupoXptoPrivKey.der

Geração do pedido de certificado:

openssl req -new -key grupoXPTO.key -out grupoXPTO.csr 

Emissão do certificado: A emissão de certificados é normalmente realizada com o auxílio de scripts que invocam o comando openssl com os argumentos apropriados. Existem duas scripts normalmente utilizadas para este efeito:

  • CA.pl - distribuída com o "openssl".
  • sign.sh - distribuída com o "mod_ssl". Espera encontrar ficheiros ca.key e ca.crt.

Produção de PKCS12: Para certas utilizações (e.g. browsers, leitores de email, etc.) é conveniente encapsularmos o certificado e respectiva chave privada num PKCS12.

openssl pkcs12 -export -chain -CAfile cacert.pem -name GrupoXPTO -aes128 -inkey grupoXPTO.key -in grupoXPTO.crt -out GrupoXPTO.p12

Verificação dos certificados:

openssl verify -CAfile cacert.pem cert1.crt cert2.crt ...

utilizando este Certificado da autoridade de certificação de raiz.

Apontadores úteis:



r12 - 19 Sep 2008 - 13:24:54 - JoseBacelarAlmeida
This site is powered by the TWiki collaboration platform Copyright © by the contributing authors. Ideas, requests, problems? Send feedback.
Syndicate this site RSSATOM