ChapterPDF Available

Criptografia Assimétrica para Programadores - Evitando Outros Maus Usos da Criptografia em Sistemas de Software

Authors:

Abstract and Figures

O mau uso generalizado da criptografia em sistemas software é a fonte mais frequente de problemas de segurança relacionados à criptografia. Diversos maus usos de criptografia já são considerados recorrentes em softwares em geral, resultando em vulnerabilidades exploráveis em ataques reais. Percebe-se uma grande lacuna entre o que os criptologistas veem como maus usos de criptografia e aquilo que os desenvolvedores veem como uso inseguro da tecnologia criptográfica. Este texto contribui para preencher essa lacuna, abordando a utilização programática de criptografia assimétrica (de chave pública) por desenvolvedores de software com pouca ou nenhuma experiência em segurança da informação e criptografia. O texto é introdutório e tem o objetivo de mostrar aos programadores de software, por meio de exemplos reais e trechos de código, os bons e maus usos da criptografia assimétrica e, assim, facilitar o aprofundamento em estudos futuros
Content may be subject to copyright.
Capítulo
2
Criptografia Assimétrica para Programadores Evi-
tando Outros Maus Usos da Criptografia em Siste-
mas de Software
Alexandre Braga (UNICAMP) e Ricardo Dahab (UNICAMP)
Abstract
The widespread misuse of cryptography in software systems is the most frequent source of
cryptography-related security problems. Several misuses of cryptography have been found to be
recurrent in software in general, resulting in vulnerabilities exploitable in real attacks. There is
a huge gap between what cryptologists see as misuses of cryptography and what developers see
as unsafe use of cryptographic technology. This chapter contributes to fill this gap by addressing
the programmatic use of asymmetric (public key) cryptography by software developers with
little or no experience in information security and cryptography. The text is introductory and
aims at showing to software programmers, through actual examples and code snippets, the
gooduses and misuses of asymmetric cryptography and facilitate further studies.
Resumo
O mau uso generalizado da criptografia em sistemas software é a fonte mais frequente de
problemas de segurança relacionados à criptografia. Diversos maus usos de criptografia são
considerados recorrentes em softwares em geral, resultando em vulnerabilidades exploráveis
em ataques reais. Percebe-se uma grande lacuna entre o que os criptologistas veem como
maus usos de criptografia e aquilo que os desenvolvedores veem como uso inseguro da tecno-
logia criptográfica. Este texto contribui para preencher essa lacuna, abordando a utilização
programática de criptografia assimétrica (de chave pública) por desenvolvedores de software
com pouca ou nenhuma experiência em segurança da informação e criptografia. O texto é
introdutório e tem o objetivo de mostrar aos programadores de software, por meio de exemplos
reais e trechos de código, os bons e maus usos da criptografia assimétrica e, assim, facilitar o
aprofundamento em estudos futuros.
50
2.1. Introdução
Ao longo dos anos, estudos [
Anderson 1993
,
Schneier 1998
,
Gutmann 2002
,
Marlinspike 2009
]
têm revelado que vulnerabilidades em softwares criptográficos são causadas principalmente
por defeitos de implementação e pela má gestão de parâmetros criptográficos. Assim, parece
ser mais fácil e prático para os atacantes cibernéticos procurarem por falhas não apenas nas
implementações em software de algoritmos criptográficos, mas também, e às vezes principal-
mente, nas camadas de software que encapsulam, circundam ou utilizam as implementações
criptográficas, em vez de tentarem encontrar falhas nos algoritmos criptográficos.
Atualmente, o desenvolvimento de sistemas de software é caraterizado por ecossistemas
de aplicativos maciçamente disponíveis, desenvolvidos, implantados e utilizados de modo distri-
buído, por uma população geograficamente dispersa, mas unida socialmente por interesses em co-
mum. Neste ambiente, a criptografia surge muitas vezes como uma tecnologia habilitadora de re-
lações (sociais e de negócios), influenciando a lógica das aplicações, resultando, por um lado, em
aplicações criptograficamente seguras e, por outro lado, em maus usos criptográficos cada vez
mais comuns. Sabe-se, por vários trabalhos relacionados [
Akhawe et al. 2013
,
Alashwali 2013
,
Egele et al. 2013
,
Georgiev et al. 2012
,
Fahl et al. 2012
,
Shuai et al. 2014
], da presença recor-
rente de diversas práticas ruins de criptografia em softwares diversos. Possivelmente, estas
vulnerabilidades criptográficas foram incluídas sem intenção.
Hoje, percebe-se o aumento de interesse, tanto da indústria [
Bleichenbacher et al. 2017
]
quanto da academia [
IACR 2012
,
Braga 2017
,
Acar et al. 2017
], pelos aspectos práticos, do
mundo real, relacionados aos maus usos da tecnologia criptográfica que levam a vulnerabilidades
exploráveis em sistemas de software. À medida que a segurança dos sistemas de software torna-
se transparente para os usuários e a criptografia de qualidade está disponível para todos os desen-
volvedores de software, a fonte mais comum de vulnerabilidades deixa de ser a infra-estrutura
criptográfica, para se tornar o software em torno desta, escrito por desenvolvedores não especia-
listas no assunto. Por isto, o mau uso generalizado da criptografia em software é, possivelmente,
afontemaisfrequentedeproblemasdesegurançarelacionadosàcriptografia[Braga2017].
Quando estudamos [
Braga 2017
]comoacriptografiapodesermalutilizadaemJava,
mesmo com o uso correto da API criptográfica, resultando em vulnerabilidades identificáveis
diretamente no código fonte, as seguintes observações emergiram empiricamente:
Apenas um quarto das ferramentas de verificação de softwares criptográficos pode ser
usado por programadores não especialistas em criptografia [Braga and Dahab 2015a].
Omauusodecriptografiaémuitofrequenteemcomunidadesdeprogramaçãoonline,
com padrões recorrentes de mau uso de APIs criptográficas [Braga and Dahab 2016].
As ferramentas de análise estática de código fonte são capazes de detectar apenas pouco
mais de um terço dos maus usos criptográficos catalogados [Braga et al. 2017a].
Os desenvolvedores podem aprender a usar APIs criptográficas sem realmente aprender
criptografia, enquanto alguns maus usos criptográficos persistem ao longo do tempo e
independem da experiência dos desenvolvedores com as APIs [Braga and Dahab 2017].
Neste contexto, este novo capítulo dá continuidade ao texto anterior intitulado "Intro-
dução à criptografia para programadores" [
Braga and Dahab 2015b
], desta vez com o objetivo
de mostrar aos programadores de software os bons e maus usos da criptografia assimétrica, por
meio de exemplos reais, contra-exemplos, trechos de código e programas ilustrativos em Java.
51
Este capítulo busca atender à demanda crescente por material didático voltado para a
utilização correta de implementações criptográficas por programadores não especialistas em
criptografia. O texto aborda a utilização programática de criptografia assimétrica por desenvol-
vedores de software com pouca experiência em segurança da informação e criptografia. Java é a
linguagem de programação escolhida porque possui uma API padronizada e estável [
Oracle a
]
que vem sendo usada por desenvolvedores de software por muito tempo, tendo sido adotada
também pela plataforma Android [Google ].
Oescopodestetextoéautilizaçãocorretadeimplementaçõescriptográficasprontas,
não cobrindo a implementação de algoritmos criptográficos. Ainda, o texto não oferece um
tratamento exaustivo ao tema da programação criptográfica; por outro lado, ele tem a finali-
dade de fomentar o interesse pelo assunto e ajudar na formação de profissionais qualificados
tanto na academia quanto na indústria. Todo o código fonte utilizado neste texto e no texto
anterior [Braga and Dahab 2015b] pode ser encontrado no repositório indicado pela URL:
https://bitbucket.org/alexmbraga/crypto4developers
Orestantedotextoestáorganizadodaseguinteforma.ASeção2.2revisitaosconceitos
eserviçoscriptográficosrelacionadosàcriptografiaassimétrica. ASeção2.3ilustra,com
programas em Java, casos de uso comuns da criptografia assimétrica. A Seção 2.4 explica
de forma programática os maus hábitos de programação insegura associados à criptografia
assimétrica. A Seção 2.5 aborda as configurações inseguras do TLS do ponto de vista dos maus
usos criptográficos. A Seção 2.6 conclui o capítulo.
2.2. Conceitos de criptografia assimétrica
Esta seção revisita os conceitos de serviços criptográficos assimétricos necessários para o
entendimento do restante do capítulo. Os seguintes assuntos são tratados: criptografia de chave
pública, encriptação assimétrica para sigilo e não-repúdio (ou irrefutabilidade) de mensagens
integras e autênticas com assinaturas digitais. A seção também oferece exemplos de sistemas
criptográficos assimétricos como RSA, acordos de chaves com Diffie-Hellman (DH), Cripto-
grafia de Curvas Elípticas (Elliptic Curve Cryptography - ECC), distribuição de chaves públicas
com certificação digital e noções gerais sobre o protocolo Transport Layer Security (TLS).
2.2.1. Criptografia de chave pública
Há dois tipos de sistemas criptográficos que são comumente conhecidos como criptografia de
chave secreta (ou simétrica) e criptografia de chave pública (ou assimétrica). Este texto trata
acriptografiaassimétrica(dechavepublica),enquantoqueacriptografiasimétrica(dechave
secreta) foi discutida em um texto anterior [
Braga and Dahab 2015b
]. Brevemente, na cripto-
grafia de chave secreta, uma única chave (um segredo compartilhado) é usada para encriptar e
decriptar a informação. A criptografia de chave pública utiliza duas chaves, que são relacionadas
matematicamente e construídas para trabalharem juntas. Uma das chaves do par é dita a chave
privada (pessoal) e é mantida em segredo, sendo conhecida apenas pelo dono do par de chaves.
Aoutrachavedoparéditaachavepública,porqueéconhecidapublicamente.
Devido à maior complexidade algébrica das operações matemáticas envolvidas, a
criptografia de chave pública tradicional (associada ao algoritmo RSA) possui em geral um
desempenho inferior se comparada à criptografia de chave secreta.
52
Figura 2.1. Sistema criptográfico assimétrico para sigilo (de [Braga and Dahab 2015b]).
2.2.2. Encriptação assimétrica para sigilo
Acriptografiadechavepúblicapodeserusadaparaobtersigilo.Nestecaso,aencriptaçãocom
achavepúblicatornapossívelquequalquerumenviecriptogramas(textoscifrados)paraodono
da chave privada. A Figura 2.1 ilustra um sistema criptográfico assimétrico para sigilo e seus
elementos básicos. Na figura, Ana, Beto e Ivo são os personagens. As mensagens de Ana para
Beto são transmitidas por um canal inseguro, controlado por Ivo. Beto possui um par de chaves,
uma chave pública e outra privada. Ana conhece a chave pública de Beto, mas somente o dono
do par de chaves (Beto) conhece a chave privada (não há segredo compartilhado). A Figura 2.1
contém os passos a seguir:
1. Ana configura o algoritmo de encriptação com a chave pública de Beto;
2. Ana alimenta o algoritmo com a mensagem original (o texto claro);
3. O texto claro é encriptado e transmitido para Beto pelo canal inseguro;
4. Beto configura o algoritmo de decriptação com a sua própria chave privada;
5. O criptograma é decriptado e o texto claro original é finalmente obtido por Beto.
Analisando a Figura 2.1, observa-se que Ana envia uma mensagem privada para Beto.
Para fazer isso, Ana encripta a mensagem usando a chave pública de Beto. Ana conhece a chave
pública de Beto, porque ela foi divulgada por Beto. Porém, o criptograma só pode ser decriptado
pela chave privada de Beto; nem Ana pode fazê-lo. Para obter comunicação segura bidirecional,
basta acrescentar ao sistema criptográfico o mesmo processo no sentido oposto (de Beto para
Ana), com outro par de chaves. Isto é, Beto usa a chave pública de Ana para enviar mensagens
encriptadas para ela. Ana, ao receber a mensagem, usa sua própria chave privada pessoal para
decriptar a mensagem enviada por Beto. A criptografia de chave pública é indispensável para o si-
gilo e a privacidade na Internet, pois torna possível a comunicação privada em uma rede pública.
53
Figura 2.2. Sist. criptográfico assimétrico para autenticação (de [Braga and Dahab 2015b]).
2.2.3. Não-repúdio de mensagens integras e autênticas
Acriptografiadechavepúblicaéabaseparaoutrosdoisserviçoscriptográficos:aautenticação
das partes comunicantes e a verificação de integridade das mensagens. O procedimento opera-
cional de utilização da criptografia de chave pública para autenticação de mensagens, em certa
medida, é o oposto do uso para sigilo. A criptografia de chave pública para assinatura digital
éusadaparaobterintegridade,autenticidadeeirrefutabilidade.
Chama-se assinatura digital ao resultado de uma certa operação criptográfica com a
chave privada sobre o texto claro. Neste caso, o dono da chave privada pode gerar mensagens
assinadas, que podem ser verificadas por qualquer um que conheça a chave pública correspon-
dente, portanto, sendo capaz de verificar a autenticidade da assinatura digital. Do ponto de vista
das implementações criptográficas subjacentes, nem sempre a operação de assinatura é uma
encriptação e nem a sua verificação é sempre uma decriptação.
Visto que qualquer um de posse da chave pública pode “decriptar” a assinatura digital,
ela não é mais secreta, mas possui outra propriedade: a irrefutabilidade. Isto é, quem quer que
verifique a assinatura com a chave pública, sabe que ela foi produzida por uma chave privada
exclusiva; logo, a mensagem não pode ter sido gerada por mais ninguém além do proprietário
da chave privada.
Na Figura 2.2, Ana usa sua chave privada para assinar digitalmente uma mensagem
para Beto. O texto claro e a assinatura digital são enviados por um canal inseguro (sem sigilo)
epodemserlidosportodos,porissoamensagemnãoésecreta.Qualquerumqueconheça
achavepúblicadeAna(todomundo,inclusiveBeto),podeverificaraassinaturadigital.Ivo
pode ler a mensagem, mas não consegue falsificá-la de maneira indetectável, pois não conhece
achaveprivadadeAna.
54
2.2.4. Exemplos de sistemas criptográficos assimétricos
Esta subseção descreve dois sistemas criptográficos assimétricos em suas formas clássicas, como
descritos nos livros textos: o algoritmo RSA canônico e o acordo de chaves Diffie-Hellman
sem autenticação. Além disso, a criptografia de curvas elípticas é tratada do ponto de vista
funcional. A subseção termina mostrando uma comparação entre os níveis de segurança dos
criptossistemas assimétricos.
2.2.4.1. O algoritmo RSA canônico
Tradicionalmente, o algoritmo criptogfico assimétrico mais conhecido e utilizado para en-
criptação é o RSA, cujo nome é formado pelas letras iniciais dos sobrenomes dos autores Ron
Rivest, Adi Shamir e Leonard Adleman. O RSA foi publicado em 1978 [
Rivest et al. 1978
].
Um par de chaves do RSA é gerado da seguinte forma: (i)Doisnúmerosprimosmuitograndes,
p
e
q
,sãoescolhidosaleatoriamente,com
(p6=q)
,paracalcular
n=pq
.(ii)Uminteiro
e
é
escolhido tal que
1<e<f(n)
,onde
e
écoprimode
f(n)
,com
f(n)=(p1)(p1)
.(iii)
Ointeiro
d
écalculadotalquesejaoinversomultiplicativode
e
(
de1
mod
f(n)
). Assim,
achavepúblicaéopardenúmeros(e,n)eachaveprivadaéopar(d,n).
AencriptaçãocomoRSAérealizadacomachavepúblicapelafórmula
c=me
mod
n
,emque
m
éotextoclaroe
c
éocriptograma.Adecriptaçãoéobtidacomachaveprivada
pela fórmula
m=cd
mod
n
.Aoperaçãodeassinaturadigitaléobtidacomachaveprivadapela
fórmula
s=md
mod
n
,onde
m
éamensageme
s
éaassinatura.Averificaçãoérealizadacom
achavepúblicapelafórmulam0=semod n,quandom0=m.
AsegurançadoRSAébaseadanadificuldadeemsefatorar
n
em seus fatores primos
quando
p
e
q
são muito grandes, hoje em dia, com no mínimo 1024 bits cada (Integer Factoriza-
tion Problem -IFP).Umvalorcomumenteusadopara
e
é
2(16)+1=65537
.Váriasaplicações
usam valores pequenos de
e
(tais como 3, 5 ou 35) para aumentar o desempenho da cifração
eaverificaçãodeassinaturas.Naprática,estaimplementaçãocanônicanuncadeveserutilizada.
Implementações com preenchimento e aleatorização devem ser preferidas.
Para promover segurança e interoperabilidade, o uso e a implementação do RSA devem
obedecer aos padrões internacionais. O documento PKCS#1v2 [
Jonsson and Burt Kaliski 2003
]
especifica o Optimal Asymmetric Encryption Padding (OAEP) como um mecanismo de pre-
enchimento (padding), que transforma o RSA em um mecanismo de encriptação assimé-
trica aleatorizado chamado RSA-OAEP. Já o Probabilistic Signature Scheme (PSS) é um
esquema de assinaturas digitais probabilísticas com RSA (RSA-PSS) também padronizado
no PKCS#1v2 [
Jonsson and Burt Kaliski 2003
]parasubstituiroesquemadeassinaturado
PKCS#1v1, considerado inseguro.
2.2.4.2. Acordos de chaves com Diffie-Hellman (DH)
Há ocasiões em que entidades que nunca tiveram a oportunidade de compartilhar chaves cripto-
gráficas (por exemplo, nunca se encontram, não se conhecem ou querem permanecer anônimas)
precisam se comunicar em sigilo. Nestes casos, uma chave efêmera, usada apenas para algumas
encriptações e decriptações decorrentes de uma conversa, pode ser gerada momentos antes do
55
início da conversa. Os métodos de acordo de chaves são utilizados para combinar ou negociar
uma chave secreta entre dois ou mais participantes usando um canal público. Uma característica
interessante destes métodos é que o segredo compartilhado (a partir do qual a chave será
derivada) é combinado pela troca de informações públicas por meio de um canal inseguro.
OprotocolodeacordodechavesDiffie-Hellman(DH)foipublicadoem1976noartigo
que lançou a criptografia de chave pública [
Diffie and Hellman 1976
]. Com o DH, o acordo
de um segredo compartilhado entre duas parte, Alice e Bob, ocorre da seguinte forma. (i)Alice
escolhe um primo grande
p
eumgerador
g
)docorpofinito
Fp
.(ii)Alicecompartilhaestes
valores com Bob. (iii)Aliceescolheumnúmeroaleatóriosecreto
a
ecalcula
A=ga
mod
p
.(iv)
Bob também escolhe um número aleatório secreto
b
ecalcula
B=gb
mod
p
.(v)AliceeBob
trocam entre si os valores
A
e
B
.(vi)Alicecalcula
Ba
mod
p
enquanto Bob calcula
Ab
mod
p
.Pelaspropriedadescomutativasdaexponenciação,
Ba=(gb)a=(ga)b=Ab=s
,onde
s
éo
segredo compartilhado entre Alice e Bob.
AsegurançadoDHvemdadificuldadedoadversárioemresolveroproblemaDiffie-
Hellman, variação do problema do logaritmo discreto (Discrete logarithm Problem -DLP):
calcular o valor
(ga)b
para inteiros muitos grandes e sen conhecer
a
enem
b
.Atualmente,
um primo
p
seguro (safe prime)tempelomenos2048bitsedeveobedecerapropriedade
p=2q1
,onde
q
também é primo. Os parâmetros
g
e
p
podem ser estáticos (reusados em
várias execuções do protocolo) ou dinâmicos (descartáveis ou efêmeros). Além disso, para
evitar ataques de personificação causados por um homem no meio (man-in-the-middle attack)
que se passa tanto por Alice quanto por Bob, apenas o DH autenticado deve ser usado.
Finalmente, o segredo compartilhado
s
não deve ser usado diretamente como chave
secreta, mas sim ser usado na derivação de uma chave secreta segura, por exemplo, com o
auxilio de uma função de resumo criptográfico.
2.2.4.3. Criptografia de Curvas Elípticas
Esta subseção oferece uma breve descrição sobre como a criptografia de curvas elíticas é usada
na prática [
Bos et al. 2014
,
Mart and Hern 2013
], do ponto de vista de uma API criptográfica.
Oleitorinteressadoemaprofundarosestudosnosaspectosmatemáticosedeimplementação
interna, deve procurar a literatura especializada [Menezes et al. 1996, Hankerson et al. 2004].
Os sistemas criptográficos baseados em curvas elípticas foram propostos por volta de
1985 de forma independente por dois pesquisadores [
Miller 1985
,
Koblitz 1987
], e se baseiam
na dificuldade em se calcular o logaritmo discreto de um número inteiro longo sobre a estrutura
algébrica de uma curva elíptica. Este problema é conhecido como Elliptic Curve Discrete Loga-
rithm Problem (ECDLP). Em geral, a curva elíptica tem a forma
y2=x3+ax+b
definida sobre
um corpo finito primo
Fp
ou binário
F2m
.OECDLconsideradomaisdifícilqueoIFPeo
DLP, associados ao RSA, ao DH e ao DSA. Por este motivo, o tamanho das chaves criptográficas
nos criptossistemas de curvas elípticas é consideravelmente menor que no RSA ou no DH.
Aplicações da criptografia de curvas elípticas incluem troca de chaves, assinaturas
digitais e encriptação. Os esquemas e protocolos criptográficos sobre curvas elípticas mais
comumente utilizados atualmente são o protocolo de acordo de chaves Elliptic Curve Diffie
Hellman (ECDH), o esquema de assinaturas digitais Elliptic Curve Digital Signature Algo-
56
Tab e l a 2 . 1 . Níveis de segurança e tamanhos de chave (de [BlueKrypt ]).
Nível de Fatoração DLP Curva Hash
segurança (IFP) chave Corpo Elíptica Assinatura KDF/HMAC/PRNG
80 1024 160 1024 160–163 SHA1 (160)
112 2048 224 2048 224–
233 SHA-224/512
SHA3-224
128 3072 256 3072 256–
283 SHA-256/512 SHA1(160)
SHA3-256
192 7680 384 7680 384–
409 SHA-384 SHA-224
SHA3-384 SHA-512
256
15360
512
15360
512–
571 SHA-512 SHA-256/384/512
SHA3-512 SHA-512/SHA3-512
rithm (ECDSA) [
NIST 2013
]eaencriptaçãoElliptic Curve Integrated Encryption Scheme
(ECIES) [Hankerson et al. 2004].
ONIST[
NIST 2013
]recomendacincocurvaselípticassobrecorposprimosparaserem
utilizadas no ECDSA, em cinco níveis de segurança, a saber: P-192, P-224, P-256, P-384 e
P-521 (também conhecidas [
SEC 2010
]comosecp192r1,secp224r1,secp256r1,secp384r1,
secp521r1). Existe ainda uma variedade de outras curvas definidas por diversas instituições.
Muitas já são consideradas inseguras para os padrões atuais enquanto outras emergem como
padrões de fato em substituição a padrões obsoletos.
Em se tratando de padrões emergentes, a curva 25519 [
Bernstein 2006
]temsidoconsi-
derada um novo padrão de fato na indústria de segurança criptográfica por ser uma boa substituta
às curvas padronizadas pelo NIST [
NIST 2013
], porque é mais rápida, possivelmente mais
segura, e alegadamente sem a influência de agências de governo sobre seu projeto. O seu
autor, Daniel Bernstein, mantém um site sobre a curva
https://cr.yp.to/ecdh.html
.
Infelizmente, nenhum dos provedores criptográficos Java adotados neste texto oferece a curva
25599 diretamente pela API.
2.2.4.4. Comparação de tamanhos de chave e níveis de segurança
Sistemas criptográficos implementados em software geralmente combinam diversas funções
criptográficas, cujas configurações devem ser escolhidas de modo a manter as funções no
mesmo nível de segurança. A Tabela 2.1 mostra uma comparação entre os níveis de segurança
de tipos de primitivas criptográficas e os tamanhos de chaves correspondentes. O nível de
segurança é uma medida relativa e pode ser interpretado como sendo a força de um algoritmo
criptográfico simétrico com chave de nbits.
Atabelafoiadaptadadowebsite
keylength.com
econsideraasrecomendações
do NIST(2016) [
BlueKrypt
]. Cada linha da tabela representa um nível de segurança, indo de
80 bits (para sistemas legados) até 256 bits. Por exemplo, no nível de 80 bits, atualmente útil
apenas para sistemas legados, um RSA de 1024 bits é comparável ao DH de 1024 bits com
chave de 160 bits, uma curva elíptica de 160 bits e hashes de 160 bits também. Já no nível
de segurança mais alto, 256 bits, o RSA se torna inviável na prática com chaves de 15360
bits, enquanto as curvas elípticas despontam com chaves de 512 bits e hashes de 512 bits para
assinaturas e de até 384 bits para geração de chaves.
57
Figura 2.3. Quantidades de chaves assimétricas e simétricas para até 150 participantes.
2.2.5. Distribuição de chaves públicas com certificação digital
Acriptografiaassimétricadechavespúblicastemapropriedadedesimplificaroproblema
de distribuição de chaves criptográficas. Por exemplo, cada um dos participantes do sistema
criptográfico só precisa ter o seu par de chaves, manter em segredo a sua chave privada e
divulgar a chave pública. Pode haver um repositório global para todas as chaves públicas ou
um mecanismo acessível para divulgá-las. A Figura 2.3 ilustra a distribuição de chaves públicas
para um grupo de quatro indivíduos. O gráfico da direita na Figura 2.3 mostra o crescimento
da quantidade de chaves (públicas e privadas) como uma função afim da quantidade de parti-
cipantes. A quantidade de chaves é o dobro da quantidade de participantes. Já a distribuição
de chaves simétricas (gráfico da esquerda) obedece a uma função quadrática.
Oprincipalproblemaadministrativoassociadoadistribuiçãodechavespública
justamente a confiança depositada na chave distribuída publicamente. Se a chave pública de
alguém pode ser facilmente encontrada em qualquer lugar, então é difícil assegurar com alto
grau de certeza que esta chave não foi corrompida ou substituída. O problema de garantir a
integridade e a autenticidade da chave pública é muito importante e, se não for solucionado
satisfatoriamente, pode comprometer a confiança no sistema criptográfico inteiro. Uma maneira
de validar chaves públicas é fazer com que elas sejam emitidas por Autoridades Certificadoras
(AC) de uma Infraestrutura de Chaves Públicas (ICP), do inglês Public-Key Infrastrucuture -
PKI, que torne possível a verificação da autenticidade de tais chaves.
Certificação digital e os aspectos de validação de certificados digitais possuem atu-
almente boas práticas bem documentadas [
Gutmann b
,
Gutmann a
,
NIST 2012
]eliteratura
especializada na implantação de tais infraestruturas [
Chandra et al. 2002
]. Um certificado di-
gital de chave pública, ou simplesmente certificado, é uma estrutura de dados que dá como
verdadeiro o vínculo entre uma chave pública autêntica e uma entidade cujo nome está no
certificado. A veracidade do certificado é garantida por uma terceira parte confiável, emissora
do certificado, chamada de Autoridade Certificadora (CA). O certificado contém a assinatura
digital da CA emissora e várias informações, tais como a chave pública, a identidade da entidade
reconhecida pela CA, datas de início de uso e de validade (final de uso), etc. Por isto, o
58
Figura 2.4. Fluxograma de validação de um certificado digital (de [Braga and Dahab 2015b]).
certificado é usado na verificação de que uma chave pública válida pertence a uma entidade
eservetambémcomomeioconfiávelparadistribuiçãodechavespúblicas.
Avalidaçãodocertificadoérealizadatodavezqueaautenticidadedachavepública
contida nele deve ser garantida. A assinatura da AC pode ser verificada por qualquer um com
acesso à chave pública da AC, cujo certificado é amplamente disponível. Por exemplo, num
caso bastante comum, uma AC pode emitir certificados SSL/TLS para servidores web que se
comunicam por meio do protocolo HTTP sobre TLS (HTTPS). Quando um software cliente
HTTPS (o navegador ou browser)fazumarequisiçãoparaumservidorwebprotegido,ares-
posta do servidor inclui o seu certificado digital. O software cliente HTTPS valida o certificado
do servidor verificando a assinatura da AC emissora sobre a chave pública do servidor e outros
parâmetros do certificado. Se o cliente já não possuir a chave pública da AC, ele vai buscá-la
(em um repositório de chaves públicas da AC). Se o certificado é verificado como válido, então
oclientesabequeoservidoréautêntico.
Avalidaçãodocertificado(edachavepúblicacontidanele)abrangemaisetapasdo
que somente a verificação da assinatura da AC. Além da verificação da assinatura, o software
cliente precisa verificar se o certificado não atingiu o final de seu período de validade, se não
foi revogado e se o nome constante no certificado é o mesmo da parte que alega ser a dona da
chave pública. O nome também deve ser obtido de um terceiro confiável, por exemplo, de um
serviço de DNS seguro, no caso de nomes de domínio. A validação do certificado é ilustrada
no fluxograma da Figura 2.4.
AverificaçãodaassinaturadaACemumcertificadodigitalexigeachavepúblicada
AC. Para ser confiável, a chave pública da AC deve estar contida em um certificado assinado
por outra AC ou autoassinado, se for uma CA raiz. As verificações sucessivas de uma sequência
de assinaturas constroem uma cadeia ou hierarquia de certificados. Os certificados na base
da hierarquia são assinados pelas ACs de mais baixo nível, cujos certificados são assinados
pelas ACs intermediárias, que têm seus certificados assinados pelas ACs de alto nível, cujos
certificados são assinados pela AC raiz, que tem seus certificados autoassinados. A Figura 2.5
59
Figura 2.5. Cadeia hierárquica de certificação digital (de [Braga and Dahab 2015b]).
ilustra esta cadeia de certificação.
Uma AC revoga um certificado nas seguintes situações: quando ocorrem erros na
emissão do certificado (nome grafado errado, por exemplo), ou o certificado foi emitido para
uso de um serviço e o portador não tem mais acesso a ele (demissão de um funcionário), ou
achaveprivadadoportadorfoicomprometida(umsmartcardfoiperdido),ouaindaachave
privada da AC foi comprometida (uma situação extrema). Uma Lista de Certificados Revogados
(Certificate Revocation List -CRL)éodocumentoassinadodigitalmentepelaACquelistao
número de série de todos os certificados, ainda não expirados, que perderam a utilidade por
algum dos motivos acima. Um software criptográfico pode consultar um serviço de CRL para
receber atualizações periódicas, em intervalos regulares definidos por procedimentos, ou ainda
consultar em tempo real se um certificado foi revogado ou não. Porém, a instabilidade do canal
de comunicação pode causar indisponibilidade do serviço de validação em tempo real.
2.2.6. O protocolo SSL/TLS
Security Sockets Layer -SSL(camadadesegurançadesockets,emtraduçãolivre)éoprotocolo
para transporte de dados protegidos com criptografia sobre os sockets TCP. O SSL permite
que a comunicação pela Internet entre aplicações cliente/servidor possa ser protegida contra
monitoramento, adulteração de conteúdo e falsificação de mensagens. O objetivo principal
do SSL é proporcionar um canal de comunicação seguro entre partes comunicantes. Tradici-
onalmente, livros de segurança em redes [
Stallings 2003
]sãoboasfontesparaestudodoSSL,
havendo também literatura específica [
Chandra et al. 2002
,
Ristic 2015
]sobreaimplementação
de código aberto mais conhecida deste protocolo, o OpenSSL [OpenSSL.org ].
AterceiraversãodoSSL(SSLv3)serviudebaseparaoTransport Layer Security (TLS).
60
Figura 2.6. Localização do Protocolo SSL/TLS na Pilha TCP/IP.
OTLSéumprotocolopadronizadopeloInternet Engineering Task Force (IETF) com o objetivo
de substituir o formato proprietário do SSL. O SSLv3 oferece os seguintes características de
segurança disponíveis até hoje no TLS:
Autenticação do servidor com assinaturas digitais e certificados X.509, por meio dos al-
goritmos RSA, DSA e ECDSA, ou até por meio de uma chave simétrica pré-configurada;
Autenticação (opcional) do cliente com assinaturas digitais e certificados X.509;
Sigilo com encriptação da informação trocada entre cliente e servidor;
Integridade (com uso de MACs) da informação trocada entre cliente e servidor.
Por razões históricas, o protocolo TLS também é referido como SSL/TLS. A Figura 2.6
posiciona o SSL/TLS em relação a pilha de protocolos TCP/IP. A camada de socket seguro fica
logo acima da camada de transporte. De fato, as aplicações (na camada de aplicação) podem
usar os sockets seguros como se fossem um serviço oferecido pela camada de transporte.
Inicialmente, o SSL foi usado para garantir o sigilo, autenticação e integridade dos dados
transmitidos via uma conexão HTTP. Quando uma conexão HTTP é protegida com SSL, o
protocolo é chamado HTTPS. Na autenticação do servidor SSL/TLS, para iniciar a canal seguro,
oservidorHTTPSprimeiroenviaseuprópriocertificadodigital.Oclientefazverificaçõesno
certificado (estas verificações são descritas em outra seção) e indica que o certificado é válido
econfiável.Ocanalseguroéestabelecidoeoservidorenviaodocumentorequisitadoparaocli-
ente. Já na autenticação do cliente SSL/TLS, o servidor requisita o certificado digital do cliente,
que o envia ao servidor. O servidor faz verificações no certificado do cliente e indica que o cer-
tificado é válido e confiável. Em seguida, o servidor envia o conteúdo requisitado para o cliente
autenticado. Este tipo de autenticação do cliente pode substituir o uso de senhas em sites web.
OSSL/TLSpossuidoissub-protocoloscomponentes: asaudação(handshake), que
autentica as partes e negocia os parâmetros de segurança criptográfica da comunicação, e o
protocolo de registro, que usa os parâmetros escolhidos na saudação para proteger o tráfego
entre as partes comunicantes. A Figura 2.7 ilustra o funcionamento da saudação (handshake)
do SSL/TLS v1.2. As etapas do diálogo de saudação entre cliente e servidor são detalhadas e
enumeradas na Figura 2.7. O objetivo principal deste diálogo é o estabelecimento de uma chave
de sessão (uma chave criptográfica secreta, simétrica e temporária). O diálogo de saudação
pode ser dividido em quatro partes:
1.
Negociação de parâmetros (versão, ID de sessão, algoritmos criptográficos e compressão);
2. Envio do certificado do servidor e solicitação opcional do certificado do cliente;
61
Figura 2.7. Estabelecimento de sessão e envio de mensagens SSL/TLS v1.2.
3. Envio do certificado do cliente, se solicitado;
4. Escolha de algoritmos criptográficos e finalização;
Esta implementação do handshake em duas rodadas é considerada [
Sullivan 2018
]uma
causa de perda de desempenho na execução do protocolo e foi otimizada na versão 1.3. Após
arealizaçãodoprotocolodesaudação(handshake), entra em ação o protocolo de registro
que realiza a troca, entre cliente e servidor, de informação encriptada segmentada em blocos
chamados de registros. Este texto não trata o protocolo de registro.
OSSL/TLSéindependentedeaplicaçãoe,comotal,nãoespecificacomoeledeve
ser adicionado a um protocolo de aplicação. Por isto, decisões de projeto importantes são
deixadas a cargo dos implementadores de protocolos de aplicação, tais como em que momento o
handshake deve ser iniciado ou como interpretar a autenticação dos certificados digitais trocados
entre as partes. Esta situação abre espaço para a inclusão de defeitos de implementação que
levam a vulnerabilidades exploráveis.
62
2.2.7. Versões do SSL/TLS e suas vulnerabilidades
Além do SSLv3 que deu origem ao TLSv1, vale ainda mencionar outras versões do SSL/TLS
que se destacam por possuírem características específicas e vulnerabilidades conhecidas. Em
linhas gerais, existem seis versões em uso do SSL/TLS que podem ser encontradas em implan-
tações reais: SSLv2, SSLv3, TLSv1.0, TLSv1.1, TLSv1.2 e TLSv1.3. As características gerais
de cada uma delas são descritas a seguir:
SSLv2 é considerado inseguro e não deve mais ser usado. Esta versão é vulnerável a ata-
ques conhecidos, tais como o BEAST (Browser Exploit against SSL/TLS) e o DROWN
(Decrypting RSA with Obsolete and Weakened eNcryption) [
Aviram et al. 2016
], e
outras vulnerabilidades como Cipher Suite Rollback eChangeCipherSpec Message Drop.
SSLv3 é obsoleto e não deve mais ser utilizado. O HTTPS sobre SSLv3 é vul-
nerável aos ataques POODLE (Padding Oracle on Downgraded Legacy Encryption)
[
Möller et al. 2014
]eLucky 13 [
Fardan and Paterson 2013
]esofredevulnerabilidades
como o Versi on Ro ll back eoKey Exchange Algorithm Confusion.
TLSv1.0 (RFC 2246) ainda é usada em sistemas legados. TLSv1.0 é vulnerável aos
ataques BEAST e Lucky 13 [
Fardan and Paterson 2013
]. Esta versão inicial do TLS tam-
bém é vulnerável a ataques de negação de serviço e que exploram falhas na renegociação.
Padrões de segurança como o PCI-DSS recomendam que esta versão seja abandonada.
TLSv1.1 (RFC 4346) é uma versão relativamente recente e que não apresenta vulnera-
bilidades conhecidas sem mitigação, mas ainda oferece algoritmos criptográficos antigos.
TLSv1.2 (RFC 5246) era a versão atual até Agosto (acabou de ser substituída pela versão
1.3) e já oferece esquemas criptográficos novos com encriptação autenticada.
TLSv1.3 (RFC 8446) foi lançado na forma final em Agosto de 2018 [
Rescorla 2018
]e
representa o rompimento definitivo com o passado pela eliminação de diversas caracte-
rísticas inseguras ou obsoletas mantidas até hoje por compatibilidade com legados.
Há testes específicos para implantações do SSL/TLS [
Ristic 2015
,
Eldewahi et al. 2015
,
OWASP 2015
]. Outros ataques contra SSL/TLS bastante conhecidos são o CRIME (Compres-
sion Ratio info-leak Made Easy)[
CRI 2012
], o BREACH (Browser Reconnaissance and Exfiltra-
tion via Adaptive Compression of Hypertext)[
BRE 2013
,
Gluck et al. 2013
], o Bleichenbacher
Attack on PKCS#l [
Bleichenbacher 1998
], os ataques ao RC4 [
AlFardan et al. 2013
], o Heart-
bleed, que afeta implementações como o OpenSSL, e o LogJam [
Adrian et al. 2015
,
Log 2016
],
que afeta as implementações dos protocolos de acordo de chaves.
2.2.8. A versão 1.3 do SSL/TLS
Uma vez que a versão 1.3 do TLS [
Rescorla 2018
]foilançadadefatonaformafinalem
Agosto deste ano (2018), faz sendo incluir neste texto um breve resumo dos avanços apre-
sentados por esta nova versão em relação a sua antecessora. Já há análises detalhadas do
TLSv1.3 [
Sullivan 2018
]disponíveisparaopúblicoemgeral.Grossomodo,anovaversão1.3
atende a quatro objetivos de projeto: redução da latência do handshake,encriptaçãodepartes
do handshake,aumentodarobustezcontraataqueseremoçãodefunçõeslegadas.Alistaa
seguir contém as principais diferenças entre o TLSv1.2 e o TLSv1.3 [Rescorla 2018]:
63
Alistadeopçõesdealgoritmossimétricosfoibastantereduzidaesócontémencriptação
autenticada (authenticated encryption with additional data -AEAD).Cifrasdeblocoem
modo CBC e a cifra RC4 foram removidos desta versão.
Oconceitodesuite criptográfica foi simplificado e agora separa os mecanismos de
autenticação e troca de chaves dos mecanismos de encriptação, hash usado na derivação
de chaves e MACs.
Ohandshake simplificado, em uma única rodada, acelera a saudação. Além disso, o
handshake em zero rodadas (sem negociações, só comunicação de escolhas pré-definidas)
foi incluído para atender às aplicações com restrições de tempo ainda maiores.
RSA e DH com parâmetros estáticos foram removidos, de modo que todas as suites
criptográficas agora possuem forward secrecy.Porém,sóoDHE/ECDHusadopara
troca de chaves.
Todas as mensagens do handshake depois do "ServerHello"agora são encriptadas e as-
sinadas pelo servidor. esta medida protege contra os ataques práticos (FREAK, LogJam)
eoutrosmaisteóricos,comoatrocamaliciosadecurvaselípticas(curveswap).
Acriptografiadecurvaselípticasfazpartedaespecificaçãoprincipalprotocolo,mas
negociação de formatos de representação de pontos da curva foi removida, para incluir
apenas um formato.
Em termos de criptografia de chaves públicas, o RSA-PSS é o único padding do RSA
permitido. O padding inseguro do padrão PKCS#1 v1.5 foi removido, assim como
também foram removidos o DSA e a compressão.
DH com parâmetros efêmeros customizados não é mais permitido. Há agora um número
fixo de opções sabidamente seguras. Isto evita a parametrização fraca do DH que leva,
por exemplo, ao ataque LogJam [Log 2016].
AMensagem"ChangeCipherSpec"foiremovidadohandshake,simplificandooprotocolo
eaumentandoarobustezcontraataques.Jáohandshake com chave pré-compartilhada
pre-shared key (PSK) foi simplificado para aumentar a robustez contra ataques.
2.2.9. Testando uma conexão TLS com OpenSSL
OsoftwareOpenSSL[
OpenSSL.org
]vemcomumaferramentaclienteTLSquepodeser
usada para estabelecer conexões com um servidor. O comando a seguir mostra como o cliente
s_client
usa a opção
-connect
,onomedoservidoreaporta443(padrãodoSSL)para
estabelecer uma conexão segura (na versão 1.2 -tls1.2)comumservidor.
$openssl s_client -connect exemplo.com:443 -tls1_2
Ocomportamentopadrãodocomandoétentarumaconexãonaversãomaisaltado
protocolo disponível na instalação do OpenSSL. Versões específicas podem ser usadas expli-
citamente com as opções
-ssl2
,
-ssl3
,
-tls1
,
-tls1_1
,
-tls1_2
e
-tls1_3
(somente em distribuições novas). Além disso, versões podem ser excluídas com as opções
-no_ssl2,-no_ssl3,-no_tls1,-no_tls1_1,-no_tls1_2.
Osuporteaalgoritmosespecíficospodesertestadopelaopção
-cipher
do co-
mando
s_client
seguido do nome da suite criptográfica. Já o comando
-ciphers -s
64
lista os algoritmos suportados na instalação local no OpenSSL. Os comandos a seguir listam os
algoritmos disponíveis e depois testam uma conexão com
AES128-SHA
,umaconfiguração
fraca. A opção -cipher kECDHE valida o uso do ECDH efêmero no acordo de chaves.
$openssl -ciphers -s
$openssl s_client -connect exemplo.com:443 -cipher AES128-SHA
$openssl s_client -connect exemplo.com:443 -cipher kECDHE
2.2.10. Considerações finais sobre SSL/TLS
AHistóriadoprotocoloSSLseconfundecomahistóriadocomércioeletrôniconaInternet.Na
última década do milênio passado, a empresa Netscape [
Wikipedia 2018
]dominavatantoomer-
cado de softwares navegadores web (browsers)comoodeservidoresWeb.Emummodelodene-
gócios inovador para a época, a Netscape distribuía gratuitamente o browser,masganhavamuito
dinheiro com a venda do seu servidor web, o único na época a possuir proteções de sigilo contra
monitoramento e interceptação da comunicação. A segurança da comunicação era garantida por
um protocolo criptográfico na camada de transporte do TCP/IP que ficou conhecido como SSL.
OSSLtornoupossíveisastransaçõessigilosasentreobrowser na máquina do cliente
eoservidorweb(dolojista).OusodoSSLépraticamentetransparenteparaocliente,oque
facilitou muito a ampla adoção deste protocolo como padrão de fato para segurança na Internet.
Com o SSL, os números de cartões de crédito puderam transitar pelas redes abertas com sigilo,
viabilizando o comércio eletrônico como acontece hoje em dia.
Entretanto, o SSL não resolve todos os problemas de segurança. Por exemplo, uma vez
que a informação cifrada do cartão de crédito chega ao lojista, ela precisa ser decifrada para
que o pagamento seja efetivado junto à instituição financeira (banco ou operadora de cartão
de crédito). Neste momento, as informações do cartão ficam expostas ao lojista e aos seus
funcionários. O SSL não resolve este problema, pois ele trata apenas da comunicação entre
browser eservidorweb.Outrosprotocolosdesegurançadevemserusadosparaprotegeras
informações de pagamento.
Finalmente, hoje em dia, surgem modalidades de ataques que exploram a confiança já es-
tabelecida em sites web que possuem conexões SSL/TLS legítimas. O abuso da confiança deposi-
tada por usuários na conexão SSL/TLS entre browser eservidorwebocorrequandoumaconexão
SSL/TLS legítima é usada em ataques. Atualmente, mesmo sites web maliciosos, utilizados por
exemplo em ataques de phishing,podemtercertificadosSSLlegítimosemseusservidores.Isto
se deve ao fato de autoridades certificadores emitirem, de forma simplificada na Internet, certifi-
cados gratuitos e de validade curta. Estes certificados, mesmo com validade reduzida, ainda po-
dem ser usados por tempo suficiente para viabilizar ataques de engenharia social [
Calvo 2018
].
65
2.3. Exemplos de bons usos da criptografia assimétrica
Esta seção usa programas que utilizam a API criptográfica padrão Java e a biblioteca cripto-
gráfica BouncyCastle [
BouncyCastle 2018
]paramostrarosseguintesconceitos:encriptação
assimétrica aleatorizada, assinatura digital probabilística e validação de certificados digitais.
Além disso, a seção mostra o uso dos algoritmos RSA-OAEP, RSA-PSS, ECDSA, ECIES e
curvas elípticas seguras. Alguns dos programas foram adaptados de [Braga et al. 2017a].
2.3.1. Encriptação e decriptação assimétrica
Esta subseção ilustra a encriptação assimétrica e aleatorizada com dois esquemas criptográficos
diferentes: RSA-OAEP e ECIES. Nos programas que se sequem, o leitor deve imaginar a
interação entre os dois personagens tradicionais de criptossistemas, Ana e Beto, ou Alice e Bob.
2.3.1.1. RSA Aleatorizado: RSA-OAEP
OcódigonaListagem2.1contémométodoprincipal(
main
)deumprogramaJavaparaencrip-
tação com RSA aleatorizado RSA-OAEP. A linha 3 seleciona o provedor criptográfico Bouncy-
Castle.Alinha4criaumtextoclaronavariável
pt
.Naslinhas6e7,cria-seopardechaves
RSA com 2048 bits. A linha 8 define o RSA como a implementação OAEP com hash SHA256
epadding MGF1 (o único disponível). As linhas de 9 a 12 criam duas máquinas criptográficas.
Uma para encriptação (configurada com a chave pública) e outra de decriptação (usando a chave
privada). Finalmente, as linhas de 14 a 17 realizam três encriptações sucessivas do mesmo texto
claro para mostrar que elas são diferentes de fato. A linha 18 faz a decriptação. As linhas de 19
a21mostramtodasasexceçõestratadasparaoRSA-OAEPemJava.Valeapenamencionaras
exceções de chave inválida, de tamanho de bloco inválido e de padding ruim ou desconhecido.
Listagem 2.1. RSA Aleatorizado com RSA-OAEP.
1public static void main( S tring args [] ) {
2try {
3Security.addProvider(new BouncyCastleProvider ( ) ) ; // provedor BC
4byte [] pt = (" Randomized RSA") . getBytes () ;
5
6KeyPairGeneratorg=KeyPairGenerator.getInstance("RSA","BC");
7g.initialize(2048);KeyPairkp=g.generateKeyPair();
8StringRSA_OAEP="RSA/None/OAEPWithSHA256AndMGF1Padding";
9Ciphere=Cipher.getInstance(RSA_OAEP,"BC");
10 e . i n i t ( C ip h er . ENCRYPT_MODE , kp . g e t P u b l i c ( ) ) ;
11 C i ph e r d = C i ph e r . g e t I n s t a n c e ( RSA_OAEP , "BC" ) ;
12 d . i n i t ( C ip he r . DECRYPT_MODE , kp . g e t P r i v a t e ( ) ) ;
13
14 U . p r i n t l n ( " P l a i n t e x t : " + U . b 2x ( p t ) ) ;
15 U . p r i n t l n ( " C i p h e r t e x t : " + U . b 2x ( e . d o F i n a l ( p t ) ) ) ;
16 U . p r i n t l n ( " C i p h e r t e x t : " + U . b 2x ( e . d o F i n a l ( p t ) ) ) ;
17 U . p r i n t l n ( " C i p h e r t e x t : " + U . b 2x ( e . d o F i n a l ( p t ) ) ) ;
18 U . p r i n t l n ( " P l a i n t e x t : " + U . b 2x ( d . d o F i n a l ( e . d o F i n a l ( p t ) ) ) ) ;
19 } catch (NoSuchAlgorithmException | NoSuchPaddingException |
20 I n v a l i d K e y E x c e p t i o n | I l l e g a l B l o c k S i z e E x c e p t i o n |
21 B a d P a d d i n gE x c e p t i o n | N o S u c h P r o v i d e r E x c e p t i o n e )
22 { Sy st em . o ut . p r i n t l n ( e ) ; }}
66
2.3.1.2. Outra maneira de usar o RSA-OAEP
OtrechodecódigonaListagem2.2mostraumasegundamaneiradeutilizaroRSAaleatorizado
OAEP. A linha 1 seleciona o provedor de serviços criptográficos BouncyCastle.Aslinhas
2e3criamopardechavesRSAcom2048bitsutilizadoporBetopararecebermensagens
encriptadas por Ana com a chave pública de Beto.
As linhas de 5 a 9 mostram as configurações comuns para Ana e Beto, em que os
parâmetros do OAEP são definidos manualmente. Primeiro, a função de preenchimento MGF1
éconfiguradaparausarafunçãodehash SHA512. Em seguida, os parâmetros do OAEP são
definidos como SHA512, MGF1 (única opção disponível) e a fonte de aleatorização default.Fi-
nalmente, a linha 9 instancia um RSA-OAEP sem configurações ("RSA/None/OAEPPadding").
As linhas de 12 a 16 mostram como Ana encripta com a chave pública de Beto. Pri-
meiro, nas linhas 12 e 13, a máquina de encriptação é configurada com os parâmetros do OAEP
(definidos anteriormente) e a chave pública de Beto. Em seguida, na linha 14, é calculado o
tamanho adequado, em bytes, do texto claro de entrada para o encriptador. Na fórmula, 2048 e
512 são os tamanhos, em bits, da chave e do hash,respectivamente.Alinha15extraiumtrecho
do texto claro como tamanho adequado e a linha 16 realiza a encriptação.
Finalmente, nas linhas de 18 a 20, Beto usa sua chave privada (linha 18) para configurar
amáquinacriptográficaemmododedecriptaçãoecomosparâmetrosOAEP(linha19),obtendo
otextoclaroapartirdocriptograma(linha20).
ORSA-OAEPlimitaotamanhodotextoclaroquepodeserencriptadoemumnica
chamada da função. Este limite está relacionado ao tamanho do corpo finito (e da chave)
usado na aritmética modular do algoritmo RSA e pode ser determinado, em bytes, pela fórmula
(ks-2*hs)/8–2,onde
ks
éotamanhodachaveRSAembitse
hs
éotamanhodohash em bits
usado pelo padding OAEP.
Listagem 2.2. Outro RSA Aleatorizado.
1Security.addProvider(new BouncyCastleProvider () ) ;
2KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA","BC");
3kpg.initialize(2048); KeyPair kp = kpg.generateKeyPair();
4
5// configuracoes comuns para Ana e Bato
6 MGF1ParameterSpec mgf1ps = MGF1ParameterSpec .SHA512;
7 OAEPParameterSpec OAEPps = new OAEPParameterSpec ("SHA512" , "MGF1" ,
8mgf1ps,PSource.PSpecified.DEFAULT);
9Cipher c = Cipher.getInstance("RSA/None/OAEPPadding", "BC");
10
11 // Encriptacao pela Ana com a chabe publica de Beto
12 Key pu bk = k p . g e t P u b l i c ( ) ;
13 c . i n i t ( Ci ph er . ENCRYPT_MODE , pubk , OAEPps ) ;
14 int maxLenB = (2 048 2512) /82; //tamanho max do texto claro ( bytes )
15 byte [] pt = U. cancaoDoExilio . substring (0 , maxLenB) . getBytes () ;
16 byte [] ct = c . doFinal( pt) ;
17
18 Key p r i v k = kp . g e t P r i v a t e ( ) ; // decriptacao com chave privada do Beto
19 c . i n i t ( Ci ph er . DECRYPT_MODE , p riv k , OAEPps ) ; //modo de decriptacao
20 byte [] ptBeto = c . doFinal ( ct ) ; // Decriptando
67
2.3.1.3. Encriptação assimétrica com curvas elípticas: ECIES
OECIESéumesquemadeencriptaçãocomcurvaselípticas[
Hankerson et al. 2004
]. A en-
criptação com ECIES é aleatorizada e autenticada, combinado no esquema criptográfico um
algoritmo simétrico (como o AES) e um MAC para autenticação do criptograma. O ECIES
pode ser uma alternativa ao RSA-OAEP com a vantagem de utilizar chaves menores que
aqueles do RSA, mantendo o mesmo nível de segurança. Nenhum dos provedores criptográficos
disponíveis na instalação da plataforma Java oferece uma implementação do ECIES, por isso
foi utilizada a implementação do ECIES no provedor criptográfico BouncyCastle (BC).
OtrechodecódigodaListagem2.3mostracomoutilizaroECIESdoprovedorBC.A
linha 3 adiciona dinamicamente o provedor BC e a linha 4 define o texto claro. Um gerador de
par de chaves para o ECIES é instanciado na linha 5 e configurado para uma curva elíptica com
chaves de 224 bits de tamanho (linha 6). Então, o par de chaves é criado na linha 6. Instancias
do ECIES, para encriptação com a chave pública (linha 8) e decriptação com a chave privada
(linha 10), são criadas a partir do identificador "ECIESwithAES–CBC", um ECIES com AES
no modo CBC, sem padding.
As linhas de 13 a 16 computam duas vezes o criptograma sobre o mesmo texto claro,
para mostrar que os criptogramas são diferentes. A linha 16 decripta o criptograma, recuperando
otextoclaro. ValeaindaobservarqueocriptogramageradopeloECIESébemmaislongo
que o texto claro utilizado no exemplo. Este é uma característica da criptografia assimétrica
aleatorizada, que carrega um nonce no criptograma, entre outras informações específicas de
cada esquema criptográfico, como por exemplo a tag de autenticação. Este característica tem
questões de armazenamento de podem inibir o uso do ECIES para proteger textos claros.
Listagem 2.3. Encriptação e decriptação com ECIES da BouncyCastle.
1public static void main( S tring args [] ) {
2try {
3Security.addProvider(new BouncyCastleProvider () ) ; // provedor BC
4byte [] ptAna = ( "Teste do ECIES") . getBytes () ;
5KeyPairGeneratorg=KeyPairGenerator.getInstance("ECIES","BC");
6g.initialize(224);KeyPairkp=g.generateKeyPair();
7
8Ciphere=Cipher.getInstance("ECIESwithAESCBC / NONE / NOPADDING" , " BC " ) ;
9e.init(Cipher.ENCRYPT_MODE,kp.getPublic());
10 C ip h er d = Ci p h er . g e t I n s t a n c e ( " E CIESwi thAESCBC / NONE / NOPADDING" , "BC " ) ;
11 d . i n i t ( C ip he r . DECRYPT_MODE , k p . g e t P r i v a t e ( ) ) ;
12
13 U . p r i n t l n ( " P l a i n t e x t : " + U . b 2x ( p tA na ) ) ;
14 U . p r i n t l n ( " C i p h e r t e x t : " + U . b 2x ( e . d o F i n a l ( p t An a ) ) ) ;
15 U . p r i n t l n ( " C i p h e r t e x t : " + U . b 2x ( e . d o F i n a l ( p t An a ) ) ) ;
16 U . p r i n t l n ( " P l a i n t e x t : " + U . b 2x ( d . d o F i n a l ( e . d o F i n a l ( p tA n a ) ) ) ) ;
17 } catch (NoSuchAlgorithmException | NoSuchPaddingException |
18 I n v a l i d K e y E x c e p t i o n | I l l e g a l B l o c k S i z e E x c e p t i o n |
19 B a d P a d d i n gE x c e p t i o n | N o S u c h P r o v i d e r E x c e p t i o n e )
20 { S ys te m . o ut . p r i n t l n ( e ) ; } }
68
2.3.2. Assinaturas digitais não-determinísticas
Esta subseção ilustra o uso de assinatura digital como mecanismo de autenticação de ori-
gem (autoria) de uma informação. Dois esquemas criptográficos de assinaturas digitais não-
determinísticas são ilustrados: assinaturas probabilísticas com RSA-PSS e aleatorizadas com
oECDSA.
2.3.2.1. Assinaturas digitais probabilísticas com RSA-PSS
OtrechodecódigonaListagem2.4mostracomoutilizaroRSA-PSSemJava.Aslinhasde
2até4selecionamoprovedorcriptográfico"BC"ecriamopardechavesRSAcom3072bits.
As linhas de 7 a 10 criam uma instância da máquina de assinatura (o assinador) para o PSS,
indicado pela string "SHA256withRSAandMGF1", e constroem um objeto de parâmetros do
PSS com hash SHA256 e MGF1, de modo análogo ao RSA-OAEP.
As linhas de 12 a 15 realizam o processo de geração da assinatura digital. Primeiro, a
linha 12 cria a mensagem (texto claro) que será assinada neste exemplo. Em seguida, a linha 13
inicializam o assinador com a chave privada e um gerador de números pseudoaleatórios seguro,
enquanto a linha 14 alimenta o assinador com a mensagem a ser assinada e a linha 15 calcula
aassinaturadigital,comométodo sign().
Por outro lado, as linhas 17 e 20 realizam o processo de verificação da assinatura digital.
Primeiro, na linha 17, a máquina de assinatura e inicializada para verificação e parametrizada
com a chave pública correspondente àquela chave privada usada na assinatura. Em seguida,
overificadoréalimentadocomamensagememtextoclaro(Nestecaso,paraqueohash da
mensagem seja recalculado). Finalmente, a linha 19 faz a verificação da assinatura digital com
ométodo verify().
Listagem 2.4. Assinatura digital aleatorizada com RSA-PSS.
1public static void main( S tring [ ] args ) throws Exception {
2Security.addProvider(new BouncyCastleProvider () ) ; // provedor BC
3KeyPairGeneratorkg=KeyPairGenerator.getInstance("RSA","BC");
4kg.initialize(3072,new SecureRandom () ) ;
5KeyPairkp=kg.generateKeyPair();
6
7Signaturesig=Signature.getInstance("SHA256withRSAandMGF1","BC");
8PSSParameterSpecspec=new PSSParameterSpec( "SHA256" , "MGF1" ,
9MGF1ParameterSpec.SHA256,20,1);
10 s i g . s e t P a r a m e t e r ( s p ec ) ;
11
12 byte [] m = " Testing good RSA PSS". getBytes () ;
13 s i g . i n i t S i g n ( k p . g e t P r i v a t e ( ) , new SecureRandom ( ) ) ;
14 s i g . u p d a t e (m ) ;
15 byte [] s = sig . sign () ;
16
17 s i g . i n i t V e r i f y ( k p . g e t P u b l i c ( ) ) ;
18 s i g . u p d a t e (m ) ;
19 if (sig.verify(s)) { System.out.println("Verification succeeded.");}
20 else {System.out.println("Verification failed."); }
21 }
69
2.3.2.2. Assinaturas digitais aleatorizadas com ECDSA
OtrechodecódigonaListagem2.5éoprimeiroexemplodestetextoqueutilizaexplicitamente
as curvas elípticas. Por isto, as linhas de 2 a 5 têm novidades. A linha 2 contém a escolha da
curva "secp256r1"ou NIST P-256. A linha 3 instancia um gerador de par de chaves para curvas
elípticas, enquanto a linha 4 inicializa o gerador com a curva selecionada. A linha 5 gera o par
de chaves. O gerador de par de chaves utiliza o provedor criptográfico "SunEC", que agrupa
diversas implementações criptográficas relacionadas às curvas elípticas e está disponível na
plataforma Java desde a versão 6 [Oracle b].
As linhas 7 e 8 instanciam um objeto
SecureRandom
com o melhor PRNG dis-
ponível para a implantação Java, geram uma semente de 24 bytes e configuram o objeto
SecureRandom
com ela. As linhas de 10 a 13 realizam os passos para geração de uma
assinatura digital. A linha 10 instancia um objeto assinador para o esquema criptográfico
ECDSA identificado por "SHA256withECDSA". A linha 11 configura o assinador com a chave
privada e o PRNG. A linha 12 obtém o documento a ser assinado enquanto a linha 13 alimenta
oassinadorcomodocumentoecalculaaassinaturadigital.
As linhas de 15 a 21 repetem os passos de instanciação e configuração de um assinador
egeraçãodeumaassinaturadigitalparaomesmodocumentoassinadoanteriormente,porém,
desta vez armazenados em objetos diferentes. As duas assinaturas digitais são comparadas
na linha 23, mostrando que elas são diferentes, apesar de terem sido geradas sobre o mesmo
documento. Este exemplo não faz a verificação da assinatura digital. O programa que mostra
averificaçãodeumaassinaturadigitalpodeserencontradoem[BragaandDahab2015b].
Listagem 2.5. ECDSA com nonce não repetido.
1public static void main( S tring [ ] args ) throws Exception {
2ECGenParameterSpececps=new ECGenParameterSpec (" secp256r1 " ) ;
3KeyPairGeneratorkpg=KeyPairGenerator.getInstance("EC","SunEC");
4kpg.initialize(ecps);
5KeyPairkpAna=kpg.generateKeyPair();
6
7SecureRandomsr1=SecureRandom.getInstanceStrong();
8byte [] seed = sr1 . generateSeed (24) ; sr1 . setSeed( seed ) ;
9
10 S i g n a t u r e s i g n e r 1 = S i g n a t u r e . g e t I n s t a n c e ( " S HA256 with ECD SA " , " Sun EC " ) ;
11 s i g n e r 1 . i n i t S i g n ( k pAna . g e t P r i v a t e ( ) , s r 1 ) ;
12 byte [] doc = U.cancaoDoExilio . getBytes () ;
13 s i g n e r 1 . u p d at e ( d o c ) ; byte [] sign1 = signer1 . sign () ;
14
15 S ec ur eR an do m s r 2 = S ec ur eR and om . g e t I n s t a n c e S t r o n g ( ) ;
16 s r 2 . s e t S e e d ( s e e d ) ;
17
18 S i g n a t u r e s i g n e r 2 = S i g n a t u r e . g e t I n s t a n c e ( " S HA256 with ECD SA " , " Sun EC " ) ;
19 s i g n e r 2 . i n i t S i g n ( k pAna . g e t P r i v a t e ( ) , s r 2 ) ;
20 d o c = U . c a n c a o D o E x i l i o . g e t B y t e s ( ) ;
21 s i g n e r 2 . u p d at e ( d o c ) ; byte [] sign2 = signer2 . sign () ;
22
23 boolean ok = Ar rays . a reEqual ( sign1 , sign2 ) ;
24 if (ok){System. out. println ("Nonce repeated ! Signatures are equal!" );}
25 else {System .out. println ( "Signatures are d ifferent ! ") ;}
26 }
70
2.3.3. Curvas elípticas seguras
Oprovedorcriptográfico"SunEC"oferecediversasopçõesdecurvaselípticas.ATabela2.2lista
as curvas padronizadas e ainda consideradas seguras pelos padrões internacionais [
NIST 2013
,
SEC 2010
]equeestãodisponíveisnoprovedor"SunEC",deacordocom[
Mart and Hern 2013
].
Na tabela, as curvas seguem a nomenclatura de SEC-2 [
SEC 2010
], com nomes no formato
sec[p|t]XXX[r|k]v
,onde
[p|t]
indica uma curva sobre corpo primo (
p
)oubinário
(
t
). Ainda, o número
XXX
indica o tamanho em bits da chave e a letra
[r|k]
indica que
acurvausaosparâmetrosdeKoblitz(k)ourandômicos(r), em uma determinada versão (v).
Na Tabela 2.2, a coluna da esquerda mostra o nível de segurança (em bits) e as outras
duas colunas mostram as curvas elípticas sobre corpos primos
Fp
ebinários
F2m
.Ascurvas
secp224r1 (NIST P-224), secp256k1, secp256r1 (NIST P-256) e secp384r1 (NIST P384), marca-
das com um asterisco, são consideradas inseguras por Daniel Bernstein [
Bernstein et al. 2013
].
Ele considera que estas curvas são complexas de implementar, facilitando a ocorrência de
defeitos que levam a vulnerabilidades, entre outros problemas.
Tab e l a 2 . 2 . Curvas elípticas seguras no provedor SunEC (de [Mar t and Hern 2013]).
Segurança Curvas sobre FpCurvas sobre F2m
80 sect163k1,sect163r1,sect163r2
96 secp192k1,secp192r1
112 secp224k1,secp224r1* sect233k1, sect233r1
115 sect239k1
128 secp256k1*,secp256r1* sect283k1, sect283r1
192 secp384r1* sect409k1, sect409r1
256 secp521r1 sect571k1, sect571r1
OtrechodecódigonaListagem2.6criaparesdechavesparacadaumadascurvasna
tabela 2.2 e lista os parâmetros das chaves. A execução do programa mostra que a chave pública
éumponto,emcoordenadas
(x,y)
,dacurvaelíptica,enquantoachaveprivadaéumasequência
de bits derivada de um número inteiro muito longo. Além disso, os nomes alternativos das curvas
(quando existem) também são listados e a chave privada está codificada no formato PKCS#8.
Listagem 2.6. Selecionando as curvas seguras de SunEC.
1public static void main( S tring argv []) {
2String[]curves={
3"secp192k1","secp192r1","secp224k1","secp224r1","secp256k1",
4"secp256r1","secp384r1","secp521r1","sect163k1","sect163r1",
5"sect163r2","sect233k1","sect233r1","sect239k1","sect283k1",
6"sect283r1","sect409k1","sect409r1","sect571k1","sect571r1"};
7try {for (String curve : curves) {
8ECGenParameterSpececps=new ECGenParameterSpec ( curve ) ;
9KeyPairGeneratorkpg=KeyPairGenerator.getInstance("EC","SunEC");
10 kpg . i n i t i a l i z e ( e cp s ) ; K ey Pai r kp = kpg . g e n e ra te Ke yP ai r ( ) ;
11 U . p r i n t l n ( " EC p a r a m e t e r s " + e c p s . ge t Na me ( ) ) ;
12 U . p r i n t l n ( " P ub . ke y : " + k p . g e t P u b l i c ( ) ) ;
13 U . p r i n t l n ( " P r iv . k ey : " + U . b2 x ( kp . g e t P r i v a t e ( ) . g et En co de d ( ) ) ) ;
14 U . p r i n t l n ( " A l g o r i t h m : " + k p . g e t P r i v a t e ( ) . g e t A l g o r i t h m ( ) ) ;
15 U . p r i n t l n ( " F o rm a t : " + k p . g e t P r i v a t e ( ) . g e t F o r m a t ( ) ) ;
16 }} catch (NoSuchAlgorithmException|InvalidAlgorithmParameterException |
17 N o S u c h P r o v i d e r E x c e p t i o n e ) { S y s te m . e r r . p r i n t l n ( " E r r o r : " + e ) ; } }
71
2.3.4. Validação completa de certificados digitais
OprogramanaListagem2.7fazavalidaçãodeumcertificadodigitalesuacadeiadecertificação
em uma conexão segura SSL/TLS. As linhas de 4 a 6 estabelecem a conexão segura e realizam
o(handshake)doprotocolo.Aslinhasde8a14mostraminformaçõesdasessãosegura,tais
como versão do protocolo, suite criptográfica e os nomes do servidor e do sujeito no certificado.
Não há validação automática do nome do servidor, que deve ser feita manualmente. A
comparação do nome do servidor (obtido da sessão) com o nome do sujeito no certificado é
feita nas linhas 17 e 18. A validação do certificado é feita nas linhas de 20 a 24. A linha 20
obtém toda a cadeia de certificação associada ao certificado do servidor, incluindo ele próprio.
Alinha22verifica,nométodo
checkValididy()
,adatadevalidadedocertificadodo
servidor, enquanto a linha 23 verifica a assinatura digital do certificado do servidor com o
método verify().Seavalidaçãofalhar,umaexceçãoespecíficdisparada(linha24).
Orestantedoprogramafazaverificaçãodacadeiadecertificaçãoassimcomoda
revogação do certificado do servidor por meio de uma CRL. O processo possui dois passos
preparatórios e um passo de verificação: (i)Obtençãodocertificadoraizedosoutroscertificados
da cadeia de certificação, de modo que a cadeia possa ser completamente construída (linhas
de 27 a 35). (ii)Designaçãodoscertificadosraízescomncorasdeconfiançadacadeia(linhas
38 e 39). (iii)Validaçãodacadeiadecertificaçãoedostatus de revogação do certificado do
servidor (linhas 41 até 65). Por questões de espaço, apenas este passo é detalhado.
Nas linhas de 42 a 50, é criado um validador de cadeia de certificação (instância de
CertPathValidator
)comquatroopçõesconfiguradas:falhasuavementesenãoobtiver
aCRLenemaverificaçãoporOCSP,semmecanismoderecuperação,verificaapenasos
certificados na ponta da cadeia, e prefere a verificação por CRL em vez de OCSP.
Nas linhas de 52 a 57, uma CRL associada ao certificado raiz (ancora de confiança)
érecuperademodoconfiável(detalhesomitidos)eadicionadaaosparâmetrosdaverificação.
Finalmente, as linhas de 60 a 65 realizam a verificação. O método
validate()
da linha
61 verifica a cadeia e a CRL passadas como parâmetros. Se exceções não ocorrem (verificação
bem sucedida), as políticas de uso do certificado (linha 62) e a chave pública (linha 63) podem
ser obtidas com confiança. No caso do SSL/TLS, o conteúdo da página indicada na URL é
recuperado (linha 67). Senão, alguma exceção é disparada (linhas 63 e 65).
Listagem 2.7. Validação completa de Certificados.
1public static void main( S tring [ ] args ) throws Exception {
2 SSLSocket s = null ;boolean ok = true ;
3try {
4 SSLSocketFactory f=(SSLSocketFactory )SSLSocketFactory . getDefault () ;
5s=(SSLSocket)f.createSocket("www.google.com",443);
6s.startHandshake();// all validations happen after handshake
7
8System.out.println("Sessioninfos");
9SSLSessionss=s.getSession();
10 S y st e m . o u t . p r i n t l n ( " P r o t o c o l : " + s s . g e t P r o t o c o l ( ) ) ;
11 S y st em . o u t . p r i n t l n ( " C i p h e r s u i t e : " + s s . g e t C i p h e r S u i t e ( ) ) ;
12 S y st e m . o u t . p r i n t l n ( " H o s t n am e : " + s s . g e t P e e r H o s t ( ) ) ;
13 P r i n c i p a l p e er = s s . g e t P e e r P r i n c i p a l ( ) ;
14 S ys te m . o u t . p r i n t l n ( " SSL P ee r P r i n c i p a l : " + p ee r ) ;
15
72
16 // Cert , date , and Host validation
17 if (! peer . getName() . contains ("CN=" + ss . getPeerHost () ))
18 { throw new CertificateException("Host and Principal mismatch");}
19
20 C e r t i f i c a t e [ ] p e er C e rt s = s s . g e t P e e r C e r t i f i c a t e s ( ) ;
21 if (peerCerts != null && p e e r C e r t s . l e n g t h > = 2 ) {
22 ( ( X 5 0 9 C e r t i f i c a t e ) p e e r C e r t s [ 0 ] ) . c h e c k V a l i d i t y ( ) ;
23 p e e r C e r t s [ 0 ] . v e r i f y ( p e e r C e r t s [ 1 ] . g e t Pu b l i cK e y ( ) ) ;
24 } else {throw new CertificateException ("Unable to verify cert . ") ;}
25
26 // Cert Path validation
27 // Step 1. Obtain CA root certs and the cert path to validate
28 C e r t i f i c a t e [ ] c e r t s = s s . g e t P e e r C e r t i f i c a t e s ( ) ;
29 X 5 0 9 C e r t i f i c a t e [ ] x 5 0 9 c e r t s = new X509Certificate [ cert s . length 1];
30 for (int i=0;i<certs.length1; i ++)
31 { x 5 0 9 c e r t s [ i ] = ( X 5 0 9 C e r t i f i c a t e ) c e r t s [ i ] ; }
32 X 5 0 9 C e r t i f i c a t e a n ch o r = ( X 5 0 9 C e r t i f i c a t e ) c e r t s [ c e r t s . l e ng t h 1];
33 L i s t l = A r r a y s . a s L i s t ( x 5 0 9 c e r t s ) ;
34 C e r t i f i c a t e F a c t o r y c f = C e r t i f i c a t e F a c t o r y . g e t I n s ta n c e ( "X .5 0 9 " , "SUN" ) ;
35 C e r t P a th c p = c f . g e n e r a t e C e r t P a t h ( l ) ;
36
37 // Step 2. Create a PKIXParameters with the trust anchors
38 TrustAnchor ta = new TrustAnchor (anchor , null);
39 P K I XP a r a m et e r s p a ra m s =new PKIXParameters ( Coll ect ion s . s ing let on ( ta ) ) ;
40
41 // Step 3. Use a CertPathValidator to validate the certificate path
42 C e r t P a t h V a l i d a t o r cp v= C e r t P a t h V a l i d a t o r . g e t I n s t a n c e ( " PKIX " , " SUN" ) ;
43 PKIXRevocationChecker rc =
44 ( P K I XR e v o c at i o n Ch e ck e r ) c p v . g e t R e v o c a t i o n C h e c k e r ( ) ;
45 r c . s e t O p t i o n s ( E nu mS et . o f ( P KI X Re v oc a ti on C he c ke r . O p ti o n . SOF T_FA IL ) ) ;
46 r c . s e t O p t i o n s ( E nu mS et . o f ( P KI X Re v oc a ti on C he c ke r . O p ti o n . NO_FALLBACK) ) ;
47 r c . s e t O p t i o n s ( E nu mS et . o f (
48 PK I X R ev o c a ti o nC h e c ke r . O pt i on . ONLY_END_ENTITY) ) ;
49 r c . s e t O p t i o n s ( E nu mS et . o f ( P KI X Re v oc a ti on C he c ke r . O p ti o n . PREFER_CRLS ) ) ;
50 p a r a ms . a d d C e r t P a t h C h e c k e r ( r c ) ;
51
52 // now it gets a valid CRL for Anchor
53 X509CRL c r l = C e r t U t i l s . g et CRL ( a nc ho r ) ; // supposed valid CRL
54 L i s t l i s t = new ArrayList () ; li st . add ( crl ) ;
55 CertStoreParameters csp=new CollectionCertStoreParameters ( list ) ;
56 C e r t S t o r e s t o r e = C e r t S t o r e . g e t I n s t a n c e ( " C o l l e c t i o n " , c s p ) ;
57 p a r am s . a d d C e r t S t o r e ( s t o r e ) ;
58
59 // validate certification path with specified params
60 PKIXCertPathValidatorResult cpvr
61 = ( P K I X C e r t P a t h V a l i d a t o r R e s u l t ) c pv . v a l i d a t e ( c p , p ar a m s ) ;
62 P ol i cy N o de p o l i c y T r e e = c p v r . g e t P o l i c y T r e e ( ) ;
63 P u b l ic K e y s u b j e c t P K = c p v r . g e t P u b l i c K e y ( ) ;
64 } catch (CertificateException|InvalidAlgorithmParameterException|
65 N oS u ch A l go r it h mE x c ep t io n | C e r t P a t h V a l i d a t o r E x c e p t i o n e )
66 { S ys te m . o ut . p r i n t l n ( e ) ; ok = false ;}
67 if (ok){System. out . println () ;CertUtils . handleSocket(s );}
68 else {System .out. println ( "Something wrong in cert v alidation . ") ;}}
73
2.4. Maus usos criptográficos e vulnerabilidades associadas
Esta seção é organizada em torno dos maus usos de programação de criptografia assimétrica
que levam a vulnerabilidades. Os maus usos são exemplificados por casos reais e ilustrados
programaticamente por meio de programas em Java. Os maus usos comuns de criptografia
assimétrica tratados no texto são os seguintes: encriptação determinística com RSA, problemas
da versão 1 do padrão PKCS#1 (assinaturas determinísticas e padding inseguro), configurações
fracas do RSA-OAEP, assinaturas digitais inseguras (com RSA, DSA e ECDSA), acordo de
chaves DH e ECDH sem autenticação ou com chaves fracas e curvas elípticas inseguras.
2.4.1. Criptografia determinística com RSA
Otrechodecódigonalistagem2.8mostraousoindiscriminadodoalgoritmoRSAcanônico,
isto é, sem aleatorização, conforme descrito anteriormente no texto [
Braga and Dahab 2015b
]
enaseção2.1.Oexemplousaumachavepequenade1024bits,inseguraparaospadrõesatuais.
Em Java, este mau uso pode ser identificado já na instanciação do algoritmo criptográfico,
por exemplo, pelo método
getInstance(a)
,daclasse
Cipher
,emque
a
éonome
do algoritmo. Há três opções inseguras para resolver o nome do algoritmo
a
para o RSA
canônico: (i) apenas o nome do algoritmo, por exemplo, "RSA"; (ii) nome do algoritmo e modo
ECB sem padding,porexemplo,"RSA/ECB/NoPadding";e(iii) nome do algoritmo, sem modo
esempadding,porexemplo,"RSA/None/NoPadding".Valeobservarqueaprimeiraopção
leva naturalmente ao erro, uma vez que, na falta de uma escolha explícita, o RSA canônico é
aopçãopadrãoimplícita.
Listagem 2.8. Três maneiras de RSA determinístico.
1public static void main( S tring args [] ) {
2try {
3Security.addProvider(new BouncyCastleProvider () ) ; // provedor BC
4byte [] textoClaroAna = (" Cripto deterministi ca" ) . getBytes () ;
5KeyPairGeneratorg=KeyPairGenerator.getInstance("RSA","BC");
6g.initialize(1024);KeyPairkp=g.generateKeyPair();
7String[]rsa={
8"RSA","RSA/ECB/NoPadding","RSA/None/NoPadding",// deterministico
9"RSA/None/PKCS1Padding","RSA/None/OAEPWithSHA1AndMGF1Padding"};
10 for (int a=0;a<rsa.length; a++){
11 C ip h er en c = C i ph e r . g e t I n s t a n c e ( r s a [ a ] , " BC " ) ;
12 en c . i n i t ( C i p he r . ENCRYPT_MODE , k p . g e t P u b l i c ( ) ) ;
13 C ip h er de c = C i ph e r . g e t I n s t a n c e ( r s a [ a ] , " BC " ) ;
14 de c . i n i t ( C i ph er . DECRYPT_MODE , kp . g e t P r i v a t e ( ) ) ;
15
16 U . p r i n t l n ( " E n c r i p t a d o co m : " + e n c . g e t A l g o r i t h m ( ) ) ;
17 byte [][] criptograma = new byte [2][];
18 for (int i=0;i<2; i++){
19 c r i p t o g r a m a [ i ] = e nc . d o F i n a l ( t e x t o C l a r o A n a ) ;
20 byte [] textoClaroBeto = dec. doFinal( criptograma [ i ]) ;
21 U . p r i n t l n ( " C r i p t o g ra m a : " + U . b 2x ( c r i p t o g r a m a [ i ] ) ) ;
22 }}
23 } catch (NoSuchAlgorithmException|NoSuchPaddingException|
24 I n v a l i d K e y E x c e p t i o n | I l l e g a l B l o c k S i z e E x c e p t i o n |
25 B a d P a d d i ng E x c e p t i o n | N o S u c h P r o v i d e r E x c e p t i o n e )
26 { Sy st em . o ut . p r i n t l n ( e ) ; } }
74
2.4.2. Problemas do RSA no padrão PKCS#1
Esta subseção aborda em maior detalhe os problemas da versão 1 do padrão PKCS#1 a partir de
três exemplos. Primeiro, a ausência de padding que leva à encritação com o RSA canônico. Em
seguida, o uso de assinaturas digitais determinísticas com o PKCS#1. Em terceiro, encriptação
com o padding PKCS#1v1.5, considerado inseguro, apesar de ser aleatorizado.
2.4.2.1. Ausência de padding na encriptação com RSA
Otrechodecódigonalistagem2.9mostramaisumavezousodoRSAcanônicoparaencrip-
tação. A utilização do algoritmo RSA sem padding aleatorizado é considerada um mau uso
porque pode levar a revelação indevida de informação pela identificação de padrões de texto
claro no criptograma. Isto é, quando um mesmo texto claro é encriptado mais de uma vez com
mesma chave. A identificação de tais padrões pode, por exemplo, favorecer a análise de tráfego
por um atacante capaz de observar a ocorrência de padrões na comunicação.
Há outros ataques sobre o RSA canônico que são mencionados pela literatura especi-
alizada [
Boneh 1999
], dentre eles há dois ataques considerados simples. O ataque de broadcast
acontece quando a mesma mensagem méencriptadapara
ei
destinatários diferentes, onde
ei
é
ovalordealgumachaveprivadai.Cadadestinatáriotemseuprópriopardechaves.Nestacaso,
épossíveldecriptaramensagemsemprecisardequalquerchaveprivadad.Asoluçãopara
este ataque, além de um padding seguro, é usar um sistema criptográfico híbrido com chaves
assimétricas para transporte de chaves simétricas.
Oataquedae-nézima raiz de cacontece quando a mensagem mémuitopequenae
ovalordeeémuitobaixo(porexemplo,noataquedaraizcúbicacom
e=3
). Neste caso, o
criptograma
c=me
émenorqueomóduloneadecriptaçãopodeserobtidasimplesmentepela
computação da e-nézima raiz de c.
Listagem 2.9. RSA canônico sem padding.
1public static void main( S tring args [] ) {
2try {
3Security.addProvider(new BouncyCastleProvider () ) ; // provedor BC
4byte [] pt = (" Cripto det erministica ") . getBytes () ;
5KeyPairGeneratorg=KeyPairGenerator.getInstance("RSA","BC");
6g.initialize(2048);KeyPairkp=g.generateKeyPair();
7
8Ciphere=Cipher.getInstance("RSA/None/NoPadding","BC");
9e.init(Cipher.ENCRYPT_MODE,kp.getPublic());
10 C i ph e r d = C i ph e r . g e t I n s t a n c e ( " RSA / No ne / No Pa dd in g " , "BC" ) ;
11 d . i n i t ( C ip he r . DECRYPT_MODE , kp . g e t P r i v a t e ( ) ) ;
12 U . p r i n t l n ( " T ex to c l a r o : " + U. b 2x ( p t ) ) ;
13 U . p r i n t l n ( " E n c r i p t a d o co m : " + e . g e t A l g o r i t h m ( ) ) ;
14 U . p r i n t l n ( " C r i p t o g r a m a : " + U . b 2x ( e . d o F i n a l ( p t ) ) ) ;
15 U . p r i n t l n ( " C r i p t o g r a m a : " + U . b 2x ( e . d o F i n a l ( p t ) ) ) ;
16 U . p r i n t l n ( " C r i p t o g r a m a : " + U . b 2x ( e . d o F i n a l ( p t ) ) ) ;
17 U . p r i n t l n ( " T e x t o c l a r o : " + U . b 2x ( d . d o F i n a l ( e . d o F i n a l ( p t ) ) ) ) ;
18 } catch (NoSuchAlgorithmException|NoSuchPaddingException|
19 I n v a l i d K e y E x c e p t i o n | I l l e g a l B l o c k S i z e E x c e p t i o n |
20 B a d P a d d i n g E x c ep t i o n | N o S u c h P r o v i d e r E x c e p t i o n e )
21 { Sy st em . o ut . p r i n t l n ( e ) ; }
75
2.4.2.2. Assinatura digital RSA determinística com PKCS#1v1
Otrechodecódigonalistagem2.10mostraaassinaturadigitaldeterminísticacomRSAsobre
um hash (no exemplo, SHA-512). O programa exemplo utiliza dois provedores criptográficos
diferentes, o "SunRSASign"para assinatura e o "BC"para verificação. O contrário também
funcionaria, porque os provedores são intercambiáveis e interoperáveis. Este foi o formato
inicialmente usado no padrão PKCS#1 para assinaturas digitais e tinha a finalidade de evitar
ousodoRSAcanônicoqueésusceptívelaoataquedefalsificaçãodeassinaturasconhecido
como Blinding [Boneh 1999].
Na listagem 2.10, as linhas de 2 a 6 faze o seguinte. A linha 2 adiciona dinamicamente
oprovedorcriptográficoBouncyCastle (BC). A linha 3 instancia um gerador de par de chaves
RSA do provedor BC. A linha 4 configura o gerador para chaves com 2048 bits de tamanho
eumPRNGseguro,enquantoalinha5criaumpardechavesnasconfiguraçõesindicadas.
As linhas de 7 a 17 realizam o processo de geração da assinatura digital. A linha 7 cria
uma instancia do objeto assinador "SHA512withRSA"do provedor "SunRsaSign", enquanto
alinha8declaraotextoclarousadonoexemplo. Alinha10configuraoassinadorcom
achavepúblicaeumainstânciadeumPRNGseguro. Aslinhasde10a16configuramo
objeto assinador 3 vezes com a mesma mensagem e PRNGs diferentes. Mesmo assim, as três
assinaturas são idênticas. Vale observar que o formato "SHA512withRSA"não usa o PRNG,
apesar da API permitir um objeto deste tipo. Esta é uma inconsistência da API.
As linhas de 19 a 22 realizam o processo de verificação da assinatura. A linha 19
cria um objeto assinatura "SHA1withRSA"do provedor "BC", enquanto a linha 21 configura
este objeto para o modo de verificação com a chave pública e alimenta o verificador com a
mensagem que foi assinada. Finalmente, a linha 22 faz a verificação da assinatura digital.
Listagem 2.10. Assinatura digital RSA determinística.
1public static void main( S tring [ ] args ) throws Exception {
2Security.addProvider(new BouncyCastleProvider () ) ; // provedor BC
3KeyPairGeneratorkg=KeyPairGenerator.getInstance("RSA","BC");
4kg.initialize(2048,new SecureRandom () ) ;
5KeyPairkp=kg.generateKeyPair();
6
7Signaturesig=Signature.getInstance("SHA512withRSA","SunRsaSign");
8byte [] m = " Testing RSA Signature PKCS1". getBytes () ;
9
10 s i g . i n i t S i g n ( k p . g e t P r i v a t e ( ) , S ec ur eR an do m . g e t I n s t a n c e S t r o n g ( ) ) ;
11 s i g . u p da t e (m) ; U . p r i n t l n ( " S i g n a t u r e : " + U . b 2x ( s i g . s i g n ( ) ) ) ;
12 s i g . i n i t S i g n ( k p . g e t P r i v a t e ( ) , S ec ur eR an do m . g e t I n s t a n c e S t r o n g ( ) ) ;
13 s i g . u p da t e (m) ; U . p r i n t l n ( " S i g n a t u r e : " + U . b 2x ( s i g . s i g n ( ) ) ) ;
14 s i g . i n i t S i g n ( k p . g e t P r i v a t e ( ) , S ec ur eR an do m . g e t I n s t a n c e S t r o n g ( ) ) ;
15 s i g . u p d a t e (m ) ; byte [] s = sig . sign () ; // generate a signature
16 s i g . u p da t e (m) ; U . p r i n t l n ( " S i g n a t u r e : " + U . b 2x ( s ) ) ;
17
18 // verify a signature
19 S i g n a t u r e v e r i f i e r = S i g n a t u r e . g e t I n s t a n c e ( " S HA5 12w ithR SA " , " BC" ) ;
20 S y st e m . o u t . p r i n t l n ( " A l g o r i t h m : " + s i g . g e t A l g o r i t h m ( ) ) ;
21 v e r i f i e r . i n i t V e ri f y ( kp . g et P ub l i c ( ) ) ; v e r i f i e r . u pd at e (m) ;
22 if (verifier.verify(s)) { U.println("Verification succeeded.");}
23 else {U.println("Verification failed."); }}
76
2.4.2.3. Encriptação com RSA PKCS#1 v1.5
OtrechodecódigonaListagem2.11descreveaencriptaçãoRSAcomopreenchimento(ou
padding)conformeopadrãoPKCS#1v1.5.Estepadrãodepreenchiment,emcertoscasos,
considerado inseguro [
Bleichenbacher 1998
], devido a sua susceptibilidade ao ataque de pad-
ding oracle,masqueaindaébastanteutilizadonoSSL/TLSatéaversãov1.2.Nalistagem2.11,
as linhas 3 a 6 definem o provedor criptográfico e o texto claro usados no exemplo e criam o
par de chaves com tamanho de 2048 bits.
Opadding éfeitoconformeailustraçãoaseguir,onde"02"são16bitsindicandoque
ocriptogramapossuiumpadding PKCS#1, nonce éumvalorpseudoaleatóriodeusnico
e"00"éumseparadorde16bitsentreotextoclarooriginaleononce.
02 nonce 00 texto claro
Apesar da vulnerabilidade do PKCS#1v1.5 ao ataque de padding oracle ter sido
publicada já há vinte anos, em 1998 [
Bleichenbacher 1998
], ainda hoje é possível achar imple-
mentações do PKCS#1v1.5 em sistemas criptográficos em produção e padrões em uso, como
oSSL/TLSv1.2.Estefatolevantaaquestãodecomoédifícilseguirasboaspráticas.
Ainda na Listagem 2.11, as linhas de 8 a 11 criam duas máquinas criptográficas para o
RSA com padding PKCS#1v1.5, indicado pela string "RSA/None/PKCS1Padding": Uma para
encriptação (configurada com a chave pública) e outra de decriptação (usando a chave privada).
Finalmente, as linhas de 14 a 16 realizam três encriptações sucessivas do mesmo texto claro
para mostrar que elas são diferentes de fato. A linha 17 faz a decriptação. As linhas de 18 a
21 mostram todas as exceções tratadas para o RSA PKCS#1v1.5 em Java.
Listagem 2.11. RSA com PKCS#1.
1public static void main( S tring args [] ) {
2try {
3Security.addProvider(new BouncyCastleProvider () ) ; // provedor BC
4byte [] ptAna = ( "Randomized RSA") . getBytes () ;
5KeyPairGeneratorg=KeyPairGenerator.getInstance("RSA","BC");
6g.initialize(2048);KeyPairkp=g.generateKeyPair();
7
8Ciphere=Cipher.getInstance("RSA/None/PKCS1Padding","BC");
9e.init(Cipher.ENCRYPT_MODE,kp.getPublic());
10 C i ph e r d = C i ph e r . g e t I n s t a n c e ( " RSA / No ne / PK CS 1P ad di ng " , " BC " ) ;
11 d . i n i t ( C ip he r . DECRYPT_MODE , kp . g e t P r i v a t e ( ) ) ;
12
13 U . p r i n t l n ( " P l a i n t e x t : " + new String (ptAna) ) ;
14 U . p r i n t l n ( " C i p h e r t e x t : " + U . b 2x ( e . d o F i n a l ( p t An a ) ) ) ;
15 U . p r i n t l n ( " C i p h e r t e x t : " + U . b 2x ( e . d o F i n a l ( p t An a ) ) ) ;
16 U . p r i n t l n ( " C i p h e r t e x t : " + U . b 2x ( e . d o F i n a l ( p t An a ) ) ) ;
17 U . p r i n t l n ( " P l a i n t e x t : " + U . b 2x ( d . d o F i n a l ( e . d o F i n a l ( p tA n a ) ) ) ) ;
18 } catch (NoSuchAlgorithmException | NoSuchPaddingException |
19 I n v a l i d K e y E x c e p t i o n | I l l e g a l B l o c k S i z e E x c e p t i o n |
20 B a d P a d d i n g E x ce p t i o n | N o S u c h P r o v i d e r E x c e p t i o n e )
21 { Sy st em . o ut . p r i n t l n ( e ) ; } }
77
2.4.3. Configurações fracas do RSA-OAEP
AFigura2.8mostraascombinaçõespossíveisparafunçõesdehash etamanhodechaves
(módulo) do RSA-OAEP, até o valor de 15360 de módulo (nível de segurança de 256 bits).
Cada célula da figura tem a quantidade de bits processada pelo RSA-OAEP. As combinações
tachadas têm níveis de segurança menores que 112 bits. As combinações sublinhadas têm nível
de segurança de 112 bits. As combinações em negrito com módulos de 3072, 7680 e 15360
têm 128, 192 e 256 bits de segurança, respectivamente.
Figura 2.8. Combinações de tamanho de chave (módulo) e hash para o RSA-OAEP.
OtrechodecódigonaListagem2.12mostraumexemplodeconfiguraçãoinsegura
do RSA-OAEP em que as chaves tem tamanho de 1024 bits (linha 5) e o hash éde160
bits, conforme a string "RSA/None/OAEPwithSHA1andMGF1Padding"(linha 7). Este código
processa apenas 86 bytes de cada vez (linha 10).
Listagem 2.12. RSA-OAEP com chave de 1024 bits e SHA-1.
1public static void main( S tring args [] ) {
2try {
3Security.addProvider(new BouncyCastleProvider ( ) ) ;
4KeyPairGeneratorkpg=KeyPairGenerator.getInstance("RSA","BC");
5kpg.initialize(1024);KeyPairkp=kpg.generateKeyPair();
6
7Cipherc=Cipher.getInstance("RSA/None/OAEPwithSHA1andMGF1Padding");
8
9c.init(Cipher.ENCRYPT_MODE,kp.getPublic());
10 byte [] ptAna = U. cancaoDoExilio . substring (0 ,86) . getBytes () ;
11 byte [] ct = c . doFinal( ptAna) ;
12
13 c . i n i t ( C ip he r . DECRYPT_MODE , kp . g e t P r i v a t e ( ) ) ;
14 byte [] ptBeto = c . doFinal ( ct ) ; // Decriptando
15 } catch (NoSuchAlgorithmException | NoSuchPaddingException |
16 I n v a l i d K e y E x c e p t i o n | B a d P ad d i n g E x ce p t i o n |
17 I l l e g a l B l o c k S i z e E x c e p t i o n | N o S u c h P r o v i d e r E x c e p t i o n e )
18 { Sy st em . ou t . p r i n t l n ( e ) ; }}
78
2.4.4. Assinaturas digitais inseguras
Esta subseção trata vulnerabilidades associadas às assinaturas digitais fracas. A primeira é a
repetição do nonce (number used once) na geração de assinaturas ECDSA e a segunda é a
utilização de configurações dos esquemas de assinatura ECDSA, DSA e RSA.
2.4.4.1. Nonce repetido na assinatura ECDSA
OECDSApodesermalutilizadoeproduzirassinaturasdigitaisvulneráveis.NoECDSA,cada
assinatura requer um número aleatório único e imprevisível, que deve ser utilizado apenas uma
vez (nonce). Por isto, o ECDSA é vulnerável à geração de números pseudoaleatórios ruins.
Aplicações de assinaturas digitais ECDSA são muito sensíveis aos maus usos do ECDSA,
tais como sementes de PRNGs com entropia baixa e nonces repetidos (com valores fixos em
programas). Assinaturas digitais geradas com o mesmo nonce,ounonces parecidos (com
alguns bits em comum) podem revelar a chave privada em aplicações reais como eWallets de
bitcoins [Bos et al. 2014, Braga et al. 2017b].
Na Listagem 2.13, as linhas 6 e 7 instanciam um objeto
SecureRandom
do tipo
"SHA1PRNG"e o configuram com uma semente de 24 bytes. As linhas de 9 a 12 reali-
zam os passos para geração da assinatura digital. A linha 9 instancia um assinador para o
"SHA256withECDSA". A linha 10 configura o assinador com a chave privada e o PRNG.
Alinha12calculaaassinaturadigitalsobreodocumento. Aslinhasde14a20repetemos
passos de instanciação e configuração de um assinador e geração da assinatura digital para o
mesmo documento assinado anteriormente, mas, desta vez, reutilizando a mesma semente para
o"SHA1PRNG".Porisso,asduasassinaturasdigitaiscomparadassãoiguais(linha22).
Listagem 2.13. Nonce repetido com ECDSA.
1public static void main( S tring [ ] args ) throws Exception {
2KeyPairGeneratorkpg=KeyPairGenerator.getInstance("EC","SunEC");
3kpg.initialize(256,SecureRandom.getInstanceStrong());
4KeyPairkpAna=kpg.generateKeyPair();
5
6SecureRandomsr1=SecureRandom.getInstance("SHA1PRNG","SUN");
7byte [] seed = sr1 . generateSeed (24) ; sr1 . setSeed( seed ) ;
8
9Signaturesigner1=Signature.getInstance("SHA256withECDSA","SunEC");
10 s i g n e r 1 . i n i t S i g n ( k pAna . g e t P r i v a t e ( ) , s r 1 ) ;
11 byte [] doc = U.cancaoDoExilio . getBytes () ;
12 s i g n e r 1 . u p d at e ( d o c ) ; byte [] sign1 = signer1 . sign () ;
13
14 S ec ur eR an do m s r 2 = Se cu re Ra nd om . g e t I n s t a n c e ( " SHA1PRNG " , "SUN" ) ;
15 s r 2 . s e t S e e d ( s e e d ) ;
16
17 S i g n a t u r e s i g n e r 2 = S i g n a t u r e . g e t I n s t a n c e ( " S HA256 with ECD SA " , " Sun EC " ) ;
18 s i g n e r 2 . i n i t S i g n ( k pAna . g e t P r i v a t e ( ) , s r 2 ) ;
19 d o c = U . c a n c a o D o E x i l i o . g e t B y t e s ( ) ;
20 s i g n e r 2 . u p d at e ( d o c ) ; byte [] sign2 = signer2 . sign () ;
21
22 boolean ok = Ar rays . a reEqual ( sign1 , sign2 ) ;
23 if (ok) {U. println("Nonce repeated! Signatures are equal !");}}
79
2.4.4.2. Configurações fracas de assinatura ECDSA
AListagem2.14ilustracomoumacurvaelípticainsegurapodeserutilizadademodoimplícito
pelas configurações da assinatura digital ECDSA. No programa exemplo, a linha 3 mostra a
criação de um par de chaves de 112 bits para curvas elípticas. Na linha 4, um objeto assinador
écriadopara"SHA1withECDSA".Ascurvasde112bitscombinadascomSHA-1(160bits)
resultam em segurança de 80 bits apenas. As linhas de 7 a 10 realizam os passos para geração
da assinatura digital: configuram o assinador com a chave privada, parametrizam o assinador
com o documento a ser assinado e calculam a assinatura digital do documento. Já as linhas de
11 a 13 realizam os passos para a verificação da assinatura digital com a chave pública.
Listagem 2.14. ECDSA com chave de 112 bits mas segurança de 80 bits.
1public static void main( S tring [ ] args ) throws Exception {
2KeyPairGeneratorkpg=KeyPairGenerator.getInstance("EC","SunEC");
3kpg.initialize(112,SecureRandom.getInstanceStrong());
4Signaturesigner=Signature.getInstance("SHA1withECDSA","SunEC");
5KeyPairkp=kpg.generateKeyPair();
6
7signer.initSign(kp.getPrivate(),new SecureRandom ( ) ) ;
8byte [] doc = U.cancaoDoExilio . getBytes () ;
9sig