segunda-feira, 20 de dezembro de 2010

Android no Desktop com VirtualBox

Então, já estou começando a fazer uns programinhas bobos para Android. Estou começando a aprender e a entender o funcionamento do sistema operacional. Como sabem (eu acho), o Android tem coração de Linux. Então pensei: será que esse "caboquim" roda legal no desktop?

A primeira coisa que fiz foi "googlar" para "Android X86", nas esperança de encontrar alguém que já tivesse tentado. Olha só o primeiro site (tô atrasado hein?): http://www.android-x86.org/. O projeto está ativo desde março de 2010 preparando a versão para x86.

Bom, fui direto ao assunto:

1. Fui para Download.
2. Em "StableRelease" baixei "android-x86-1.6-r2.iso" (baixe uma mais nova, se encontrar).
3. Gerei uma virtual machine no virtual box escolhendo "Linux" e "Others" (outros linux).

Não é que rodou de cara?

Olha o sistema rodando aí de primeira, sem necessidade de qualquer ajuste



Bem no momento de escrita do post.

Experimente ai!

quarta-feira, 17 de novembro de 2010

IOWait causando 100% de consumo de CPU no Ubuntu - SOLUCIONADO

Há algum tempo eu vinha tendo problemas de IOWait alto ao ligar o notebook, o que fazia com que o sistema ficasse impossível de utilizar por mais ou menos uns 15 minutos. O IOWait consiste no tempo em que o processador fica aguardando (bloqueado) o término de uma operação de I/O. O interessante é que não aparecia nenhuma aplicação consumindo de forma exagerada o disco ou a CPU no system monitor. Obviamente não era a ferramenta ideal para avaliar o problema.

Após "fuçar" por uns dois dias (efetivamente umas 4 horas ao longo de 4 semanas...) descobri o iotop, que permite monitorar os processos consumindo operações de I/O. Foi rodar o programa imediatamente após uma inicialização e logo os vilões apareceram: gdl_fs_crawler e gdl_indexer. Quem são? Estes dois são processos de background que cuidam do serviço de indexação do Google Desktop. Sim, estava com o Google Desktop instalado no Ubuntu e configurado para inicializar automaticamente.

Identificado o problema, a solução não poderia ser mais simples: tirar o Google Desktop da inicialização (System→Preferences→Startup Applications). Reinicializada a máquina, praticamente zero de IOWait e a máquina voltou a funcionar excelentemente, permitindo a inicialização do OpenOffice logo de cara.

Colocando o Google Desktop para rodar após a inicialização o IOWait fica menos exagerado, mas ainda bate 2000Kb/s de leitura de disco. O ideal é deixar o Google Desktop indexando durante a noite e desligar a indexação durante o período de uso normal, mantendo-o fora da inicialização.

Mas ele ainda é minha ferramenta preferida de pesquisa no desktop.

segunda-feira, 18 de outubro de 2010

Pesquisando imagens na web

Muita coisa interessante vem surgindo no mundo da computação "mundana", recentemente. Coisas que, na faculdade, só ouvia falar como pesquisas avançadas hoje estão no dia-a-dia das pessoas.

Uma das funcionalidades interessantes de meu Motorola Droid é o MotoID, programa que "escuta a música" e identifica qual é. Interessante aplicação de análise de espectro... isso me lembra minhas aulas de identificação, estimação e processos estocásticos com meu orientador, José Manoel.

Da mesma forma, estão surgindo as ferramentas de reconhecimento de imagens por similaridade. Existem algumas como o Similar Images do Google, Tiltomo e Bing  que ainda são baseadas nos atributos informados sobre a imagem, mas as mais interessantes são aquelas que realizam a análise da imagem.

Então, há algum tempo recebi a imagem de um logo anexado a um e-mail e fiquei curioso de saber de onde tinha saído. Mexi na internet e achei o TinEye, uma excelente ferramenta de busca reversa de imagens. O funcionamento é bastante simples: você faz o upload da imagem (ou mesmo parte de uma imagem), a ferramenta faz a análise e vasculha a web buscando aquela imagem em particular.



Outra da mesma família é a Byo Image Search, que não tem uma base tão extensa quanto o TinEye e funciona principalmente pela distribuição de cores da imagem.

De qualquer forma, vale a pena dar uma avaliada em todas elas.

A era de reconhecimento de imagem, voz e sons está muito mais próxima do que imaginamos.

quarta-feira, 6 de outubro de 2010

