Criptografia
Mestrado Integrado em Engenharia Biomédica
Guiões das aulas Teórico-Práticas 2008/2009
Aula 1: 18/09/2008
Apresentação da disciplina.
Aula 2: 25/09/2008
Objectivos:
- Instalação do IDE recomendado (Eclipse JEE);
- Execução de programa elementar;
- Apontadores WEB com material de Referência e Tutorials.
Transcreva para o editor do Eclipse, compile e execute o seguinte programa:
/**
* The HelloWorldApp class implements an application that
* simply prints "Hello World!" to standard output.
*/
class HelloWorldApp {
public static void main(String[] args) {
System.out.println("Hello World!"); // Display the string.
}
}
Leia a secção do
Java Tutorial referente a
este exemplo. Consulte também a documentação referente ao método
println
(a que classe pertence?).
Para se realizarem programas minimamente interessantes, é necessário conhecer um conjunto básico de conceitos e de classes da biblioteca standard (secções
Learning the Java Language e
Essential Java Classes)
Aula 3: 02/10/2008
Pretende-se realizar uma pequena aplicação java com a seguinte funcionalidade:
- O utilizador, ao invocar o programa, passa também como argumento um nome de um ficheiro de texto
fich
;
- O programa deverá gravar um novo ficheiro
fich.out
em que converte todas as letras minúsculas em maiúsculas;
- No final, deverá imprimir no écran o número total de caracteres e linhas processadas.
Algumas classes relavantes:
Aula 4: 09/10/2008
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.
Algumas classes relevantes:
Aula 5: 16/10/2008
Jornadas de Engenharia Biomédica. (tolerância de ponto)
Aula 6: 23/10/2008
Continuação da aula de "Cifra de Ficheiro".
Aula 7: 30/10/2008
As classes
Cliente,
Servidor e
TServidor implementam 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 8: 06/11/2008
O objectivo desta aula é implementar o acordo de chaves
Diffie-Hellman directamente em
Java (sem recorrer ao
framework JCA).
- Alice,Bob: acordam nos parâmetros P e G
- Alice: gera x tal que 0 ≤ x < P
- Alice -> Bob : G^x mod P
- Bob: gera y tal que 0≤ y < P
- Bob -> Alice : G^y mod P
- Alice, Bob: segredo acordado K = G^(xy) mod P = (G^x)^y mod P = (G^y)^x mod P
Utilize 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
Classes relevantes:
Aula 9: 13/11/2008
(obs: só para quem acabou o programa pedido na aula anterior...)
Pretende-se codificar uma nova versão do protocolo de acordo de chaves
Diffie-Hellman que faça 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.
Em
JCE Reference Guide está disponível um exemplo de codificação desse protocolo.
APIs:
Aula 10: 20/11/2008
Pretende-se complementar o programa com o acordo de chaves
Diffie-Hellman para incluir a funcionalidade análoga à do protocolo
Station to Station. Recorde que nesse protocolo é adicionado uma troca de assinaturas:
- Alice -> Bob : g^x
- Alice <- Bob : g^y, SB(g^x, g^y)
- Alice -> Bob : 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 11: 27/11/2008
Continuação da aula anterior.
Aula 12: 04/12/2008
Apresentação dos mini-projectos práticos.
Aula 13: 11/12/2008
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 14: 18/12/2008
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:
- - O utilizador gera um par de chaves;
- - 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);
- - 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.
- - 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:
Aula 15: 08/01/2008
Apresentação dos trabalhos práticos.