relatório final - rsa android
DESCRIPTION
Aplicativo RSA em ambiente AndroidTRANSCRIPT
MINISTÉRIO DA DEFESA
EXÉRCITO BRASILEIRO
DEPARTAMENTO DE CIÊNCIA E TECNOLOGIA
INSTITUTO MILITAR DE ENGENHARIA
(Real Academia de Artilharia Fortificação e Desenho - 1792)
TEMA DIRIGIDO
ALGORITMO RSA NO AMBIENTE ANDROID
LOLLIPOP COM APLICAÇÃO EM JAVA
Leonardo Linhares Muniz Ribeiro
Marília Nascimento Monteiro
Tayná Larissa Fischer Vieira
2º ANO
Maj ANDERSON FERNANDES PEREIRA DOS SANTOS
RIO DE JANEIRO
05 DE NOVEMBRO DE 2015
RESUMO
O presente trabalho tem por objetivo desenvolver um algoritmo de Criptografia
RSA utilizando a linguagem de programação Java e aplicá-lo ao ambiente Android
Lollipop. Para tanto foram desenvolvidos estudos acerca do algoritmo RSA, da
linguagem Java, do ambiente Android, além da implementação do algoritmo em
Java para Desktop e para Android. Ao final do desenvolvimento foi entregue um
aplicativo em Android Lollipop, como se objetivava inicialmente, com as
funcionalidades de criptografar e decriptografar quaisquer tipos de arquivos de um
Smartphone onde opera.
SUMÁRIO
1. INTRODUÇÃO ............................................................................................6
1.1. MOTIVAÇÃO .......................................................................................................... 6
1.2. OBJETIVO ............................................................................................................... 7
1.2.1. OBJETIVOS PRINCIPAIS ...................................................................................... 7
1.3. CONTRIBUIÇÃO .................................................................................................... 7
1.4. ORGANIZAÇÃO ..................................................................................................... 8
2. FUNDAMENTAÇÃO TEÓRICA ...............................................................9
2.1.1. INTRODUÇÃO ........................................................................................................ 9
2.1.1.1. A CRIPTOGRAFIA ................................................................................................. 9
2.1.1.2. HISTÓRICO ............................................................................................................. 9
2.1.1.3. SOBRE O ALGORITMO RSA .............................................................................. 11
2.1.2. CONCEITOS E ANÁLISES TEÓRICAS .............................................................. 12
2.1.2.1. CRIPTOGRAFIA MODERNA .............................................................................. 12
2.1.2.2. O ALGORITMO RSA ............................................................................................ 13
2.1.2.2.1. EMBASAMENTO MATEMÁTICO ..................................................................... 13
2.1.2.2.1.1. FUNÇÃO PHI DE EULER .................................................................................... 13
2.1.2.2.1.2. O ALGORITMO ESTENDIDO DE EUCLIDES .................................................. 13
2.1.2.2.2. OBTENÇÃO DAS CHAVES ................................................................................. 14
2.1.2.2.3. CIFRAGEM E DECIFRAGEM ............................................................................. 15
2.1.2.2.4. VULNERABILIDADES ........................................................................................ 15
2.1.2.2.4.1. FATORANDO NÚMEROS PRIMOS MUITO GRANDES ................................. 15
2.1.2.2.4.2. PEQUENOS EXPOENTES .................................................................................... 16
2.1.2.2.4.3. EXPOSIÇÃO PARCIAL DA CHAVE PRIVADA ................................................ 16
2.1.2.2.4.4. ATAQUES TEMPORAIS ...................................................................................... 16
2.1.2.2.5. APLICAÇÕES ........................................................................................................ 17
2.1.2.2.5.1. ASSINATURA DIGITAL ...................................................................................... 17
2.1.2.2.5.2. CERTIFICADO DIGITAL ..................................................................................... 17
2.1.2.2.5.3. S/MIME E PGP ...................................................................................................... 18
2.1.2.2.5.4. SSL/TLS ................................................................................................................. 18
2.1.2.2.5.5. IPSEC ..................................................................................................................... 18
2.2. JAVA ...................................................................................................................... 19
2.2.1. INTRODUÇÃO ...................................................................................................... 19
2.2.1.1. BREVE HISTÓRICO DA LINGUAGEM ............................................................. 19
2.2.2. CONCEITOS .......................................................................................................... 20
2.2.2.1. JVM – JAVA VIRTUAL MACHINE ....................................................................... 20
2.2.2.2. ORIENTAÇÃO A OBJETO ................................................................................... 21
2.2.3. VANTAGENS E DESVANTAGENS DO JAVA .................................................. 22
2.2.3.1. VANTAGENS ........................................................................................................ 22
2.2.3.1.1. TRATAMENTO DE EXCEÇÕES ......................................................................... 22
2.2.3.1.2. GARBAGE COLLECTOR ....................................................................................... 22
2.2.3.1.3. PORTABILIDADE ................................................................................................ 23
2.2.3.1.4. COMPILAÇÃO JIT (JUST-IN-TIME) ................................................................... 23
2.2.3.1.5. CUSTO E SUPORTE ............................................................................................. 23
2.2.3.2. DESVANTAGENS ................................................................................................ 24
2.2.3.2.1. BAIXO DESEMPENHO NAS VARIADAS PLATAFORMAS ........................... 24
2.2.3.3. ALGORITMO RSA EM JAVA ............................................................................. 24
2.2.3.3.1. RESULTADOS ...................................................................................................... 24
2.3. ANDROID .............................................................................................................. 25
2.3.1. INTRODUÇÃO ...................................................................................................... 25
2.3.1.1. BREVE HISTÓRICO DA PLATAFORMA .......................................................... 25
2.3.2. CONCEITOS FUNDAMENTAIS ......................................................................... 26
2.3.2.1. COMPONENTES DO APLICATIVO ................................................................... 27
2.3.2.1.1. ACTIVITIES ............................................................................................................ 27
2.3.2.1.1.1. CICLO DE VIDA DE UMA ACTIVITY................................................................. 28
2.3.2.1.2. SERVICES .............................................................................................................. 29
2.3.2.1.3. PROVEDORES DE CONTEÚDO ......................................................................... 30
2.3.2.1.4. RECEPTORES DE BROADCAST ......................................................................... 31
2.3.2.2. ATIVANDO COMPONENTES ............................................................................. 31
2.3.2.3. O ARQUIVO MANIFESTO .................................................................................. 32
2.3.2.3.1. FILTROS ................................................................................................................ 32
2.3.2.3.2. PERMISSÕES ........................................................................................................ 32
3. APLICATIVO .............................................................................................34
3.1. PROBLEMAS ENCONTRADOS .......................................................................... 34
3.2. VISÃO GERAL DO APLICATIVO ...................................................................... 36
3.2.1. CRIPTOGRAFAR GERANDO AS CHAVES ...................................................... 37
3.2.2. CRIPTOGRAFAR COM CHAVE PÚBLICA ....................................................... 39
3.2.3. DESCRIPTOGRAFAR .......................................................................................... 40
4. TRABALHOS FUTUROS .........................................................................42
5. CONCLUSÃO .............................................................................................44
REFERÊNCIAS BIBLIOGRÁFICAS ........................................................................45
APÊNDICE A – O CÓDIGO........................................................................................51
1. INTRODUÇÃO
A necessidade de transportar mensagens mantendo a segurança das informações
é uma necessidade advinda das guerras, e a medida que o processo de envio da mensagem
foi se sofisticando, a maneira como se garantia sua segurança teve também que evoluir.
Surgiu, assim, a criptografia, com o objetivo de encriptar mensagens, tornando seu
conteúdo restrito àqueles que possuíam a senha das mensagens. Com a evolução da
tecnologia o transporte de informações de conteúdo restrito através de redes de
comunicações tornou-se comum, e a criptografia passou a ser aplicada aí, com o objetivo
de impedir que, ainda que interceptadas, as informações tivessem seu conteúdo revelado.
1.1. MOTIVAÇÃO
Manter a segurança das informações é um dos grandes desafios dos
desenvolvedores atuais. As informações transmitidas e armazenadas nos dispositivos
digitais se tornaram extremamente vulneráveis com o surgimento das redes e com a
disseminação da computação nos processos cotidianos. Assim, a manutenção do sigilo
das informações disponibilizadas na rede passou a ser imprescindível. Nesse cenário
surge a criptografia como uma ferramenta de extrema importância na manutenção do
sigilo das informações.
A Criptografia busca, em sua raiz, restringir o conteúdo da mensagem ao seu
remetente e destinatários, evitando que as informações sejam passadas a outros, caso a
mensagem seja interceptada em seu transporte. Atualmente, em meio à crescente
necessidade de manutenção da segurança, em concordância com o avanço tecnológico,
os algoritmos que encriptam dados têm sido amplamente desenvolvidos e aprimorados.
Ocorre que, paralelamente a isso, os trabalhos no sentido de desenvolver algoritmos que
decriptografem as mensagens têm também avançado.
Desenvolver, implementar e otimizar algoritmos que sejam seguros tem sido um
dos grandes desafios à segurança dos dados, motivando o estudo da área em todos os seus
níveis.
1.2. OBJETIVO
No contexto da Criptografia, o presente trabalho tem como objetivo implementar
o algoritmo de encriptação RSA em Java na arquitetura Android.
1.2.1. OBJETIVOS PRINCIPAIS
Para que se atinja o objetivo final de implementar o algoritmo RSA para Android,
definiram-se os seguintes objetivos principais, sendo esses requisitos ao produto final:
Desenvolver estudo acerca do algoritmo RSA: compreender o funcionamento
do algoritmo e o processo empregado para encriptar e decriptar mensagens;
Desenvolver estudo acerca da Linguagem Java: entender o funcionamento da
linguagem de programação a ser utilizada, vantagens e desvantagens no seu
emprego e buscar a melhor forma de empregá-la para a implementação do
algoritmo estudado;
Desenvolver código em Java do algoritmo para Android: pautado no estudo
anterior, implementar o algoritmo para Desktop;
Desenvolver estudo acerca do ambiente Android: entender como deverá
funcionar a adaptação do código já implementado em Desktop, como funciona
o ambiente Android de maneira global e específica para o aplicativo que
objetiva-se desenvolver;
Desenvolver Aplicativo em Android Lollipop de Criptografia RSA:
implementar o algoritmo já desenvolvido para Desktop fazendo as adaptações
necessárias para o ambiente Android.
1.3. CONTRIBUIÇÃO
Os estudos desenvolvidos assim como o viés prático do trabalho são de grande
valia para a formação dos alunos que trabalharam em seu desenvolvimento. A segurança
de dados é uma área ampla e de interesse geral, de modo que iniciar os estudos na área é
uma grande oportunidade de entender mais a fundo o papel e o valor da criptografia na
engenharia da computação e na engenharia de defesa. Além disso, a aplicação dos
conhecimentos teóricos buscados no ambiente Android torna o trabalho diferenciado,
uma vez que se tem a oportunidade de implementar o algoritmo em um ambiente cada
vez mais usual, desenvolvendo um produto novo.
Assim, o desenvolvimento do trabalho não somente aproxima os alunos do
contexto da engenharia de defesa, como também de novas habilidades na área de
programação, sendo de grande valor à formação dos mesmos.
1.4. ORGANIZAÇÃO
O presente trabalho encontra-se organizado segundo a seguinte estrutura:
1. Introdução;
2. Fundamentação teórica, onde encontram-se abordados os tópicos: RSA, Java e
Android;
3. Aplicativo, onde está descrito o funcionamento do aplicativo;
4. Análise crítica;
5. Conclusão; e
6. Referências Bibliográficas.
Deste modo, primeiro são desenvolvidos os fundamentos teóricos necessários
para o entendimento do algoritmo, bem como um breve estudo da linguagem Java e da
plataforma Android.
2. FUNDAMENTAÇÃO TEÓRICA
Para atingir o objetivo de desenvolver um algoritmo RSA no ambiente Android
lollipop com aplicação em Java, foram estudados os seguintes temas: RSA, Java e
Android.
2.1.1. INTRODUÇÃO
2.1.1.1. A CRIPTOGRAFIA
Onde há conflitos, há necessidade da proteção das informações. A ameaça de
interceptação de dados levou ao surgimento de códigos, de modo que apenas quem
escrevia e o destinatário legítimo poderiam entender o conteúdo transmitido. A
criptografia, surgiu assim, como um conjunto de técnicas que quando aplicadas,
conferiam segurança ao transporte das mensagens.
Com a globalização e a internet, o acesso às informações foi disseminado por
todo o mundo. Impedir a difusão de certos dados, passou a ser o enfoque de entidades
públicas e privadas, visando a proteção de seus sistemas e suas estratégias como um todo.
Chaves e algoritmos têm se tornado cada vez mais complexos e em contrapartida,
os métodos para a quebra deles tem evoluído de maneira cada vez mais acelerada. O
desenvolvimento de um código pode ser visto como uma luta evolutiva, assim que ele é
decifrado ou evolui, ou é extinto (SINGH, 2007). A batalha intelectual entre encriptadores
e decifradores tem se arrastado por toda a história e ainda se prolongará por muito tempo,
sendo ela a principal motivação para o estudo de métodos cada vez mais avançados para
encriptar e decriptar mensagens.
2.1.1.2. HISTÓRICO
Embora atualmente a criptografia tenha grande atuação no meio civil, protegendo
dados pessoais, esta evoluiu principalmente no meio militar. A necessidade que os
exércitos têm ao mesmo tempo de manter o sigilo de suas mensagens e de descobrir as
estratégias do inimigo trouxe vários matemáticos às linhas de batalha.
Em Guerras de Gália de Júlio César, César descreve que utilizou uma cifra de
substituição (neste caso cifra de César) para mandar uma mensagem para Cícero, que
estava cercado e prestes a se render.
Muitas estratégias só foram possíveis devido à criptografia, mas em contrapartida,
uma cifra fraca pode chegar a ser pior que a falta de uma. No Século XV, Maria, rainha
da Escócia, acreditando que tinha uma comunicação segura com Babigton, escreveu
explicitamente sobre suas intenções de matar Elizabeth, rainha da Inglaterra, acreditando
que sua comunicação era segura. Walsingham, por sua vez, não apenas decifrou as
mensagens, como as falsificou para conseguir informações sobre os cúmplices (SINGH,
2007).
Esse trata-se de um marco na criptoanálise, ciência que permite decifrar uma
mensagem sem o conhecimento de sua chave, dando-lhe pela primeira vez grande
relevância. Os primeiros relatos de quebra surgiram com os árabes na descoberta de um
método para decifrar a substituição monoalfabética, por volta do século X.
A criptografia Alemã merece destaque. Durante a Primeira Guerra Mundial, o
rádio era uma invenção recente e todos os lados estavam ávidos para explorar seu poder,
mas não havia maneira certa de como garantir a segurança. Os alemães então, um pouco
antes da grande Ofensiva Alemã (21 de março de 1918), introduziram a cifra ADFGVX,
uma mistura complexa de substituição e transposição. Os aliados, porém, conseguiram
decifrar uma mensagem. Os alemães perderam assim seu elemento surpresa e foram
obrigados a recuar.
A criptografia evoluiu e foram desenvolvidas máquinas de cifragem. Um inventor
alemão, Arthur Scherbius, com o objetivo de substituir os sistemas de criptografia
inadequados empregados na Primeira Guerra, criou uma máquina criptográfica chamada
Enigma. Em 1925 Scherbius começou uma produção em massa das máquinas para o
exército alemão (SINGH, 2007).
Nas duas décadas seguintes, os alemães compraram 30 mil máquinas Enigma e a
invenção se tornou o sistema mais seguro de criptografia do mundo, e por um momento
parecia que o Enigma desempenharia um papel vital na vitória nazista, mas ao ser
decifrado acabou colaborando com a queda precoce de Hitler.
Os criptoanalistas aliados trabalhavam dia e noite tentando dominar as cifras
germânicas; Rejewski, um criptoanalista polonês até conseguiu quebrar uma versão
inicial do Enigma, através de uma adaptação capaz de verificar cada um dos ajustes até
encontrar um correspondente (os nazistas mudavam a chave diariamente). Mas as
habilidades de Rejewski acabaram quando os alemães aumentaram a segurança do
enigma e o número de chaves possível aumentou para 159.000.000.000.000.000.000. A
máquina alemã tornou-se mais uma vez invulnerável e dessa vez parecia ser
humanamente impossível quebrá-la (SINGH, 2007).
Apenas Alan Turing, fundador conceitual da computação moderna, foi capaz de
quebrar o Enigma novamente. Uma equipe foi montada em Bletchley Park para decifrar
a Enigma e lá Turing construiu uma máquina, capaz de resolver problemas matemáticos.
Os aliados conseguiram quebrar o enigma e a partir daí um serviço de inteligência foi
criado de modo que os alemães não percebessem que seu sistema não era mais seguro. A
quebra do enigma não só foi dita responsável por encurtar a guerra em 2 anos, como deu
início à criptografia moderna.
2.1.1.3. SOBRE O ALGORITMO RSA
Dentre as diversas técnicas de criptografias ainda empregadas na atualidade,
mantém-se em destaque a empregada no chamado Algoritmo RSA, cujo foco desse
relatório será atribuído.
O algoritmo RSA é assim chamado por ter sido criado por 3 professores do
Instituto de Tecnologia de Massachussets (MIT), Ronald Rivest, Adi Shamir e Leonard
Adleman. Ele é conhecido por ser, atualmente, um dos métodos mais seguros e eficientes
de codificação que se utiliza da implementação de chaves assimétricas e é baseado na
Teoria dos Números.
Ao utilizar duas chaves, uma pública e uma privada, o RSA possui a capacidade
de atuar diretamente na internet, como no envio de e-mails e compras on-line. Por mais
que uma das chaves seja exposta ao público no intento de codificar as mensagens
desejadas, a secreta é necessária para a decodificação, mantendo assim a segurança da
mensagem.
Além disso, o RSA é caracterizado principalmente pela utilização de números
primos muito grandes na criação das chaves, o que acaba por tornar a decifração da chave
privada inviável se forem empregados algoritmos convencionais de fatoração.
2.1.2. CONCEITOS E ANÁLISES TEÓRICAS
2.1.2.1. CRIPTOGRAFIA MODERNA
A criptografia tem por base números inteiros, enquanto o computador utiliza
números binários. Para que a conversão entre os sistemas seja viável, foi desenvolvido o
American Standard Code for Information Interchange, ou, simplesmente, tabela ASCII,
empregada em computadores pessoais desde a década de 60.
A tabela original trabalhava apenas com 7 bits, suportando apenas a língua inglesa.
Para que desse suporte para todos os idiomas, foi expandida para 8 bits. Hoje, emprega-
se a chamada ASCII ESTENDIDA, englobando 256 caracteres, entre o alfabeto latino
minúsculo e maiúsculo, acentos, pontuações e outros símbolos.
A criptografia moderna é dividida em duas vertentes, a de chaves simétricas e de
chaves assimétricas. No primeiro tipo, um determinado algoritmo utiliza-se de uma chave
para converter as informações recebidas em um conjunto de bits aparentemente
aleatórios; o mesmo algoritmo utiliza-se da chave para decriptar a mensagem. A
necessidade de uma mesma chave para encriptar ou decriptar uma informação, faz com
que a demanda de proteção dessa cresça, atrelando a esse tipo de criptografia
características particulares.
Já no caso da chave assimétrica, distinguem-se duas chaves, uma para a
encriptação, a chamada chave pública, e a outra para a decifração da mensagem, chamada
chave privada; como pode ser deduzido a partir de seus nomes, a primeira é de domínio
ostensivo, enquanto a segunda deve ser mantida sob sigilo. O sistema assimétrico tende
a ser mais lento, uma vez que engloba cálculos extensos e problemas matemáticos sem
solução computacional otimizada – a não simetria entre as chaves, faz com que o processo
de quebra seja mais lento e exija maior esforço computacional, o que é agravado devido
aos algoritmos utilizados, que costumam envolver problemas matemáticos que possuem
limitação para solução com auxílio do computador.
O Algoritmo RSA foi o primeiro algoritmo assimétrico mundialmente empregado
como padrão, sendo utilizado até os dias atuais, inclusive no meio computacional.
2.1.2.2. O ALGORITMO RSA
2.1.2.2.1. EMBASAMENTO MATEMÁTICO
2.1.2.2.1.1. FUNÇÃO PHI DE EULER
A função Φ(𝑛), chamada Phi de Euler, denota o número de inteiros positivos que
não excedem 𝐧 e que são primos com 𝐧. Para o cálculo de Φ(𝑛), temos:
Teorema: Se o inteiro 𝐧 > 𝟏 tem a fatoração em primos dada por:
𝑛 = 𝑝1𝑘1 ⋅ 𝑝2
𝑘2 ⋅ … ⋅ 𝑝𝑟𝑘𝑟
Então:
Φ(𝑛) = 𝑛 ⋅ (1 −1
𝑝1) ⋅ (1 −
1
𝑝2) ⋅ … ⋅ (1 −
1
𝑝𝑟)
Para o emprego no Algoritmo RSA, em especial, todo 𝐧 utilizado deverá ser da forma
𝐧 = 𝐩𝟏 ⋅ 𝐩𝟐, de modo que a fórmula acima, poderá ser reduzida a:
Φ(𝑛) = (𝑝1 − 1)(𝑝2 − 1) (1)
2.1.2.2.1.2. O ALGORITMO ESTENDIDO DE EUCLIDES
Considere o problema de se calcular 𝐦 e 𝐧 na equação:
𝑎 ⋅ 𝑚 + 𝑏 ⋅ 𝑛 = 𝑚𝑑𝑐(𝑎, 𝑏)
O Algoritmo Estendido Euclidiano se propõe a resolver tal questão.
Seja 𝐚 > 𝐛, podemos escrever:
𝑎 = 𝑏 ⋅ 𝑞1 + 𝑟1 𝑟1 = 𝑎𝑥1 + 𝑏𝑦1
𝑏 = 𝑟1 ⋅ 𝑞2 + 𝑟2 𝑟2 = 𝑎𝑥2 + 𝑏𝑦2
𝑟1 = 𝑟2 ⋅ 𝑞3 + 𝑟3 𝑟3 = 𝑎𝑥3 + 𝑏𝑦3
𝑟2 = 𝑟3 ⋅ 𝑞4 + 𝑟4 𝑟4 = 𝑎𝑥4 + 𝑏𝑦4
𝑟3 = 𝑟4 ⋅ 𝑞5 + 𝑟5 𝑟5 = 𝑎𝑥5 + 𝑏𝑦5
… …
𝑟𝑛−3 = 𝑟𝑛−2 ⋅ 𝑞𝑛−1 + 𝑟𝑛−1 𝑟𝑛−1 = 𝑎𝑥𝑛−1 + 𝑏𝑦𝑛−1
𝑟𝑛−2 = 𝑟𝑛−1 ⋅ 𝑞𝑛 𝑟𝑛 = 0
Onde 𝐫𝐧 = 𝟎, 𝐫𝐧−𝟏 o 𝐦𝐝𝐜(𝐚, 𝐛) e os números 𝐱𝐢 e 𝐲𝐢, com 𝐢 = 𝟏, 𝟐, 𝟑, … , 𝐧 são
inteiros a determinar.
Para determinar valores de 𝐱𝐣 e 𝐲𝐣, supondo que todos os valores anteriores estejam
preenchidos, pode-se escrever com base nas equações acima apresentadas:
𝑟𝑗 = 𝑟𝑗−2 − 𝑟𝑗−1 ⋅ 𝑞𝑗
Mas,
𝑟𝑗−2 = 𝑎𝑥𝑗−2 + 𝑏𝑦𝑗−2
𝑟𝑗−1 = 𝑎𝑥𝑗−1 + 𝑏𝑦𝑗−1
Logo:
𝑟𝑗 = 𝑎(𝑥𝑗−2 − 𝑞𝑗𝑥𝑗−1) + 𝑏(𝑦𝑗−2 − 𝑞𝑗𝑦𝑗−1)
E assim:
𝑥𝑗 = 𝑥𝑗−2 − 𝑞𝑗𝑥𝑗−1 (2)
𝑦𝑗 = 𝑦𝑗−2 − 𝑞𝑗𝑦𝑗−1 (3)
Ao final, tem-se que:
𝑟𝑛−1 = 𝑎𝑥𝑛−1 + 𝑏𝑦𝑛−1 ∴ 𝑚𝑑𝑐(𝑎, 𝑏) = 𝑎𝑥𝑛−1 + 𝑏𝑦𝑛−1
Onde 𝐱𝐧−𝟏 e 𝐲𝐧−𝟏 são definidos por iterações contínuas das equações (1) e (2),
resolvendo o nosso problema inicial.
O problema inicial pode ser reescrito, sem perda de generalidade, da seguinte forma:
𝑏 ⋅ 𝑛 ≡ 𝑚𝑑𝑐(𝑎, 𝑏) 𝑚𝑜𝑑 𝑎
Nos casos para a criptografia RSA, em especial, 𝐦𝐝𝐜(𝐚, 𝐛) = 𝟏, e objetiva-se
encontrar o valor de 𝐧, como será descrito nos tópicos seguintes.
2.1.2.2.2. OBTENÇÃO DAS CHAVES
Para gerar-se as chaves deve-se seguir uma sequência de passos:
1) Deve-se escolher dois números primos 𝒑 e 𝒒, dando preferência para aqueles cuja
ordem é muito grande;
2) Realiza-se a operação 𝒏 = 𝒑 ⋅ 𝒒;
3) Calcula-se a função de Euler, que expõe a quantidade de co-primos menores que
n: Φ(𝑛) = (𝑝 − 1)(𝑞 − 1), para 𝑝 e 𝑞 primos;
4) Escolhe-se um valor inteiro 𝑒 o qual 1 < 𝑒 < Φ(𝑛) e 𝑚𝑑𝑐(Φ(𝑛); 𝑒) = 1; e
5) Calcula-se 𝒅 de tal forma que 𝒅 ⋅ 𝒆 ≡ 𝟏 𝒎𝒐𝒅 Φ(𝒏);
Dessa forma, tem-se a chave pública (𝒏, 𝒆) e a privada (𝒅, 𝒑, 𝒒) e, a partir delas,
pode-se iniciar o processo de cifragem e decifragem.
2.1.2.2.3. CIFRAGEM E DECIFRAGEM
Para que se inicie o processor de cifragem é necessário que todos os símbolos sejam
números; para tanto, em meio computacional e em outros meios, é necessário,
inicialmente, converter cada letra ou símbolo em um número com base na tabela ASCII.
Depois, esses números são agrupados, formando um número único chamado m. Se m for
maior que n, então ele deve ser dividido em blocos de modo que cada um seja menor que
n;
A cifragem e a decifragem devem ser executadas seguindo o seguinte método:
Cifragem: 𝑐 ≡ 𝑚𝑑𝑚𝑜𝑑 𝑛
Decifragem: 𝑚 ≡ 𝑐𝑒𝑚𝑜𝑑 𝑛
Onde 𝐜 é a mensagem encriptada.
2.1.2.2.4. VULNERABILIDADES
Apesar de ser um dos algoritmos mais seguros do mundo o RSA possui algumas
vulnerabilidades. Fatoração de números inteiros muito grandes, pequenos expoentes,
exposição parcial da chave privada e ataques temporais são apenas algumas delas,
segundo Dan Boneh (1999).
2.1.2.2.4.1. FATORANDO NÚMEROS PRIMOS MUITO GRANDES
Um exemplo de ataque de força bruta ao RSA é uma fatoração do módulo n, a fim
de chegar ao expoente de decriptografia. Essa ainda é uma ameaça distante da realidade,
pois, mesmo com a melhora dos algoritmos de fatoração, a tecnologia atual ainda tem
sérias dificuldades em fatorar n, se os primos forem corretamente escolhidos.
Em 1997, Martin Gardner publicou na Scientific American que seriam necessários 40
trilhões de anos para fatorar n, fazendo uso do poder computacional da época, porém a
tarefa levou apenas 30 anos para ser realizada (PAAR, 2009).
Uma discussão surgiu sobre qual seria o tamanho seguro para o módulo n usado no
RSA. Acredita-se que padrões de 1024 bits possam ser fatorados em 10 a 15 anos ou até
mais rápido por agências de inteligência. Hoje, são aconselhados padrões de 2048 ou
4096 bits (PAAR, 2009).
2.1.2.2.4.2. PEQUENOS EXPOENTES
Com o objetivo de reduzir o tempo de decriptografia, pode-se tentar usar um valor
pequeno de d para a chave privada e de e para a chave pública. A especificação do
algoritmo sugere valores aleatórios. Quanto mais difícil de se encontrar as chaves melhor,
e enquanto a descoberta do e geralmente não leva a quebra total do RSA, a menos que a
mensagem seja pequena e o ataque de Coppersmith utilizado, se o d for descoberto a
mensagem estará decifrada.
Sugere-se um valor de e = 216 + 1 = 65537, para tornar o sistema mais seguro
(WEINER, 1990).
2.1.2.2.4.3. EXPOSIÇÃO PARCIAL DA CHAVE PRIVADA
Não é apenas através de uma escolha de um pequeno d que o RSA pode ser quebrado.
Se uma fração da chave privada for exposta é possível reconstruir toda a chave. No
entanto isso apenas é possível quando e < n1/2. (BONEH, 1998).
Por isso é importante gerar não só uma chave grande e aleatória, como também
proteger a chave privada
2.1.2.2.4.4. ATAQUES TEMPORAIS
Estes ataques não são decorrentes de falhas ou artifícios matemáticos, mas sim de
vulnerabilidades na implementação computacional.
Se o tempo de decriptação for precisamente medido, a chave privada d pode ser
deduzida rapidamente, mesmo que a chave esteja devidamente armazenada (KOCHER,
2006).
2.1.2.2.5. APLICAÇÕES
Devido à incapacidade de fatorar primos muito grandes com os sistemas
computacionais atuais, o algoritmo RSA é um dos mais usados, principalmente em dados
enviados pela internet.
O algoritmo é o único capaz de implementar assinatura digital e troca de chaves
(dentre os mais comuns). Ele vem sendo utilizado em várias aplicações de segurança
envolvendo camadas altas, certificados e assinaturas digitais, S/MIME e PGP, camadas
de transporte, TLS, camada de rede, IPSec, e até nas camadas de segurança mais
inferiores, como o protocolo SSL.
2.1.2.2.5.1. ASSINATURA DIGITAL
Uma assinatura digital tem que verificar as propriedades:
As assinaturas são únicas para cada usuário e não podem ser forjadas;
O emissor não pode negar o envio de uma mensagem que contenha sua assinatura;
e,
O receptor não pode modificar uma assinatura nem retirá-la e colocá-la em outra
mensagem.
A assinatura digital é, então, uma garantia de que o documento é uma cópia verdadeira
e correta do original, garantindo também a autoria.
Todo processo de geração e verificação da assinatura pode ser feito utilizando o
algoritmo RSA. Para que um documento ou assinatura adulterada não seja detectada, o
atacante deve ter a chave privada de quem assinou o documento (BRAGHETTI, 2003).
2.1.2.2.5.2. CERTIFICADO DIGITAL
Ao receber uma chave pública deve-se certificar se a chave seja realmente
proveniente da pessoa certa. Sem uma garantia, um intruso pode convencer os
interlocutores de que chaves públicas falsas pertencem a eles e se fazer passar por ambos.
O intruso pode, então, decifrar todas as mensagens, cifrá-las novamente, ou ainda
substituí-las por outras mensagens.
Os certificados de chave pública são uma garantia para evitar esse ataque e consistem
em chaves públicas assinadas. Assim, um certificado digital é um documento eletrônico,
assinado digitalmente por uma terceira parte confiável, que associa o nome de uma pessoa
ou instituição a uma chave de criptografia pública (MAIA, PAGLIUSI).
2.1.2.2.5.3. S/MIME E PGP
O S/MIME (Security Multipurpose Mail Extension) e o PGP (Pretty Good Privacy)
são as duas aplicações mais utilizadas em implementações de segurança em correio
eletrônico.
O S/MIME baseia-se no standart MIME, cujo objetivo é permitir incluir na
mensagem eletrônica anexos em ASCII, sendo possível acrescentar anexos de todos os
tipos aos correios eletrônicos.
Já o PGP, é um software que assegura privacidade criptográfica e autenticação para
comunicação de dados. Ele segue um formato OpenPGP, que utiliza um grande número
de algoritmos, dentre eles RSA (GARFINKEL, 1991).
2.1.2.2.5.4. SSL/TLS
O SSL (Secure Socket Locker) é uma camada de protocolo de rede, cuja
responsabilidade é gerenciar um canal de comunicação seguro entre o cliente e o servidor.
Foi desenvolvido pela Netscape Communications Corporation e atualmente é
implementado na maioria dos navegadores. A palavra-chave “https://”, por exemplo,
significa http + SSL, sites que apresentam essa palavra-chave, então, possuem uma
camada de segurança (BRAGHETTO, 2012).
Já o TLS (Transport Layer Security), é uma versão mais recente e segue os mesmos
moldes do SSL, protegendo transferência de dados. Ambas as camadas utilizam o RSA
na troca de chaves.
2.1.2.2.5.5. IPSEC
O IPSec é um conjunto de padrões utilizados para garantir uma comunicação
segura entre dois ou mais hosts, mesmo que as informações estejam sendo enviadas
através de um meio não seguro, como a Internet (NIST, ERICSSON, 2011).
Um exemplo é o VPN (Rede Privada Virtual), um túnel fechado entre um
computador e um servidor, onde ambos têm uma chave que criptografa todos os dados
que passem por este túnel.
2.2. JAVA
2.2.1. INTRODUÇÃO
O Java foi projetado para permitir o desenvolvimento de aplicações portáteis de
alto desempenho para uma ampla variedade de plataformas de computação. Resolvia,
assim, o problema do desenvolvimento de novos códigos devido à mudança do sistema
operacional utilizado. Disponibilizando aplicações em ambientes heterogêneos, é
possível fornecer mais serviços e aumentar a produtividade, comunicação e colaboração
do usuário, reduzindo o custo de propriedade das aplicações da empresa e do consumidor.
2.2.1.1. BREVE HISTÓRICO DA LINGUAGEM
Na década de 90, muitos eram os problemas enfrentados pelos programadores.
Dentre eles, destacavam-se o uso de ponteiros, a falta de memória, o custo financeiro e a
necessidade de ter que reescrever parte do código ao mudar de sistema operacional. A
linguagem Java surgiu para tentar sanar esses problemas, frequentes em outras
linguagens. Veio, inicialmente, com o objetivo principal de evitar a reescrita de códigos,
direcionados para os diferentes sistemas operacionais; queria desenvolver um código
universal e assim o fez. A ideia, porém, não foi bem vista no mercado, e foi logo
esquecida, sendo ressuscitada ainda na mesma década, com o advento da internet. Assim,
seu lançamento posterior foi focado no uso de clientes web, para rodar pequenas
aplicações, mas acabou ganhando destaque no lado do servidor.
De maneira mais específica, em 1991, James Gosling, Patrick Naughton, Mike
Sheridan juntos com dois fundadores da Sun, Andy Bechtolsheim e Bill Joy formaram o
Green Team, um projeto com o objetivo de desenvolver um sistema que os permitisse
construir uma rede distribuída e heterogênea de dispositivos eletrônicos voltados para o
consumidor final, todos se comunicando entre si.
O desafio era criar um ambiente de software que fosse interessante para o mercado
consumidor e ao mesmo tempo atraente para desenvolvedores de software. Gosling,
responsável pela linguagem, resolveu criar uma nova que tivesse uma estrutura similar a
C/C++, que fosse segura (sem ponteiros), confiável, multiplataforma e interpretada
(convertida em um formato intermediário, os bytecodes). Chamada anteriormente de
Greentalk e Oak, teve seu nome alterado para Java por questões de marketing.
Por volta de 1994, com a oportunidade representada pela Internet e pela Web, o
time resolveu disponibilizar o código fonte do interpretador Oak na internet e criaram um
navegador, chamado WebRunner, reescreveram o compilador em Oak e se prepararam
para lançar o projeto.
Em 1995, durante o evento Sun World, John Gage anunciou a tecnologia Java
para o mundo. A web, pela primeira vez, era capaz de executar aplicações.
Quando a versão 1.0 foi anunciada, em 1996, 15 empresas já haviam licenciado a
tecnologia Java, incluindo a IBM, Silicon Graphics, Netscape, Oracle e Toshiba. Até a
Microsoft demonstrou interesse de incorporar o Java em seu Browser.
Enquanto Java 1.1 incorporou diversas funcionalidades como o JavaBeans, JDBC
e o os compiladores Just In Time (JIT), o Java 1.2, ou simplesmente Java 2 evoluiu de
uma linguagem de programação para uma grande família de tecnologias, todas baseadas
na linguagem Java e no conceito de multiplataformas.
O Java 2 foi dividido em 3 versões. A J2SE, Standart Edition, base da plataforma,
a J2EE, Enterprise Edition, voltada para aplicações corporativas e a J2ME, Micro Edition,
uma versão reduzida, para pequenos aparelhos. Empresas como IBM, BEA e Oracle
lançaram seus servidores de aplicação Java EE (O “2” saiu do nome em 2006) e com o
surgimento de servidores de aplicação Open Source, a tecnologia se tornou cada vez mais
popular.
2.2.2. CONCEITOS
2.2.2.1. JVM – JAVA VIRTUAL MACHINE
A máquina virtual Java (no inglês, Java Virtual Machine - JVM) é um programa
responsável pelo gerenciamento dos aplicativos, à medida que são executados. Ela
carrega e executa os aplicativos Java, convertendo o ByteCode, código gerado pelo
compilador Java (javac), em executável de máquina.
Por meio dela, programas escritos em Java podem funcionar em qualquer plataforma
de software e hardware, desde que esta possua uma versão da JVM.
Formalmente, existem três noções de JVM: Specification (especificação),
implementation (implementação) e instance (instância). Portar uma única especificação
garante que todas as implementações são interoperáveis. Uma implementação JVM é um
programa que atinge todas as requisições da especificação JVM. Uma instância da JVM
é um processo que executa um programa compilado em ByteCode.
Além de interpretar código, a JVM é responsável pela execução de pilhas,
gerenciamento de memórias, threads e etc., ou seja, comporta-se como um “computador
virtual”.
2.2.2.2. ORIENTAÇÃO A OBJETO
A linguagem Java é um exemplos de linguagem orientada a objeto, e essa
característica representa um grande diferencial para a linguagem.
A programação orientada a objeto trata-se de um paradigma de desenvolvimento de
software empregado em linguagens como C++ e Java. Diferencia-se da programação
estruturada a medida que viabiliza a reutilização do código e possibilita a escrita do
mesmo de modo muito mais próximo do pensamento cotidiano.
Define-se, pois, objetos, no âmbito da programação, de maneira muito semelhante
ao que é feito no cotidiano. Objetos são entidades, com características determinadas, que
os diferenciam entre si. Em programação, consideram-se classes de objetos, as quais
descrevem atributos gerais que todos os objetos daquele tipo devem possuir. A partir da
diferenciação desses atributos, são criados objetos distintos. Podem ser desenvolvidas
ainda, operações próprias para cada classe que se cria, que são como “comportamentos”
particulares da classe. Essas operações são denominadas métodos. Um método é uma
implementação específica de uma operação para uma determinada classe.
Define-se ainda herança, como um mecanismo existente no paradigma orientado
a objetos que viabiliza a reutilização dos atributos (estrutura) e dos métodos
(comportamentos) de uma classe para a definição de uma nova, criando uma ordem
hierárquica entre superclasses e subclasses. Há múltiplas possibilidades de operações com
herança, envolvendo, por exemplo, a herança múltipla, em que uma subclasse é definida
com base em mais de uma superclasse.
No ambiente de programação orientada a objetos, utiliza-se ainda o conceito de
polimorfismo. Segundo tal conceito, a mesma operação, pode se comportar de maneira
diferente em classes diferentes. O polimorfismo é empregado de maneira fortemente
atrelada à herança. Ele viabiliza que operações empregadas em superclasses também o
sejam em subclasses, de maneira alterada. Assim, a linguagem de programação deve ser
capaz de selecionar o método correto com base no nome da operação - as operações são
diferenciadas entre as superclasses e as subclasses; para isso usam-se funções virtuais,
que funcionam como redefinições de funções previamente estabelecidas para as
superclasses.
Como base nesses cinco conceitos fundamentais (classes, atributos, métodos,
herança e polimorfismo), são definidas as principais diretrizes da programação orientada
a objetos.
2.2.3. VANTAGENS E DESVANTAGENS DO JAVA
Sabe-se que, hoje em dia, não existe uma linguagem melhor que a outra, mas
linguagens mais propícias para certa situação. Visto isso, segue algumas vantagens e
desvantagens de se utilizar JAVA.
2.2.3.1. VANTAGENS
2.2.3.1.1. TRATAMENTO DE EXCEÇÕES
O fato do Java possuir recursos para lidar com exceções, evitando que o programa
finalize subitamente sem que o problema esteja claro, faz com que a linguagem se torne
mais confiável para o usuário. Graças a tais recursos o programador é apto para prever
um possível erro e tomar as medidas necessárias.
2.2.3.1.2. GARBAGE COLLECTOR
Os programas escritos em Java liberam automaticamente a memória alocada e não
utilizada, pois fazem uso do Garbage Collector que, de tempos em tempos, percorre a
memória a procura de objetos que não possuem mais uma referência válida. Esses objetos
são considerados como “lixo” e são coletados para liberação da memória ocupada. Por
ser um processo automático que pode ser forçado a acontecer, o Garbage Collector
otimiza, e muito, a memória consumida do programa.
2.2.3.1.3. PORTABILIDADE
Java é considerado como uma linguagem portátil, pois, como seu código-fonte é
compilado para bytecode e esse é interpretado pela JVM, a linguagem em si se torna
independente da plataforma que está sendo utilizada. Ou seja, o mesmo código pode ser
utilizado para diferentes sistemas operacionais.
2.2.3.1.4. COMPILAÇÃO JIT (JUST-IN-TIME)
Também conhecida por tradução dinâmica, just-in-time combina a velocidade do
código compilado à flexibilidade da interpretação e permite algumas otimizações que não
são possíveis em compilações estáticas.
A máquina virtual responsável pela execução dos bytecodes resultantes da
compilação do programa fonte realiza a tradução desse bytecodes enquanto o executa.
Cada trecho do código é traduzido no instante que está para ser executado pela primeira
vez.
Esse mecanismo apresenta um desempenho superior ao processo clássico de
interpretação, uma vez que o código de máquina resultante do JIT é armazenado na
memória, garantindo que o trecho de código não seja recompilado ou reinterpretado.
2.2.3.1.5. CUSTO E SUPORTE
O custo do Java é praticamente zero, os editores e ambientes de produção são
gratuitos (NetBeans, Eclipse, Jcreator, entre outros), assim como os servidores de
aplicação (TomCat, Jboss, Jetty e outros). O Java é padronizado e mantido pela JCP (Java
Community Process), que recebe contribuição de diversas empresas: Oracle, IBM,
Novell, Xerox etc.
Além disso, por ser a comunidade mais extensa, a tecnologia Java tem um bom
suporte. Existem inúmeros JUGs (Java User Groups), que promovem eventos,
disponibilizam material, artigos, revistas e fórum de discussões.
2.2.3.2. DESVANTAGENS
2.2.3.2.1. BAIXO DESEMPENHO NAS VARIADAS PLATAFORMAS
Por ser portátil, Java não tem como suprir as mais variadas necessidades
encontradas em cada plataforma diferente e, dessa forma, ele tem carência de eficiência
quando comparado a outras linguagens. Afinal, é natural que ao adotar um caráter
genérico um produto sofra com deficiência de qualidade específica.
2.2.3.3. ALGORITMO RSA EM JAVA
Com base no algoritmo de encriptação anteriormente apresentado, e utilizando as
bibliotecas e funções convenientes da linguagem Java junto com o programa Eclipse, foi
desenvolvido um código para a encriptação de mensagens (APÊNDICE A).
Tomando como base a velocidade de processamento do algoritmo RSA,
anteriormente comentada, não é recomendada a utilização do algoritmo para a encriptação
de mensagens completas, pois o procedimento pode ser extremamente lento; pode-se
utilizar o método, porém para encriptar a chave de um método mais simples que pode ser
empregado na mensagem. Ou seja, a melhor maneira de utilizar o RSA é criar um
envelope digital. De qualquer forma, o algoritmo desenvolvido foi pensado de modo
simples visando permitir a encriptação e decriptação de arquivos um pouco maiores, sem
grandes atrasos no sistema.
2.2.3.3.1. RESULTADOS
O códico descrito no APÊNDICE A foi executado e considerando que o texto do
arquivo “Teste.txt” era “Teste 27, torcendo para que funcione!”, obteve-se a seguinte
resposta:
Mensagem a ser criptografada: Teste 27, torcendo para que funcione!
Conversão da mensagem para bytes:
8410111511610132505544321161111149910111010011132112971149732113117101
321021171109910511111010133
Mensagem encriptada em Bytes: 8266-119-235612497-496343-46-12-1251-
144878474852-1135691-125101-56-116-73-55-1735-120-2524116-122527-
7010543559212440-81-11964101-96-152-2-27803107-89-7769-89-2071-97-53-93-
117124-869733642028127-7612266-49665357-4-31-1-1123619-50-4640-41123-3892-
49120-6765-60-17-125-80-104793711614541205017-88-124-2493100-7856-70-
207891-34-86-11586-5593-1549-1830-33-35-36-416167-50-22-1012543546-119-39-2-
44-111552-5412-73-31-225-5993726-48-1933-66-87-98-62-113-98-96-8973-58-54-
3879-96-71478635-114-45-84-43-77-29528433-26-122-14-14-90-96-42-8550-17-52-
10661-61-76-141857-80-10749-125-80-101118-78-60-91154-53-27378914120-9-
12698110-824337-31113-90772735-31-47-88-6229-388-3967-9685-105-20-79
String Decriptada em Bytes:
8410111511610132505544321161111149910111010011132112971149732113117101
321021171109910511111010133
Decrypted String: Teste 27, torcendo para que funcione!
CONSTRUÍDO COM SUCESSO (tempo total: 1 segundo)
O tempo de construção foi considerado bom, e a encriptação e decriptação
ocorreram sem maiores problemas, uma vez que a mensagem utilizada era pequena, não
sendo identificados os problemas previstos, na teoria, para compilação do algoritmo.
2.3. ANDROID
2.3.1. INTRODUÇÃO
O sistema operacional móvel Android é o mais utilizado em todo o mundo ―
segundo pesquisas da StatCounter Global Stats (2015), está presente não apenas em
smartphones, como também em tablets, notebooks, câmeras, SmartTVs, videogames e
muitos outros dispositivos. O Android revolucionou totalmente o conceito de telefone e
tudo isso nos últimos 7 anos, quando o primeiro dispositivo foi lançado (WILSON, 2013).
2.3.1.1. BREVE HISTÓRICO DA PLATAFORMA
Em 2003, Andy Rubin, Rich Miner, Nick Sears e Chris White fundaram em Palo
Alto, Califórnia a Android Inc. Rubin, então, definiu a empresa como “Dispositivos
móveis mais inteligentes e que estejam mais cientes das preferências e da localização do
seu dono”.
Por verem um mercado mais amplo, eles decidiram focar em mobile e ofereceram
um novo meio de sistema operacional móvel, o Open Source, baseado no Kernel Linux.
A ideia era ser um sistema gratuito e simples aos desenvolvedores.
Em 2005, o Google comprou a Android Inc, e nasceu a Google Mobile Division.
Surgiram os primeiros contratos de parceria com fabricantes de hardware e software e o
Google prometeu um sistema flexível e atualizável.
O protótipo, com previsão de lançamento para 2006, parecia um BlackBerry, sem
touchscreen e operando com teclado QWERTY. Mas ao ver os lançamentos dos
concorrentes o Google redesenhou seu modelo e em 22 de outubro de 2008 foi lançado o
primeiro Android comercial do mercado, rodando em um HTC Dream.
O Google então ofereceu 10 milhões de dólares aos desenvolvedores que
conseguissem realizar os melhores aplicativos para Android, levando em consideração a
primeira versão do Android SDK, surgiu assim a versão 1.0.
A plataforma está sempre sendo atualizada e suas versões, com nomes em ordem
alfabética e homenageando doces (Menos a Alpha e Beta), sempre apresentam melhorias
e inovações.
A versão utilizada neste trabalho é a 5.1, o Android Lollipop. Entre suas melhorias
tem-se: suporte para processadores 64 bits, introdução da nova diretriz de design do
Android (Material Design) e substituição da máquina virtual Dalvik por ART.
A versão atual, o Android 6.0, foi nomeada de Marshmallow. Entre suas melhorias
há um novo sistema de permissões, semelhante ao do iPhone e um novo gerenciamento
de energia, um suporte nativo para as digitais. Porém quanto mais recente a versão menos
aparelhos são contemplados.
2.3.2. CONCEITOS FUNDAMENTAIS
Os aplicativos Android são escritos na linguagem Java, o Android SDK compila o
código para APK: um Android Package, com extensão .apk. Ele contém todo o conteúdo
e é o arquivo que os dispositivos Android usam para instalar o aplicativo.
O sistema operacional Android é um sistema multiusuário Linux e cada aplicativo é
um usuário diferente com um ID designado pelo sistema. O sistema, então, estabelece
permissões para todos os aquivos no app e apenas o ID designado pode acessá-los.
Cada processo tem sua máquina virtual (VM) própria e cada aplicativo roda em seu
próprio processo Linux. O Android começa o processo quando algum componente do
aplicativo precisa ser executado e o encerra quando não é mais necessário ou para
recuperar memória.
É o princípio do “menor privilégio”, cada aplicativo tem acesso apenas aos
componentes que precisa para fazer seu trabalho, nada mais.
Contudo, há meios para um aplicativo acessar informações de outros ou os serviços
do sistema. Se os aplicativos compartilharem a mesma ID, o mesmo processo Linux e a
mesma VM, eles podem acessar os arquivos um do outro.
Além disso, um aplicativo pode pedir permissão ao usuário para acessar informações
como contatos, mensagens, cartão SD, câmera etc.
2.3.2.1. COMPONENTES DO APLICATIVO
Cada componente do aplicativo funciona como um ponto diferente de entrada do
sistema; nem todos esses pontos, porém, são entradas para o usuário, sendo alguns
interdependentes e tendo cada um uma função específica. São 4 tipos de componentes,
cada um com um propósito e ciclo de vida diferente.
2.3.2.1.1. ACTIVITIES
Uma activity representa uma tela única com a qual os usuários podem interagir, a
fim de fazer algo. Por exemplo, um aplicativo de e-mail pode ter uma activity para criar
um e-mail, outra para mostrar a caixa de entrada e outra para ler os e-mails.
Um aplicativo consiste normalmente de várias activities frouxamente ligadas, elas
trabalham em coesão, mas são independentes. Cada vez que uma nova começa, a anterior
é interrompida, mas o sistema a preserva em uma pilha (a “pilha de retorno”). A pilha usa
um mecanismo de fila, então quando o usuário pressiona a tecla back, a activity é
removida da pilha e retoma a anterior.
Um outro aplicativo, se tiver permissão, pode começar uma dessas activities e
cada activity pode começar outra.
Uma activity é implementada como uma subclasse de Activity.
2.3.2.1.1.1. CICLO DE VIDA DE UMA ACTIVITY
Toda activity tem um ciclo de vida, ela pode existir em basicamente três estados:
1) Retomado, quando está em primeiro plano da tela e tem o foco do usuário;
2) Em pausa, quando outra activity está em primeiro plano, mas ainda é visível; e,
3) Parado, quando é totalmente obscurecida por outra.
Quando uma activity transita dos diferentes estados descritos acima, o sistema é
notificado através de vários métodos de retorno. Os métodos de call-back são ganhos para
fazer um trabalho adequado quando o estado da activity muda. São eles:
i) onCreate( ): Chamado quando a aplicação é criada. É onde se deve fazer tudo
do conjunto estático normal, criar pontos de vista, vincular dados em listas etc.
É sempre seguido por onStart( ).
ii) onRestart( ): Chamado depois que a activity foi interrompida, pouco antes de
ser iniciada de novo. Seguido por onStart( ).
iii) onStart( ): Chamado imediatamente antes da activity torna-se visível para o
usuário. Seguido por onResume( ) se a atividade vem para primeiro plano ou
onStop( ) se se torna oculto.
iv) onResume( ): Chamado imediatamente antes da activity passar a interagir
com o usuário. A aplicação pode, então, iniciar ou retomar ações necessárias
para atualizar as interfaces como usuário. É seguido por onPause( ).
v) onPause( ): Acontece quando o Android chama uma activity diferente. Os
direitos à tela são perdidos e é o momento de parar todo o conteúdo supérfluo
que consome recursos do sistema e bateria. É seguido por onResume( ) se a
activity retorna para a frente, ou por onStop( ) se torna invisível para o usuário.
vi) onStop( ): Chamado quando outra activity obteve o primeiro plano, ou quando
está sendo eliminada. Seguido de onRestart( ) se a activity está voltando a
interagir com o usuário, ou por onDestroy( ) se está indo embora.
vii) onDestroy: Chamado antes que a activity seja destruída. É a última
oportunidade da aplicação fazer alguma coisa antes de ser eliminada. Pode ser
chamado quando o Android precisa de memória ou se o usuário finalizou a
aplicação.
Figura 1 – Ciclo de vida de uma Activity.
Fonte: Elaborada pelo autor, baseada em figura disponível em
https://developer.android.com/intl/pt-br/guide/components/activities.html
2.3.2.1.2. SERVICES
Um service é o componente que roda em background para realizar operações de
longa duração ou trabalhar em processos remotos. Eles são trechos de código geralmente
em segundo plano e sem interface usuário. Um exemplo é uma música tocando enquanto
o usuário utiliza um aplicativo diferente.
Um service é implementado como a subclasse Service e o seu ciclo de vida é parecido
com o de uma activity. As diferenças são apenas pelo fato de um service não ter
representação visual. onResume( ), onPause( ) e onStop( ) não são então necessários.
Uma nova chamada, onBind( ), cria o serviço se ele não existir e chama
onCreate( ), mas não onStart( ). É comum que services tenham vários clientes conectados
a eles.
Figura 2 – Ciclo de vida de um Service
Fonte: Elaborada pelo autor, baseada em figura disponível em
https://developer.android.com/intl/pt-br/guide/components/services.html
2.3.2.1.3. PROVEDORES DE CONTEÚDO
Um provedor de conteúdo gerencia uma aplicação de dados comxpartilhados. Os
dados podem ser armazenados no sistema de arquivos, uma SQLite database, na internet,
ou em outro local de armazenamento que seu aplicativo possa acessar.
Através do provedor de conteúdo, outros aplicativos podem acessar e até mesmo
modificar os dados.
Um provedor de conteúdo é implementado com a subclasse ContentProvider e
precisa implementar uma certa ordem de APIs que possibilitam outros aplicativos realizar
transações.
2.3.2.1.4. RECEPTORES DE BROADCAST
Um receptor de Broadcast é um componente que responde à solicitação de serviço
de outras aplicações. Muitos broadcasts se originam do sistema. Por exemplo um anúncio
broadcast que a bateria está baixa ou que a tela se apagou. Aplicativos também podem
iniciá-los, para deixar outros aplicativos saberem que algum dado foi feito download e
está pronto para uso, por exemplo.
Apesar de receptores de Broadcast não apresentarem entrada a uma interface
usuário, eles podem criar uma notificação na barra de status para alertar que algum evento
acorreu.
Um receptor de Broadcast é implementado como uma subclasse BroadcastReceiver
e cada um é entregue como um intent.
2.3.2.2. ATIVANDO COMPONENTES
As activities, os services e os receptores de broadcast são ativados por mensagens
assíncronas chamadas intents. Eles vinculam componentes individuais no tempo de
execução, mesmo se o componente pertença a outro aplicativo.
A mensagem é criada junto com um objeto Intent, que define a mensagem para ativar
ou um componente específico ou um específico tipo de componente.
Para activities e services, um intent define a ação a ser executada e pode especificar
a URI que o dado pode agir. Já para os receptores de broadcast, o intent simplesmente
define o anúncio sendo transmitido.
O provedor de conteúdo não é ativado por intents, ele é ativado quando atingido por
um requerimento do ContentResolver. O content resolver maneja todas as transações
diretas com os provedores de conteúdo para que o componente que está fazendo as
transações não precise manejar.
2.3.2.3. O ARQUIVO MANIFESTO
Antes do sistema Android iniciar um componente, ele deve saber que esse
componente existe, para isso, o sistema executa o AndroidManifest.xml. Nele, a aplicação
deve declarar todos os componentes.
O manifesto não apenas declara os componentes, ele também identifica as
permissões que um aplicativo requer, declara o nível de API mínimo requerido pelo
aplicativo, declara as características de hardware e software usadas ou requeridas pelo
aplicativo, quais bibliotecas API que o aplicativo precisa se conectar etc.
2.3.2.3.1. FILTROS
Os principais componentes de uma aplicação são ativados por Intents, que são um
conjunto de informações descrevendo uma certa ação – desde o momento em que a ação
deve ocorrer até a categoria de componente que a deve executar. O Android localiza um
componente apropriado para o intent, inicia uma nova instância do componente se
necessário e o passa o objeto do intent.
Os componentes demostram suas capacidades através de tais filtros. O sistema do
Android deve saber qual intent um componente pode suportar antes de iniciar o
componente. E essas especificações, filtros, se encontram no manifesto como elementos
<intent-filter>. Um componente pode ter um número qualquer de filtros contanto que
cada um descreva uma característica diferente.
2.3.2.3.2. PERMISSÕES
Uma permissão é uma restrição de acesso a parte do código ou dados no aparelho.
A limitação é imposta para proteger dados cruciais e código que poderia ser modificada
para distorcer ou danificar a experiência do usuário.
Cada permissão é identificada por um rótulo único. Comumente, o rótulo indica a
ação que é restrita. Como por exemplo:
android.permission.CALL_EMERGENCY_NUMBERS
android.permission.READ_OWNER_DATA
android.permission.SET_WALLPAPER
android.permission.DEVICE_POWER
Se uma aplicação necessita de acesso a um atributo protegido por uma permissão,
ele deve declarar que requer daquela permissão com um elemento de <uses-permission>
no manifesto. Então, quando o aplicativo está instalado no aparelho, o instalador
determina se deve ou não garantir a permissão requisitada ao checar com as autoridades
que assinaram os certificados do aplicativo ou, em alguns casos, perguntando ao usuário.
3. APLICATIVO
A portabilidade do algoritmo RSA de Java para Android foi feita utilizando o
Android Studio.
3.1. PROBLEMAS ENCONTRADOS
O desenvolvimento do aplicativo baseou-se na importação do código Java
previamente desenvolvido para Desktop. Ocorreu, porém, que no código em Java, o
algoritmo estava em uma classe única e, portanto, o processo de criptografia se dava
segundo as etapas descritas pela figura 3.
Figura 3 – Processo de criptografia antigo
Como as funções que encriptavam e decriptavam estavam dentro da mesma classe,
a função que decriptava conseguia utilizar o próprio vetor de bytes gerado pela que
encriptava, sem acessar o arquivo, e assim executar seu processo. Para que o código fosse
portado para Android, devido á divisão das Activities, foi necessária a partição do código
em java e com isso, a função que decriptava deveria receber a mensagem do arquivo.
A função inicialmente criada para encriptação transformava o vetor (bytes)
encriptado em uma String, e só então registrava no arquivo; isso inviabilizava a
transformação direta da String para o vetor de Bytes original que seria utilizado pela
função que decriptava. O problema foi resolvido salvando no arquivo diretamente o vetor
de bytes e alterando sua forma de leitura (Figura 4). Foram gerados novos códigos em
Java Desktop e, em seguida, as funções foram implementadas no aplicativo via Android
Studio.
Figura 4 – Processo de criptografia novo
3.2. VISÃO GERAL DO APLICATIVO
Existem três caminhos possíveis que podem ser seguidos ao acessar o aplicativo.
Criptografar gerando as chaves, criptografar já possuindo a chave pública e
descriptografar (Figura 5).
Figura 5 – Visão geral do Aplicativo
Figura 6.1a Figura 6.1b Figura 6.1c
Figura 6.1c Figura 6.1d Figura 6.1e
3.2.1. CRIPTOGRAFAR GERANDO AS CHAVES
Figura 6.1f
Nesse caminho o aplicativo criptografa a mensagem gerando a chave pública
(N, e) e a privada (p, q, d). Primeiro seleciona-se o botão “CRIPTOGRAFAR” (Figura
6.1a), depois o botão “Gerar Chaves” (Figura 6.1b), seleciona-se o tamanho da chave em
bits dentre as opções: 2048, 1024, 512, 256, 128, 64, 32, 16 e 8 (Figura 6.1c).
O usuário tem agora duas opções de entrada, ou ele digita a mensagem e pressiona
“SEND” ou digita o nome do arquivo, pressiona “CARREGAR” (a mensagem a ser
criptografada aparecerá na tela) e depois pressiona “SEND” (Figura 6.1d).
Aparecerá na tela, então, a chave pública e a mensagem criptografada. O usuário,
agora, tem a opção de salvar a mensagem pressionando “SIM” ou de voltar a tela inicial
pressionando “NÃO” (Figura 6.1e).
Caso pressionado o botão “SIM”, uma nova tela aparecerá, onde o usuário deve
digitar o nome do arquivo com o formato, ex.: .txt (Figura 6.1f). Ao pressionar o botão
“SALVAR”, o aplicativo volta à tela inicial.
Três arquivos terão, então, sido salvos no root da memória interna do celular,
ChavePublica.txt, onde estará a chave pública, números N e e, DestruaMe.txt, onde estará
a chave privada, números p, q e d e um arquivo com a mensagem criptografada, com
nome e extensão escolhidos pelo usuário (Figura 6.1g).
Figura 6.2a Figura 6.2b Figura 6.2c
Figura 6.2d Figura 6.2e
3.2.2. CRIPTOGRAFAR COM CHAVE PÚBLICA
Já nesse caminho o aplicativo criptografa a mensagem a partir de uma chave
pública (N, e) fornecida pelo usuário. Primeiro seleciona-se o botão “CRIPTOGRAFAR”
(Figura 6.2a), depois insere-se os números N e e da chave pública (Figura 6.2b).
O usuário tem, de novo, duas opções de entrada, ou ele digita a mensagem e
pressiona “SEND” ou digita o nome do arquivo, pressiona “CARREGAR” (a mensagem
a ser criptografada aparecerá na tela) e depois pressiona “SEND” (Figura 6.2c).
Figura 6.3a Figura 6.3b Figura 6.3c
Aparecerá na tela, então, a mensagem criptografada. O usuário, agora, tem a opção
de salvar a mensagem pressionando “SIM” ou de voltar a tela inicial pressionando “NÃO”
(Figura 6.2d).
Caso pressionado o botão “SIM”, uma nova tela aparecerá, onde o usuário deve
digitar o nome do arquivo com o formato, ex.: .txt (Figura 6.2e). Ao pressionar o botão
“SALVAR”, o aplicativo volta à tela inicial.
Nesse caminho, apenas a um arquivo terá sido salvo no root da memória interna
do celular, aquele da mensagem criptografada, com nome e extensão escolhidos pelo
usuário.
3.2.3. DECRIPTOGRAFAR
Figura 6.3d
No último caminho o aplicativo decriptografa a mensagem. Primeiro seleciona-se
o botão “DECRIPTOGRAFAR” (Figura 6.3a), depois insere-se o nome do arquivo, com
formato, a ser decriptografado e pressiona-se “CARREGAR”. O vetor de bytes aparecerá
na tela, o usuário insere, então, a chave privada, os números p, q e d e pressiona “SEND”
(Figura 6.3b).
Aparecerá na tela, a mensagem decriptografada. O usuário, agora, tem a opção de
salvar a mensagem pressionando “SIM” ou de voltar a tela inicial pressionando “NÃO”
(Figura 6.3c).
Caso pressionado o botão “SIM”, uma nova tela aparecerá, onde o usuário deve
digitar o nome do arquivo com o formato, ex.: .txt (Figura 6.3d). Ao pressionar o botão
“SALVAR”, o aplicativo volta à tela inicial.
O arquivo com a mensagem decriptografada terá sido salvo no root da memória
interna do celular, com nome e extensão escolhidos pelo usuário.
4. TRABALHOS FUTUROS
Embora tenha sido desenvolvido de maneira satisfatória e seja extremamente
funcional e fácil de ser utilizado, o aplicativo final possui pontos de melhoria aqui citados.
O primeiro problema a ser comentado é a inexistência da possibilidade de se
escolher o local onde os arquivos gerados serão salvos: embora se escolha o nome dos
arquivos, não é possível através do aplicativo escolher a pasta para onde o arquivo será
enviado; ele é sempre enviado para o diretório geral da memória interna do smartphone.
Paralelamente, não há possibilidade de escolher um arquivo de uma pasta diferente do
diretório geral citado. Tal restrição poderia ser resolvida implementando-se um sistema
de gerenciamento e busca de arquivos, que permitisse acessar as diversas pastas da
memória interna e externa do smartphone, e selecionar o arquivo a ser encriptado ou
decriptado diretamente de uma delas.
Além disso, o processo pelo qual se registram as senhas privadas não é o mais
seguro possível. As senhas privadas precisam ser salvas de alguma forma, pois sem elas
não é possível descriptografar a mensagem, e assim não há funcionalidade para o envio
da mensagem, uma vez que ela dificilmente conseguirá ser lida (dependendo do número
de bytes selecionado será impossível fatorar o produto de primos – N – da chave pública).
Salvar a chave privada diretamente em um arquivo no smartphone, porém, não é seguro.
Para que se resolvesse o problema, as senhas poderiam ser encriptadas antes de serem
salvas utilizando, para isso, uma chave privada fixa inerente ao aplicativo; o arquivo
gerado conteria, portanto, a chave privada criptografada segundo um padrão que só seria
reconhecido pelo aplicativo desenvolvido. Assim, na hora de descriptografar mensagens
ou arquivos em geral, apenas o aplicativo desenvolvido conseguiria abrir o arquivo das
senhas, torná-las claras e emprega-las.
No layout do aplicativo há ainda a limitação de não poder ser possível copiar os
valores que são mostrados na tela das chaves públicas: ainda que elas sejam salvas em
um arquivo no próprio smartphone, poderia ser possível copiá-las manualmente, sendo
essa uma opção para o usuário.
Como previsto na teoria, a criptografia RSA não se demonstra eficiente para
arquivos grandes: o aplicativo não consegue encriptar arquivos com algumas centenas de
bytes – sempre que chamado tem dificuldade em converter o arquivo no vetor de bytes,
que é muito grande, e logo em seguida não consegue encriptá-lo. Embora essa seja uma
limitação do algoritmo RSA, e não um problema do código implementado ou do
processador do smartphone utilizado para os testes, o funcionamento poderia ser
otimizado, aplicando um processo de criptografia mais simples que conseguisse encriptar
a mensagem, ainda que de maneira menos segura, e encriptando a chave dessa criptografia
com RSA, garantindo o sigilo, como sugere a teoria para contornar a lentidão do RSA.
5. CONCLUSÃO
É fato que a Criptografia RSA é amplamente utilizada na segurança de dados,
atualmente. O método, embora simples, por se basear na limitação da capacidade dos
computadores de fatorar números muito grandes, como os que formam a chave pública
do método, tem um fator de segurança alto.
O trabalho em questão cumpriu com todos os objetivos aos quais se propunha: os
estudos e as implementações foram desenvolvidos, e o produto final, o aplicativo para
Android foi entregue de maneira satisfatória. Surpreendendo às expectativas, o aplicativo
desenvolvido possui interface e funcionalidades de fácil uso, tornando o processo de
criptografia e decriptografia de mensagens e arquivos através dele simples, mantendo o
nível de segurança necessário.
O estudo acerca do método de Criptografia RSA foi de grande valia, e viabilizou
o contato, ainda que simples e restrito, dos alunos com área da defesa cibernética, área de
crescimento constante e de grande necessidade de desenvolvimento de novos estudos e
tecnologias. Além disso, a oportunidade de tornar os conhecimentos teóricos obtidos
práticos demonstrou-se extremamente proveitosa, passando desde a implementação do
algoritmo – elaboração de lógica matemática e de programação necessária – até o uso de
novas linguagens e ambientes de programação.
Acrescenta-se ainda a possibilidade vista de avanço para os estudos na área de
segurança de dados, tendo a pesquisa aberto um leque de opções para o desenvolvimento
de melhorias para o aplicativo desenvolvido e de novos produtos na área de defesa. A
segurança das informações é um problema muito mais próximo do que se espera, e com
o estudo foi possível notar que existem boas soluções disponíveis e de implementação
viável para que se garanta esta e, principalmente, que há muito espaço para
desenvolvimento de novos produtos e otimização de antigas soluções na área.
REFERÊNCIAS BIBLIOGRÁFICAS
ANDRADE, Rafael Santos, SILVA, Fernando dos Santos. “Algorítimo de criptografia
RSA: análise entre a segurança e velocidade”. Revista eventos pedagógicos, 2012.
ANDROID DEVELOPER, Building a Simple User Interface. Disponível em
http://developer.android.com/intl/pt-br/training/basics/firstapp/building-ui.html,
acessado em 25/10/2015.
ANDROID DEVELOPER, Creating an Android Project. Disponível em
http://developer.android.com/intl/pt-br/training/basics/firstapp/creating-
project.html, acessado em 25/10/2015.
ANDROID DEVELOPER, Layouts. Disponível em
http://developer.android.com/intl/pt-br/guide/topics/ui/declaring-layout.html,
acessado em 26/10/2015.
ANDROID DEVELOPER, Running your App. Disponível em
http://developer.android.com/intl/pt-br/training/basics/firstapp/running-app.html,
acessado em 25/10/2015.
ANDROID DEVELOPER, ScrollView. Disponível em
http://developer.android.com/intl/pt-br/reference/android/widget/ScrollView.html,
acessado em 26/10/2015.
ANDROID DEVELOPER, Starting Another Activity. Disponível em
http://developer.android.com/intl/pt-br/training/permissions/index.html, acessado
em 26/10/2015.
ANDROID DEVELOPER, Working with System Permissions. Disponível em
http://developer.android.com/intl/pt-br/training/basics/firstapp/starting-
activity.html, acessado em 26/10/2015.
ANDROID DEVELOPERS. Como usar o tema do Material. Disponível em
http://developer.android.com/intl/pt-br/training/material/theme.html, acessado em
28/10/2015.
ANDROID, A história do Android. Disponível em: https://www.android.com/intl/pt-
BR_br/history/, acessado em 27/08/2015.
BONEH, Dan. “Exposing an RSA private key given a small fraction of its bits”. 1998.
BONEH, Dan. “Twenty Years of Attacks on the RSA Cryptosystem”. Notices of the
AMS 46: 203-213, 1999.
BRAGHETTO, Luis Fernando B, BARBOSA, Luis Alberto de Moraes, BRISQUI,
Marcelo Lotierso, SILVA, Sirlei Cristina. “Criptografia Assimétrica e Assinatura
Digital” UNICAMP, Campinas, 2003. Disponível em
https://technet.microsoft.com/en-us/library/aa995740(v=exchg.65).aspx, acessado
em 05/05/2015.
BURNETT, Steve. “Criptografia e segurança: o guia oficial”/ Steve Burnett, Stephen
Paine; tradução de Edson Fumankiewicz. Rio de Janeiro. Elsevier, 2002.
CAELUM, Desenvolvimento móvel com Google Android. Apostila da Caelum Ensino
e Inovação, disponível em http://www.caelum.com.br, acessado em 28/08/2015.
CAELUM, Java e Orientação a Objetos. Disponível em
https://www.caelum.com.br/download/caelum-java-objetos-fj11.pdf, acessado em
20/05/2015
CAELUM. InputStream, InputStreamReader e BufferedReader. Disponível em
http://www.caelum.com.br/apostila-java-orientacao-objetos/pacote-java-io/#15-3-
inputstream-inputstreamreader-e-bufferedreader. Acessado em 15 de agosto de 2015.
CODERS HUB. Implementation of RSA Algorithm (Encryption and Decryption) in
Java. Disponível em http://www.coders-hub.com/2013/04/implementation-of-rsa-
using-java.html#.VeO2bLJViko. Acessado em 30 de julho de 2015.
DE AMORIM, Anderson Duarte. ANDROID, uma visão geral. 2011.
http://developer.android.com/guide/components/fundamentals.html#Components,
acessado em 28/08/2015.
DEVMEDIA. Criptografia Assimétrica: Criptografando e Descriptografando Dados
em Java. Disponível em: http://www.devmedia.com.br/criptografia-assimetrica-
criptografando-e-descriptografando-dados-em-java/31213. Acessado em 05 de
agosto de 2015.
DEVMEDIA. Números Aleatórios em Java – A Classe java.util.Random. Disponível
em: http://www.devmedia.com.br/numeros-aleatorios-em-java-a-classe-java-util-
random/26355. Acessado em 04 de setembro de 2015.
FERRAZ J., VINICIUS M., Utilizando classes das bibliotecas Java na aplicação de
conceitos de segurança. Universidade Federal de Pernambuco. Disponível em
http://www.cin.ufpe.br/~ruy/crypto/2005-1/Projeto%20de%20Criptografia%20-
%20Relatorio%20-%20Assinatura%20Digital.pdf. Acessado em 15 de agosto de
2015.
GARFINKEL, Simson. “PGP: Pretty Good Privacy”. O’Reilly & Associates, 1991.
GASPAROTTO, Henrique Machado, Os 4 pilares da Programação Orientada a
Objetos. Disponível em http://www.devmedia.com.br/os-4-pilares-da-
programacao-orientada-a-objetos/9264 , acessado em 20/05/2015.
GUJ. Criptografia RSA em JAVA. Disponível em http://www.guj.com.br/java/56444-
criptografia-rsa-em-java. Acessado em 5 de agosto de 2015.
GUJ. Método readLine da classe java.io.DatalnputStream. Disponível em
http://www.guj.com.br/java/193-metodo-readline-da-classe-javaiodatainputstream.
Acessado em 15 de agosto de 2015.
JAVA PLATFORM. Class Cipher. Disponível em
http://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html. Acessado em 15
de julho de 2015.
JAVA PLATFORM. Class KeyPaiGenerator. Disponível em
http://docs.oracle.com/javase/7/docs/api/java/security/KeyPairGenerator.html.
Acessado em 15 de julho de 2015.
JAVA PLATFORM. Class ObjectOutputStream. Disponível em
http://docs.oracle.com/javase/7/docs/api/java/io/ObjectOutputStream.html.
Acessado em 05 de agosto de 2015.
JAVA PROGRESSIVO. Como ler caracteres, Strings e Bytes de um arquivo Java.
Disponível em http://www.javaprogressivo.net/2014/01/Como-ler-caracteres-
Strings-Bytes-de-arquivos.html. Acessado em 15 de agosto de 2015.
JAVA PROGRESSIVO. static - Usando membros estáticos em Java. Disponível em
http://www.javaprogressivo.net/2012/10/static-Usando-membros-estaticos-em-
Java.html. Acessado em 05 de agosto de 2015.
JAVA. Obtenha Informações sobre a Tecnologia Java. Disponível em
https://www.java.com/pt_BR/about/, acessado em 18/05/2015.
JAVAFREE. Uso da palavra reservada “final”. Disponível em
http://javafree.uol.com.br/topic-862444-Uso-da-palavra-reservada-final.html.
Acessado em 15 de agosto de 2015.
JENKOV. Java IO: ObjectOutputStream. Disponível em:
http://tutorials.jenkov.com/java-io/objectoutputstream.html. Acessado em 15 de
julho de 2015
KOCHER, Paul C. “Timing Attacks on Implementations of Diffie-Hellman, RSA,
DSS, and Other Systems”, 2006.
MAIA, Luiz Paulo, PAGLIUSI, Paulo Sergio. “Criptografia e certificação digital”
MERCATO, Maria, A doce história do Android. Disponível em
http://www.androidpit.com.br/historia-do-android, acessado em 27/08/2015.
MEYER, Maximiliano, A história do Android. Disponível em
https://www.oficinadanet.com.br/post/13939-a-historia-do-android, acessado em
27/08/2015.
MONTEBUGNOLI, Thiago Cavalheiro. Android – Lendo e Carregando Arquivo
Texto. Disponível em
http://www.theclub.com.br/restrito/revistas/201208/andr0812.aspx, acessado em
27/10/2015.
NAUGHTON, Patrick. Dominando o Java, Guia Autorizado da Sun Microsystems.
Editora Makron Books, 1997, Osborne.
NIST, S. Frankel, ERICSSON, S. Krishnan. “IP Security (IPSec) and Internet Key
Exchange (IKE) Document Roadmad”, 2011.
PAAR, Christof. Understanding cryptography, a textbook for students and
practitionars. Berlim. Springer, 2009.
PEDRO, Luciana Rocha, CIOLETTI, Leandro Martins. “Algorítimo Euclidiano
Estendido”. Departamento de Matemática, UFMG, MG, 2009.
PORTAL ANDROID. Manipulando arquivos .txt no Android. Disponível em
http://www.portalandroid.org/comunidade/viewtopic.php?f=7&t=23281, acessado
em 27/10/2015.
POZZER, Cesar Tadeu. Introdução a Programação Orientada a Objetos na
Linguagem C++. Disponível em http://www-
usr.inf.ufsm.br/~pozzer/disciplinas/cg_5_oo_c++.pdf, acessado em 20/05/2015
REVIVER SOFT. .KEY Extensão de arquivo. Disponível em
http://www.reviversoft.com/pt/file-extensions/key. Acessado em 15 de julho de
2015.
RICARTE, Ivan Luiz Marques. Introdução a Orientação a Objetos, Definições.
Disponível em http://www.dca.fee.unicamp.br/cursos/POOCPP/node4.html,
acessado em 19/05/2015
ROMANATO, Allan. Entenda como funciona a Java Virtual Machine (JVM).
Devmedia, 2015.
SANTOS JÚNIOR, Luis Armando, NOGUEIRA, Antônio Carlos. “A função Phi de
Euler e sua aplicação na Criptografia”. Faculdade de Matemática, UFU, MG.
SINGH, Simon. O livro dos códigos. Tradução de Jorge Calife. 6ª ed Editora Afiliada,
2007.
SOUZA, Bruno, BIZNELLA NARDON, Fabiane, REHEM, Serge. A história da
tecnologia Java. Easy Java Magazine, 2014.
SOUZA, Cleidson. Conceitos de Orientação a Objetos. Disponível em
http://www.ufpa.br/cdesouza/teaching/es/3-OO-concepts.pdf, acessado em
19/05/2015.
STACK OVERFLOW. Principal objetivo das classes utilitárias. Disponível em
http://pt.stackoverflow.com/questions/90047/principal-objetivo-de-classes-
utilit%C3%A1rias, acessado em 27/10/2015.
STACKOVERFLOW. When should I use “this” in a class. Disponível em
http://stackoverflow.com/questions/2411270/when-should-i-use-this-in-a-class.
Acessado em 15 de agosto de 2015.
STATCOUNTER GLOBLAL STATS, Top 8 Mobile Operating Systems from Oct 2014
to Oct 2015. Disponível em http://gs.statcounter.com/#mobile_os-ww-monthly-
201410-201510. Acessado em 19 de novembro de 2015.
THE DEVELOPER´S POINT, Implementing RSA in Java (BigInteger approach).
Disponível em http://www.thedeveloperspoint.com/implementing-rsa-in-java/.
Acessado em 02 de setembro de 2015.
TI EXPERT. Public, Private e Protected. Disponível em
http://www.tiexpert.net/programacao/java/public-private-protected.php. Acessado
em 5 de agosto de 2015.
TI EXPERT. Try e Catch. Disponível em http://www.tiexpert.net/programacao/java/try-
catch-finally.php. Acessado em 15 de julho de 2015.
TUTORIALSPOINT. Java.lang.Integer.compareTo() Method. Disponível em
http://www.tutorialspoint.com/java/lang/integer_compareto.htm. Acessado em 02 de
setembro de 2015.
TUTORIALSPOINT. Java.math.BigInteger.gcd() Method. Disponível em
http://www.tutorialspoint.com/java/math/biginteger_gcd.htm. Acessado em 04 de
setembro de 2015.
TUTORIALSPOINT. Java.math.BigInteger.modInverse() Method. Disponível em
http://www.tutorialspoint.com/java/math/biginteger_modinverse.htm. Acessado em
15 de agosto de 2015.
TUTORIALSPOINT. Java.math.BigInteger.modPow() Method. Disponível em
http://www.tutorialspoint.com/java/math/biginteger_modpow.htm. Acessado em 15
de agosto de 2015.
TUTORIALSPOINT. Java.math.BigInteger.probablePrime() Method. Disponível em
http://www.tutorialspoint.com/java/math/biginteger_probableprime.htm. Acessado
em 04 de setembro de 2015.
UDACITY, Developing Android Apps – Android Fundamentals. Curso do Google,
disponível em https://www.udacity.com/course/developing-android-apps--ud853,
acessado em 02/10/2015.
WEINER, Michael J.. “Cryptanalysis of short RSA secret exponents”. IEEE
Transactions on information theory 36:553-558, 1990.
WILSON, Mark. T-Mobile g1: Full Details of th HTC Dream Android Phone (23 de
setembro de 2008). Disponível em http://gizmodo.com/5053264/t-mobile-g1-full-
details-of-the-htc-dream-android-phone, acessado em 19/11/2015.
ZARELLI, Guilherme Biff. Android – Opções de Armazenamento (persistência de
dados). Disponível em http://helpdev.com.br/2012/08/03/android-opcoes-de-
armazenamento/, acessado em 27/10/2015.
APÊNDICE A – O CÓDIGO
package tema.dirigido;
import java.math.BigInteger;
/**
* A classe BigInteger representa os números inteiros grandes. A vantagem do seu
* uso em criptografia consiste no fato dela representar os valores na notação
* de complemento a dois, dela possuir todos os operadores matemáticos básicos
* sobre inteiros e possuir funções complexas já implementadas, tais como a
* aritmética modular (mod e modInverse), algoritmo de Máximo Divisor Comum
(gcd), e
* geração de números primos (probablePrime).
*/
import java.util.Random;
/**
* A classe Random nos permite gerar números aleatórios, processo fundamental
* para que geremos chaves privadas da maneira mais segura possível.
*/
import java.io.*;
public class RSA
{
private BigInteger p;
private BigInteger q;
private BigInteger N;
private BigInteger phi;
private BigInteger e;
private BigInteger d;
private int bitlength = 1024;
/**
* Em criptografia, "Bit Length" é o número de bits numa chave digital usado
* para codificar ou decodificar uma mensagem ou arquivo. Quanto maior o
* "Bit Lenght", mais difícil será para quebrar a chave.
*/
private int blocksize = 256;
private Random r;
public RSA()
{
r = new Random();
p = BigInteger.probablePrime(bitlength, r);
q = BigInteger.probablePrime(bitlength, r);
/**
* probablePrime é uma função da biblioteca BigInteger que retorna um
* número primo com uma probabilidade de falha de 2^(-100), cujas
* entradas são o tamanho em bits do inteiro a ser retornado, e uma fonte de
bits
* aleatórios usado para selecionar candidatos a serem verificados como
* primos
*/
N = p.multiply(q);
phi = (p.subtract(BigInteger.ONE)).multiply(q.subtract(BigInteger.ONE));
/**
* Da construção do algoritmo sabemos que e deve ser primo com phi, e
* por esse motivo geramos um e primo;
* Sabemos também que 1<e<phi, logo geramos e com metade do
comprimenro
* de bits de p e q;
*/
e = BigInteger.probablePrime(bitlength/2, r);
/**
* A função a.compareTo(b) retorna:
* x<0 - se a<b
* x=0 - se a=b
* x>0 - se a>b
* Como e é primo, precisamos garantir apenas que o mdc(e,phi)=1. O laço
* abaixo verifica essa condição, e a desigualdade entre e e phi
* supracitada; se uma delas não for atendida, ele incrementa e de 1 e
* repete o teste, até que encontremos um e válido. Como e é primo
* gerado aleatoriamente com metade do comprimento em bits de phi, a
* probabilidade do laço rodar mais que uma vez é muito baixa.
*/
while (phi.gcd(e).compareTo(BigInteger.ONE) > 0 && e.compareTo(phi) <
0)
{
e.add(BigInteger.ONE);
}
/**
* A função modInverse calcula o inverso de um número num determinado
módulo
* Ou seja, se a=b.modInverse(c) então a=b^(-1) no módulo c, ou ainda
* a.b=1 mod c. Assim, geramos d diretamente
*/
d = e.modInverse(phi);
}
/**
* Do algoritmo sabemos que a mensagem criptografada, sendo um bloco c, é
* tal que c=m^d mod n, onde m é a mensagem limpa e N o produto entre p e
q.
* Logo, a função de criptografia utiliza-se da função modPow, que retorna
* o valor de c da expressão acima quando utilizamos ela m.modPow(d,n).
* Processo análogo é empregado para a decriptografia.
* @param message
* @return
*/
public byte[] encrypt(byte[] m)
{
return (new BigInteger(m)).modPow(d, N).toByteArray();
}
//Decriptar mensagem
public byte[] decrypt(byte[] message)
{
return (new BigInteger(message)).modPow(e, N).toByteArray();
}
//Função utilizada para converter cada byte para uma string
private static String bytesToString(byte[] encrypted)
{
//Iniciamos o processo com a string vazia
String test = "";
/**
* Para cada byte, aplicamos a conversão para string e atualizamos a
* string test que armazena os resultados
*/
for (byte b : encrypted)
{
test += Byte.toString(b);
}
return test;
}
/**
* Utilizamos a palavra reservada this para referenciar os parâmetros da
* classe criada às variáveis geradas pelo algoritmo até então.
* @param e
* @param d
* @param N
*/
public RSA(BigInteger e, BigInteger d, BigInteger N)
{
this.e = e;
this.d = d;
this.N = N;
}
public static void main (String[] args) throws IOException
{
RSA rsa = new RSA();
/**
* Foi criado um arquivo .txt e inserido na pasta do projeto, de modo que
* o texto a ser criptografado fosse extraído de lá.
*/
//Inicialmente lemos os bytes do arquivo com a classe InputStream
InputStream is = new FileInputStream("Teste.txt");
/**
* Para recuperar um caractere precisamos traduzir os bytes com o ecoding
* dado para o respectivo código unicode. Quem faz isso é a classe
* InputStreamReader
*/
InputStreamReader isr = new InputStreamReader(is);
/**
* A classe BufferedReader concatena os chars de modo a formar uma
* String através do método readLine.
*/
BufferedReader br = new BufferedReader(isr);
String teste = br.readLine();
System.out.println("Mensagem a ser criptografada: " + teste);
System.out.println("Conversão da mensagem para bytes: " +
bytesToString(teste.getBytes()));
// Encriptação
byte[] encrypted = rsa.encrypt(teste.getBytes());
System.out.println("Mensagem encriptada em Bytes: " +
bytesToString(encrypted));
// Decriptação
byte[] decrypted = rsa.decrypt(encrypted);
System.out.println("String Decriptada em Bytes: "
+ bytesToString(decrypted));
System.out.println("Decrypted String: " + new String(decrypted));
}
}