Padrões internacionais para tabelas com nomes de países, estados, cidades e unidades monetárias

Com frequência vejo alunos e pessoal de mercado construindo aplicações com tabelas de países, estados, cidades, códigos de moeda e informações afins. Normalmente nestas aplicações estas pessoas criam algumas telas CRUD para o cadastramento das informações e populam as tabelas buscando dados nos correios ou em outras fontes geralmente menos confiáveis.

O fato é que para a lista de países, estados (províncias), moedas e muitas outras existem padrões internacionais ISO que formalizam estes valores.

A ISO 3166 é uma norma internacional para codificar nomes de países e dependências, com suas principais subdivisões administrativas. Na realidade trata-se de um conjunto de três normas:
  • ISO 3166-1 - códigos para países e dependências, publicado desde 1974
  • ISO 3166-2 - códigos para as principais subdivisões de um país ou dependência
  • ISO 3166-3 - códigos obsoletos (retirados de ISO 3166-1), publicado desde 1998 
Para as unidades monetárias, temos a ISO 4217.

E não é necessário visitar a Wikipedia e baixar as informações de lá. Como era de se esperar, existem repositórios na web para estes dados, que podem ser baixados ou consultados on-line. Um bom exemplar destas fontes dinâmicas destes padrões é o CommonDataHub, site que disponibiliza estes e outros padrões nos mais diversos formatos, além de fornecer webservices para consumo on-line. É cobrado, mas é um serviço com garantia de informações. Para a consulta a todas as cidades - com população superior a 5000 habitantes - o valor é de US$750,00/ano.

As informações parecem ser de boa qualidade pois achei São Simão/GO lá. :-)


Então, para estas tabelinhas básicas, melhor buscar a informação na fonte. Seu sistema ficará mais fácil de integrar com outros sistemas do mundo.

sábado, 2 de outubro de 2010

Problemas de som no Ubuntu 10.04 - apenas browser com som

O som parou de funcionar no meu notebook (obviamente, após várias "fuçadas" aleatórias do newbee aqui).

Por incrível que pareça, apenas os browsers conseguiam reproduzir som.

Então, após procurar em vários blogs e posts, comecei a olhar os arquivos de configuração. Então encontrei a pasta ".pulse". Como acontece normalmente com o Gnome, os arquivos de configuração ficam nestas pastas.

Dei uma olhada nas datas, tirei uma cópia e removi a pasta (um simples rm -r .pulse).

Um restart e pronto, voltou a funcionar! :-P

domingo, 19 de setembro de 2010

Sem permissão para acessar o Google?

Agora à noite fui fazer uma pesquisa no Google e recebi um "403 Forbidden":

Ao tentar acessar o GMail, recebi a mensagem abaixo:

Forbidden

You don't have permission to access /accounts/SetSID on this server


O que eu fiz de errado para não ter mais acesso ao Google? :-P

Bem, o blogger estava funcionando. Alguns segundos depois, o acesso ao Google voltou, mas ao GMail não.

Vamos ter notícias disso.

sábado, 11 de setembro de 2010

Resetando as configurações do GNome

Hoje resolvi fuçar nas configurações do Compiz e fiz uma bagunça nas configurações do meu gnome. Quem disse que eu conseguia voltar ao que era antes? Tinha guardado uma cópia, certo? Claro que não! :-P

Então a solução foi levar o gnome às configurações iniciais. Como fazer?

1) Remover os arquivos de configuração

rm -rf .gnome .gnome2 .gconf .gconfd .metacity

2) Reinicializar o gnome

Três formas:

a) CTRL+ALT+Backspace

b) sudo /etc/init.d/gdm restart

c) killall gnome-panel


quinta-feira, 17 de junho de 2010

Ataques por buffer overflow – e além deles

Este artigo é um resumo e revisão do artigo “Beyond Stack Smashing”, cuja referência está ao final do texto.

Uma das principais formas de ataque aos sistemas é a injeção de código. O hacker identifica brechas de segurança no sistema e injeta um conjunto de dados em memória que corresponde às instruções que deseja executar. A partir daí basta (como se fosse simples!) forçar o redirecionamento do contador de programa para aquela posição de memória e pronto, o código injetado passa a ser executado, realizando a alteração de comportamento que o atacante projetou, que pode ser simplesmente um “denial of service” (DoS) ou algo mais sofisticado como executar um programa ou mudar uma senha através da chamada ao comando apropriado. O ping da morte é um exemplo clássico de buffer overflow (ou buffer overrun) que provocava uma queda no sistema atacado.

Só para relembrarmos, temos duas estruturas básicas na organização de memórias de um processo: o stack e o heap. O stack é a região de memória organizada numa fila lifo (last-in, first-out) que suporta as chamadas de rotinas, armazenando variáveis locais, parâmetros de chamada e endereços de retorno. A organização varia entre os sistemas operacionais, mas para cada um deles possui uma estrutura relativamente bem conhecida. Já o heap é a estrutura responsável por manter as estruturas criadas por alocação dinâmica.
Uma das formas de se realizar um ataque de buffer overflow é através do chamado “stack smashing” (“esmagamento” de pilha), onde o atacante se utiliza de um software com falhas de projeto que permitam o envio de dados além de uma quantidade esperada por um buffer. Com isso, os dados enviados sobrescrevem o espaço de memória reservado para o ponteiro-de-retorno e, com o conhecimento adequado, pode-se colocar a informação desejada naquele ponto.

Para ficar mais claro, vamos a um exemplo com objetivo puramente didático. Considere portanto o programa em C a seguir e a figura que ilustra a organização da stack.

void funcaoErrada(char* str) {
int i = 10;
char buffer[10];
strcpy(buffer,str);
}

int main() {
char *s = “Texto com mais de dez caracteres”;
funcaoErrada(s);
}

Fica evidente que este programa irá se comportar de forma imprevisível, corrompendo a pilha à medida em que a função strcpy, na “funcaoErrada”, ultrapassa os limites do buffer e escreve por sobre o ponteiro de retorno e outras estruturas.

Agora, imagine que o hacker tem conhecimento suficiente sobre a organização de memória de um certo sistema operacional e sobre um determinado programa em questão, de modo que consiga, através de um buffer overflow, sobrescrever o ponteiro-de-retorno com um conjunto de bytes que aponte exatamente para a posição buffer[0], onde ele colocou um conjunto de bytes que corresponde às instruções desejadas? Pronto. Tomou posse do comportamento do sistema através do código injetado.

Esta é a base do “stack smashing”, que possui variantes mais sofisticadas.

O "Trampolining" é uma variação de “stack smashing”. No modelo básico, o atacante precisa saber o endereço absoluto de buffer[0], para poder registrar esta informação no ponteiro-de-retorno. Isto nem sempre é factível. No entanto, se sabe-se que um registrador R possui um endereço relativo ao do buffer, então pode-se de forma indireta usar o valor de R para apontar para buffer[0]. O conjunto de instruções que permite esta transferência indireta de controle é denominada “trampolim”.

Outra forma é utilizar o que podemos chamar de “stack smashing em 2 passos”. A técnica é útil quando o buffer é muito pequeno. Neste caso o hacker utiliza alguma operação anterior para carregar as instruções do código injetado para uma posição específica e em seguida realiza o buffer overflow para carregar o ponteiro-de-retorno com o endereço daquela posição.

"Arc Injection" é outra técnica de exploração que exige que o programa atacado utilize os dados passados como parâmetro para outro processo inicializado por ele. Para isto é necessário saber antecipadamente que a função hackeada realiza este tipo de chamada, ou então usar o stack buffer overrun para direcionar a execução a uma chamada de uma função de criação de um novo processo (execl, system), por exemplo. Outra possibilidade com esta técnica é executar uma chamada a uma função com endereço já conhecido na estrutura de memória do sistema operacional. Então, na realidade não estamos injetando código, mas injetando uma chamada para um outro processo (daí o nome).

Finalmente, “Pointer Subterfuge"consiste na técnica de alterar a organização de ponteiros dentro de um programa, colocando a informação apropriada para permitir o redirecionamento. Esta técnica se divide em outras categorias:
  • function-pointer clobbering: consiste na modificação do código de uma função quando a mesma está sendo acionada por ponteiros (void (*function) () = ….)
  • data-pointer modification: consiste em utilizar um buffer oveflow para escrever sobre um ponteiro dentro da função.
  • exception-handler hijacking: no windows ponteiros para os manipuladores de exceção são armazenados na pilha. Se sobrescrevemos estas posições por meio de um buffer overrun e em seguida disparamos a exceção, não é ela que será executada mas sim o código armazenado no endereço escrito no ponteiro.
  • virtual pointer smashing (VPTR Smashing): A “virtual function table” (VTBL) é um array para funções virtuais disponibilizadas para uma classe e é, normalmente, armazenado no cabeçalho do objeto. A VTBL é acessada por um VPTR (virtual pointer). A substituição do VPTR por um valor próprio, apontando para uma estrutura VTBL forjada, construida intencionalmente para apontar para funções injetadas no sistema pelo atacante (na pilha, por exemplo, por stack smashing).
Além do stack – heap smashing
Até algum tempo atrás imaginava-se que ataques baseados no heap não eram possíveis devido a sua estrutura imprevisível. Como sabemos, o heap é a área onde acontece a alocação dinâmica de memória mediante solicitação do programa e é o fluxo do programa que determina como o heap estará estruturado.

Mais uma vez, para explorar qualquer fragilidade no heap o atacante tem que conhecer algum invariante na estrutura e nos processos de sua manipulação. Obviamente, o caminho inicial deve ser encontrar um comportamento padrão e fragilidades e na arquitetura no processo que realiza a alocação dinâmica, no entanto esta técnica é bem mais difícil que aquelas baseadas em stack por que os processos de alocação e liberação, bem como os processos de compressão de espaços livres de memória, dificultam qualquer previsão sobre onde estão os espaços alocados, quais os tamanhos alocados e quais informações eles contém. No caso de aplicações multi-threaded a coisa piora ainda mais. Difícil, mas não impossível. Existem pesquisadores (principalmente de grupos Hacker) trabalhando nas possibilidades de uso do heap para abrigar código injetado que possa ser executado posteriormente por uma mudança no contador de programa.

A coisa não é tão simples assim
Fica claro que não é trivial realizar este tipo de ataque. É necessário conhecer a organização de memória dos processos no sistema operacional, conhecer o código-fonte do programa atacado e, certamente, não é o tipo de ataque que ocorre com apenas uma tentativa. De qualquer forma, é um tipo de ataque que ainda ocorre com freqüência.

Para quem quer mais informações, basta dar uma olhada nas referências.

Referências

terça-feira, 25 de maio de 2010

Reflections on trusting trust - uma visita ao artigo de Ken Thomson

Primeiro vamos saber que é esse tal de Ken Thomson.

Ken Thomson (esquerda) e Dennis Ritchie (direita) (fonte [2])

Bem, pelo companheiro na foto podemos ter uma idéia. Thomson é um dos criadores do Unix e criador da linguagem B, precursora de C (:-P). É um dos responsáveis pelas expressões regulares, por UTF-8 e pelo desenvolvimento de programas de jogo de xadrez. Atualmente está no Google.

No artigo "Reflections on trusting trust" Thomson faz uma descrição de como um compilador pode ser alterado para inserir um cavalo-de-tróia no código do programa que faz o login em um sistema Unix e, com isso, prepará-lo para responder positivamente a uma certa palavra-chave. Também demonstrou como o compilador C poderia ser alterado para propagar este comportamento malígno mesmo quando tentar-se recompilar o código-fonte - original, não modificado - do próprio compilador. Ou seja, mesmo compilando-se um código-fonte correto com este compilador alterado, o código-objeto resultante conterá a alteração para o login. De fato o compilador está plantando um backdoor no sistema operacional [3].

Em resumo, o que Thomson questiona é: o quanto podemos confiar em um código-fonte confiável, se não temos referências de confiabilidade nos demais elementos utilizados para produzir e executar o código-objeto dele derivado?

O artigo de Thomson data de 1984, mas não se tratava de conjectura. Em uma análise relativamente recente (Agosto de 2009) o SophosLab demostrou que um arquivo infectado com o vírus W32/Induc-A executava um código que procurava por uma instalação do compilador Delphi e, caso o encontrasse, o alterava. A partir daí todo código gerado por aquele compilador passaria a incluir o W32/Induc-A em seu código-objeto [4]. Exatamente o mesmo caso descrito por Thomson.

Portanto, suponha que você está desenvolvendo neste momento um sistema para uma grande corporação financeira, que irá processar milhares de transações diariamente, trafegando dados sigilosos. Questione: o quanto pode-se confiar em sua plataforma de desenvolvimento e na plataforma que irá executar o sistema em produção?

No contexto de desenvolvimento seguro de software o que Thomson nos alerta é que possuir uma metodologia de desenvolvimento seguro, por si só, não é suficiente para garantir que o produto do desenvolvimento resulte em um processamento seguro.

De fato, o que seria necessário é uma plataforma de computação confiável. E este conceito existe. Em 2003, por iniciativa da AMD, Hewlett-Packard, IBM, Intel e Microsoft foi formado o Trusting Computing Group (TCG), cujo objetivo inicial era o desenvolvimento de um módulo de computação confiável (trusting computing module) baseado tanto em hardware como em software, para garantir, através de serviços de criptografia e verificação de integridade de código e memória, que apenas código autorizado pudesse rodar na plataforma. Em 2009 o TCG liberou um conjunto de especificações que descrevem o protocolo para comunicação com hard-disks auto-encriptáveis. Ou seja, os produtos do TCG são ainda recentes.

Existe também um conjunto de especificações da ISO que tratam do tema:
  • ISO/IEC 11889-1:2009 Information technology -- Trusted Platform Module -- Part 1: Overview
  • ISO/IEC 11889-2:2009 Information technology -- Trusted Platform Module -- Part 2: Design principles
  • ISO/IEC 11889-3:2009 Information technology -- Trusted Platform Module -- Part 3: Structures
  • ISO/IEC 11889-4:2009 Information technology -- Trusted Platform Module -- Part 4: Commands
Para quem se interessa no tema, vale a pena dar uma olhada.

Então, fica a questão: mesmo com uma metodologia de desenvolvimento seguro, podemos garantir que estamos desenvolvendo e executando código seguro? Podemos confiar nos códigos que utilizamos em nossos computadores pessoais, nas plataformas executadas pelos Bancos e até mesmo nos códigos que rodam na nuvem ?

Referências
[1] Thomson, K., "Reflections on trusting trust", Communications of the ACM, volume 27, issue 8, pag. 761 - 763, 1984.
[2] http://en.wikipedia.org/wiki/Ken_Thompson , visitado em 21/05/2010.
[5] Spinellis, D., "Reflections on trusting trust revisited", Communications of the ACM, volume 46, issue 6, pag. 112, 2003.

domingo, 25 de abril de 2010

Criptografia com curvas elítipticas

Introdução

O problema da escolha de um método para criptografia na comunicação entre duas entidades tem duas restrições fundamentais:

  • Possuir características técnicas que minimizem o consumo de espaço (informação armazenada ou transmitida) e o esforço de processamento na cifragem e decifragem;

  • Garantir que o esforço para a decifragem, sem que se possua a chave, exija um tempo absurdo, mesmo que se possua um poder computacional igualmente absurdo. Esta robustez do sistema criptográfico está baseada na complexidade computacional do cálculo da função inversa àquela utilizada na criptografia;

  • A criptografia mais conhecida e utilizada até final da década de 90 é a já conhecida criptografia simétrica, onde deve haver um algoritmo e uma chave de conhecimento de ambas as partes de um processo de comunicação. Apesar de ser um método bastante eficiente, em termos computacionais, um problema que sempre esteve sob estudo é como garantir a integridade e confidencialidade da chave, garantindo assim a segurança da comunicação.

    Tradicionalmente o que fazemos é criar diversos artifícios para garantir que a chave seja transferida com segurança ao alvo da comunicação: utilizamos uma outra chave para cifrar a chave a ser transferida, utilizamos um processo de geração compartilhada (cada parte gera uma parte da chave e estas partes são transferidas fisicamente através de um processo seguro e auditável) e outros processos. Ainda assim, temos que garantir que cada parte guardará esta chave apropriadamente. Normalmente as chaves realmente importantes e de uso recorrente são armazenadas em equipamentos próprios para este fim (os HSMs).

    Buscando contornar essa dificuldade surgiram as pesquisas das chamadas funções criptográficas de chave pública, cujo propósito é transferir informações cifradas por uma chave conhecida (chave de cifragem, pública) de tal forma que mesmo se a informação e estas chave forem interceptados a confidencialidade será garantida, pois falta uma chave de decifragem (desconhecida, de uso privado da entidade-destino). Por isso mesmo este tipo de criptografia é também chamada de "criptografia assimétrica".

    Vamos abordar um pouco da história da criptografia assimétrica, dos algoritmos que surgiram e o por quê da importância da criptografia com curvas elípticas.


    Criptografia assimétrica

    Há bastante tempo o homem pesquisa alternativas para garantir a criptografia de informações sem que um segredo (a chave) precise ser trocado entre as partes.

    O registro mais antigo deste tipo de estudo remonta ao ano de 1874 [1], quando Willian Stanley Jevons, pesquisador inglês dos temas de economia e lógica, descreveu as relação entre funções sem função inversa (funções de sentido único) e a criptografia e, mais especificamente, o problema da fatoração (representação de uma função através da família da função e seus parâmetros) que foi a base para os primeiros algoritmos da criptografia assimétrica.

    Um sistema de criptografia assimétrico foi publicado em 1976 por Whitfield Diffie e Martin Hellman e por isso mesmo é chamado de algoritmo de Diffie-Hellman.

    Da esquerda para a direita: Ralph Merkle, Martin Hellman e Whitfield Diffie [2]

    O Algoritmo de Diffie-Hellman

    Este algoritmo baseado na função GX mod N, apresentado aqui de forma bastante simples, é particularmente interessante para entendermos a criptografia com chaves assimétricas. Para fins práticos N deveria ser um número primo muito grande (muito mesmo!) que determina o tamanho do campo finito gerado.

    Consideremos que dois individuos, Alice e Bob, desejam se comunicar de forma segura, de tal forma que Alice irá transferir uma informação a Bob.

    Para isto Alice e Bob concordam em valores para G e N (estes são os parâmetros do algoritmo, que podem ser de conhecimento público). Estes valores devem ser primos, com G < g =" 11" n =" 23.
    Alice e Bob escolhem suas chaves privadas, digamos 2 e 9 respectivamente. Esta chave não é comunicada a ninguém.

    Alice calcula 112 mod 23, cujo resultado é 6, e envia esta informação a Bob. Esta é a chave pública de Alice.

    Bob calcula 119 mod 23, cujo resultado é 19, e envia esta informação a Alice. Esta é a chave pública de Bob.

    Alice pega o valor enviado por Bob, 19, e calcula 192 mod 23 (chave pública de Bob elevada à chave privada de Alice mod N), que resulta em 16. Bob faz o mesmo, pegando o valor enviado por Alice, 6, e calcula 69 mod 23 (chave pública de Alice elevada à chave privada de Bob mod N), que resulta também em 19. O valor 19 é a chave comum para a comunicação entre Alice e Bob.

    O que percebemos é que para Alice e Bob conversarem eles apenas precisaram entrar em acordo sobre um algoritmo e seus parâmetros e a informação trocada entre eles, para a determinação da chave comum, não contém nenhum teor de confidencialidade. O único requisito é que as chaves privadas continuem secretas.

    Temos portanto uma exponencial e encontrar as chaves requer o cálculo de um logaritmo sobre um campo numérico discreto baseado em números primos muito grandes, o que é computacionalmente imprático (o que, hoje, significa "impossível"). Fica clara a relação recorrente que envolve a dificuldade do cálculo da inversa e o tamanho da chave para garantir a segurança da estratégia de criptografia.

    Logicamente a descrição aqui simplifica bastante o modelo - que exige números primos bastante grantes e uma boa qualidade no algoritmo de geração de números aleatórios - mas é o suficiente para que possamos entender a simplicidade brilhante do método.

    O algoritmo RSA

    Ainda em 1977 Ron Rivest, Adi Shamir e Len Adleman criaram o algoritmo RSA (formado pelas iniciais de seus nomes).

    Ron Rivest, Adi Shamir e Len Adleman [3]

    O algoritmo implementou o conceito de assinatura digital e foi elegantemente baseado no produto de dois números primos. A inversa dependeria de, dado o produto, achar estes primos, o que é imprático computacionalmente.

    O RSA é utilizado no protocolo SSL na maioria dos browsers [4].


    Os algoritmos baseados nas curvas elípticas

    Como mencionei ao início do artigo, espaço (memória) e velocidade são dois fatores importantes na escolha de um algoritmo de criptografia. E é aí que surge o especial interesse nas curva elípticas: elas oferecem mais segurança para um mesmo tamanho de chave. Por outra óptica, elas oferecem mais segurança para uma chave menor, o que significa mais velocidade (menos ciclos, menos energia, menos calor produzido).

    A matemática das curvas elípticas

    Enquanto o algoritmo de Diffie-Hellman baseia-se no problema do logaritmo discreto sobre um campo finito formado por números primos, as curvas elípticas baseiam sua técnica num campo finito formado por pontos - pares (x,y) - de números primos que estão sobre a curva elíptica definida por uma determinada equação.

    Em geral os pontos (x,y) são definidos pela equação a seguir
    y^2 = x^3 + ax + b, \,
    que está representada na figura abaixo (de [5])

    onde temos as curvas para b = 0, 1/10, 2/10, 3/10, 4/10. Mas existem outras equações possíveis para as curvas elípticas. Para ter uma idéia de outras equações e no formato destas curvas, dê uma olhada aqui.

    Agora imagine que tenhamos um quadrado de lado p definindo uma região onde está a curva, sendo p um número primo muito grande. O campo em que estamos interessados é formado por pontos (x,y), onde tanto x quanto y são números primos dentro do campo Fp, que são os inteiros módulo p na faixa [0, p-1], e definem pontos sobre a curva elíptica escolhida.

    É possível determinar aproximadamente quantos pontos tem-se sobre a curva através da equação p + 1 - 2*sqrt(p) <= #E <= p + 1 + 2*sqrt(p). Por exemplo, para a equação y² = x³ +4x +20 com F29 temos 37 pontos (incluindo o ponto no infinito).

    Ainda, a matemática das curvas elípticas define um conjunto de operações aritméticas que produzem resultados dentro do campo discreto de primos sobre a curva. A imagem abaixo ilustra a soma dos pontos P e Q, resultando em R [5].
    A mais importante operação refere-se à multiplicação por escalar, onde temos o ponto P sobre a curva e k é um inteiro. Então Q = kP = P + P + P + ... + P (a soma é feita k vezes).

    Chave pública e chave privada

    Na criptografia com curvas elípticas, a equação base é a multiplicação por escalar Q = kP, onde P é um ponto de referência na curva (parâmetro da curva), Q é a chave pública e k é a chave privada. O problema do logaritmo discreto nas curvas elípiticas é justamente termos P e Q e tentarmos encontrar o k correspondente.

    De fato, os parâmetros da curva são definidos pela tupla T = (p, a, b, P, n, h), onde:
    - p define o tamanho do campo;
    - a e b são os parâmetros da equação, que vimos há pouco;
    - P é o ponto-base da curva;
    - n é um primo grande, da ordem de P;
    - h é um inteiro tal que h = #E(Fp)/n (também falamos de #E logo acima);

    Digamos então que Alice (A) e Bob (B) desejam se comunicar utilizando uma criptografia suportada pelas curvas elípticas. De forma bem simplista, eles terão que acordar sobre uma curva e seus parâmetros de domínio definidos pela tupla T.

    Alice determina Qa = Ka*P, sendo Qa sua chave pública e Ka sua chave privada.

    Bob determina Qb = Kb*P, sendo Qb sua chave pública e Kb sua chave privada.

    Assim, Alice pode calcular Kab = Ka*Qb = Ka*(Kb*P). Da mesma forma, Bob pode calcular Kab = Kb*Qa = Kb*(Ka*P). Sendo Ka e Kb escalares, temos que Alice e Bob conseguem definir uma chave exclusiva para se comunicarem sem que para isso precisem divulgar sua chave privada.

    Obviamente esta é uma demonstração muito simples e a própria definição dos parâmetros requer um conjunto de validações. Não basta escolher quaisquer parâmetros de curva.

    Uma descrição detalhada de todos os passos para a escolha dos parâmetros e suas validações pode ser encontrada em [6].

    Quebrando a criptografia

    Para o caso de P192, teríamos 3x10⁵⁷ adições a serem feitas para achar o k pelo método da força-bruta. A tabela abaixo ([6]) nos mostra que a criptografia com curvas elípticas entrega muito mais segurança com uma chave muito menor que aquela utilizada no RSA (as colunas ECC e DSA/RSA indicam o tamanho da chave).

    Entretanto em 2009 um conjunto de pesquisadores suíços utilizou um cluster de 200 Playstation 3 para quebrar com sucesso a criptografia com chave de 112 bits (Fp-112) e, por isso, recomenda-se atualmente o uso de chaves de 256 bits. Veja aqui e aqui mais detalhes sobre esta façanha.

    Conclusão

    Apesar da matemática significativamente mais complexa, a criptografia com curvas elípticas provê um processo cuja criptografia é simples e de implementação relativamente fácil em hardware, provendo criptografia eficiente com chave muito menor.

    No entanto ficamos com o sentimento que à medida que o poder computacional for crescendo, e vem crescendo de forma consistente com a Lei de Moore, novos algoritmos precisarão ser criados para que não tenhamos que usar chaves absurdamente grandes. Já estão aí os computadores quânticos, com um poder de processamento nunca visto anteriormente. Talvez as próximas pesquisas de criptografia tenham todas que se basear na criptografia quântica para garantir a segurança frente ao crescente poder computacional.

    Referências

    [1] Public-key criptography, em http://en.wikipedia.org/wiki/Public-key_cryptography, acessado em 20/04/2010.
    [2] Public Key Criptography, em http://www.livinginternet.com/i/is_crypt_pkc.htm, acessado em 20/04/2010.
    [3] Public Key Criptography (PKC) History, em http://www.livinginternet.com/i/is_crypt_pkc_inv.htm, acessado em 20/04/2010.
    [4] Anderson, R. "Security Engineering: A Guide to Building Dependable Distributed Systems", Wiley, 1a ed, 20o1.
    [6] SECG, "SEC 1: Elliptic Curve Cryptography", Standards for Efficient Cryptography Group - www.secg.org, 2009.
    [7] An Intro do Elliptical Curve Cryptography, em http://www.deviceforge.com/articles/AT4234154468.html, acessado em 22/04/2010.

    terça-feira, 6 de abril de 2010

    Especificação formal de protocolos de segurança

    Compartilho aqui um artigo que escrevi para a disciplina de Segurança Lógica que estou cursando atualmente no ITA. A validação formal de protocolos é um tema com que venho tendo contato há algum tempo e sobre o qual possuo bastante curiosidade, uma vez que se a implementação de um protocolo de segurança já não é simples, sua verificação, além de não ser simples, é fundamental para que o protocolo garanta os requisitos de segurança para o fim a que se propõe.

    Neste artigo introdutório abordamos o tema da especificação dos protocolos. A verificação ficará para um outro momento. Aguardo comentários e dicas que possam me auxiliar a enteder melhor o tema.

    View more documents from fabianmartins.

    sábado, 3 de abril de 2010

    Disney baseado em objetos

    Veja este vídeo:



    Você vai descobrir que os filmes da Disney são completamente orientado a objetos. Observe que cada caso de uso possui um conjunto de atores-base (classe-base) que são especializados conforme o tema do filme. Fica evidente o uso do modelo MVC (model-view-controller) onde os objetos que representam os personagens possuem diferentes views em diferentes filmes.

    Pode ser que eu esteja exagerando agora, mas não duvido que a Disney venha a possuir (ou já possua) um framework para o desenvolvimento e reaproveitamento de cenas e uma engine que utilize este framework para gerar cenas de filmes automaticamente. Quem sabe?

    Imagine: SnowWhiteGroupDance extends GroupDance .... :-P

    domingo, 10 de janeiro de 2010

    Tchau, Windows!

    A primeira grande mudança por aqui neste início de 2010 é que estou abandonando o Windows - tanto quanto possível.


    Eu vinha usando o Windows desde 1998 como meu principal sistema operacional, mais por que todo mundo usava, por causa dos jogos, e por que praticamente a totalidade dos meus clientes o utiliza.

    No entanto de uns tempos pra cá vinha me cansando das "blue screen of death", das atualizações duras (sempre tendo que reinicializar a máquina), de ter que formatar a máquina completamente para instalar a nova versão do sistema e, principalmente, de pagar caro pelo Office.

    Então desde o final do ano passado - final mesmo, última semana - abandonei o Windows e meu sistema operacional oficial agora é o Ubuntu, uma das distribuições mais populares e seguras do Linux, principalmente por sua facilidade de uso. Como estou há mais de 10 anos afastado de um uso mais "hard" do Linux, não teria melhor opção né?

    Mas não deu pra abandonar o Windows completamente. Ainda tenho uma conta bancária corporativa em um banco cujo site só funciona no Internet Explorer :-S. Para isso estou usando o VirtualBox pra rodar o meu antigo Windows XP, só para acessar este site. Bem, é lógico que vou utilizá-lo para realizar alguns testes e me divertir um pouco. Então, não foi de todo mal.

    Vou compartilhar com vocês minhas alegrias e tristezas desta nova decisão. Até agora foi tudo tranquilo e minha única dificuldade foi fazer meu token eCPF funcionar, mas isso é coisa para o próximo post.

    Até breve!

    Bem-vindo, 2010!

    Estamos aqui em 2010 voltando com o objetivo de manter este blog mais ativo do que foi possível em 2009. Em junho do ano passado perdemos a presença de alguém muito especial e as várias conseqüências me deixaram afastado das postagens. Mas isto é uma outra história; possivelmente para outro blog.