Convertendo livros em ePub para o Kindle com o kindlegen

Ultimamente compro meus eBooks na Amazon e leio-os no aplicativo Kindle para iPad. Uma das características que me levou a adotar o Kindle foi a sincronia que ele permite para livros pessoais enviados para a Amazon Cloud Drive. Sincroniza a última página de leitura, anotações e marcações.

Só que há aqueles que possuem livros no formato ePub (não suportado pelo Kindle) e eu mesmo disponibilizo alguns livros no formato ePub. Este pequeno tutorial tem por objetivo converter um livro no formato ePub para o formato Kindle.

O aplicativo utilizado será o kindlegen, desenvolvido pela própria Amazon. É um aplicativo de linha de comando, com versão para Windows, Linux e Mac OS. Disponível aqui.

Os livros convertidos pelo kindlegen contêm, num mesmo arquivo, os dois formatos suportados pelo Kindle, o formato KF8 e o Mobi. Então não há a necessidade de preocupação com qual Kindle (aplicativo ou ereader) o livro será lido.

Todos os comandos indicados no tutorial servem para qualquer versão utilizada.

Vamos utilizar, como exemplo, o ePub da Bíblia ACF 2007 (que pode ser baixado aqui no blog mesmo :) ). O nome do arquivo é ACF2007.epub.

Depois de baixado o kindlegen, descompacte o arquivo baixado e, no diretório onde ele foi descompactado, copie o arquivo ACF2007.epub (só para facilitar o trabalho).

CONVERTENDO DE EPUB PARA O FORMATO KINDLE

Para converter o arquivo, abra o prompt de comando ou o terminal e digite:

kindlegen ACF2007.epub

A conversão pode demorar dependendo do tamanho do arquivo ePub.

Terminada a conversão, haverá a criação de um arquivo ACF2007.mobi, com tamanho 7619 kB. O tamanho é maior que o ePub, pois o arquivo mobi gerado, como falei, contêm os dois formatos de livros Kindle, o KF8 (mais novo) e o Mobi (mais antigo, herança do Mobipocket).

COMPRESSÃO DO FORMATO KINDLE

Há algumas opções que podem ser aplicadas na conversão do arquivo e que o deixarão com tamanho menor. Uma delas é ativar a compressão do arquivo. O kindlegen nos permite três tipos:

  • sem compressão (opção -c0);
  • compressão padrão DOC (opção -c1; esta opção é utilizada mesmo que não se passe por parâmetro ao kindlegen);
  • compressão Kindle Huffdic (opção -c2)

Assim, para converter o arquivo ePub com a compressão Kindle huffdic utilizamos o comando abaixo:

kindlegen -c2 ACF2007.epub

Esta opção irá demorar mais para converter o livro, mas ele ficará com tamanho um pouco menor. Em termos de comparação veja a tabela abaixo quando utilizamos as diversas opções de compressão:

FORMATO|TAMANHO|COMPRESSÃO
 ePub  | 1520KB|-----
 Mobi  |14187KB|sem compressão
 Mobi  | 7619KB|compressão padrão DOC
 Mobi  | 5188KB|compressão Kindle huffdic

REMOVENDO OS ARQUIVOS FONTE DO FORMATO KINDLE

Quando um arquivo é convertido para o formato Kindle, são adicionados ao arquivo final, os arquivo fonte (source) que são utilizados para a construção final do arquivo, o que torna o tamanho final do arquivo mobi maior. Para não adicionar estes arquivos basta usar a opção -dont_append_source como parâmetro ao kindlegen, como mostrado no comando abaixo:

kindlegen -c2 -dont_append_source ACF2007.epub

Abaixo uma tabela comparando o tamanho dos arquivos gerados:

FORMATO|TAMANHO|SOURCE|COMPRESSÃO
 Mobi  | 5188KB|  NÃO |Kindle Huffdic
 Mobi  | 3669KB|  SIM |Kindle Huffdic

 

Publicado em Tutorial | Marcado com , , , | Deixe um comentário

Atualização na Bíblia ACF 2007 e remoção da ACF 1994

Há alguns meses, a SBTB entrou em contato comigo para falar um pouco do blog. E, nesta conversa, foi-me solicitado que removesse a versão 1994 da ACF, tendo em vista que o texto da 2007 já foi lançado para substituir essa edição (embora já exista a ACF 2011, mas como não tive acesso ao texto, nem me foi autorizado nada, a 2007 continua sendo a edição mais nova disponibilizada aqui no blog). Assim, a partir de hoje, disponibilizarei somente a versão da ACF 2007 e aproveito para liberar uma nova versão nos formatos ePub e mobi com pequenas correções e acréscimos, citados abaixo:

  • (correção) nome do livro de Miquéias;
  • (correção) remoção de espaços em branco entre alguns capítulos de salmos;
  • (adição) atendendo o pedido do leitor André, adicionei no Salmo 119, subtítulos com os nomes das letras em hebraico.
Publicado em Bíblia | Marcado com , , | Deixe um comentário

Criptografia: Cifra de Trithemius ou Tabula Recta em Python

No século XV o monge alemão Johannes Trithemius desenvolveu um cifra de criptografia polialfabética. Descrita em um de seus livros, o terceiro volume de uma série, esta cifra recebe o nome de Tabula Recta.

A Tabula Recta consiste numa tabela de 26×26 preenchida da seguinte maneira: a primeira linha (1) é preenchida com o alfabeto latino em ordem alfabética. A segunda linha (2) é o mesmo alfabeto só que deslocado uma casa para a esquerda. A terceira linha (3) é deslocada em mais uma casa e assim por diante até chegarmos a 25 deslocamentos. No 26º deslocamento o ciclo se reinicia voltando-se à configuração inicial da primeira linha (1).

  |A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|
-------------------------------------------------------
 1|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|
 2|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|
 3|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|
 4|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|
 5|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|
 6|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|
 7|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|
 8|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|
 9|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|
10|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|
11|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|
12|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|
13|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|
14|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|
15|O|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|
16|P|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|
17|Q|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|
18|R|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|
19|S|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|
20|T|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|
21|U|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|
22|V|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|
23|W|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|
24|X|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|
25|Y|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|
26|Z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|

Para cifrar uma mensagem basta começar com a primeira letra da mensagem e a primeira linha da tabela (a linha não numerada corresponde ao alfabeto plano, as demais são os alfabetos cifrados). Para cada letra adicional da mensagem pulamos para a linha seguinte até chegarmos ao final das linhas da tabela onde o ciclo se reinicia. Tomemos por exemplo a palavra guerra.

primeira letra - G
primeira linha - G -> G
segunda letra - U
segunda linha - U -> V
terceira letra - E
terceira linha - E -> G
quarta letra - R
quarta linha - R -> U
quinta letra - R
quinta linha - R -> V
sexta letra - A
sexta linha - A -> F

Assim, a palavra guerra, cifrada, fica GVGUVF. Observe que na cifra de Trithemius a primeira letra da mensagem não sofre alteração, o que facilita na decifragem da mensagem caso a pessoa saiba que foi utilizada esta cifra.

CÓDIGO

Abaixo há a classe Trithemius (salva no arquivo trithemius.py) e um arquivo para teste da cifra (arquivo teste_trithemius.py). A classe ignora espaços em branco e não trata caracteres especiais.

Classe Trithemius

# -*- coding: utf-8 -*-
import string

class Trithemius(object):
    '''
    Classe de cifra Trithemius
    '''
    def __init__(self):
        self.plain = string.ascii_uppercase
        self.cipher = string.ascii_uppercase

    def shift(self):
        '''
        Desloca o alfabeto cifrado em uma casa.
        '''
        self.cipher = self.cipher[1:] + self.cipher[:1]

    def encrypt(self, text, decrypt=False):
        '''
        Cifra text com a cifra de Trithemius.
        Se decrypt é True, decifra ao invés de cifrar o text.
        '''
        text = text.replace(' ', '')
        ret_text = ''
        for char in text.upper():
            if decrypt:
                idx = self.cipher.find(char)
                ret_text += self.plain[idx]
            else:
                idx = self.plain.find(char)
                ret_text += self.cipher[idx]
            self.shift()
        self.cipher = string.ascii_uppercase
        return ret_text

    def decrypt(self, text):
        '''
        Decifra text com a cifra de Trithemius.
        '''
        return self.encrypt(text, True)

BitBin

Arquivo para teste

# -*- coding: utf-8 -*-
from trithemius import Trithemius
import sys

versao = sys.version_info[0]

if versao == 2:
	leitura = raw_input
elif versao == 3:
	leitura = input

txt_in = leitura('Texto a ser cifrado: ')

trit = Trithemius()
txt_cifrado = trit.encrypt(txt_in)
print('Texto cifrado: {0}'.format(txt_cifrado))
print('Texto plano: {0}'.format(trit.decrypt(txt_cifrado)))

TESTE

Abaixo reproduzo a saída dos testes feito com a palavra guerra.

Texto a ser cifrado: guerra
Texto cifrado: GVGUVF
Texto plano: GUERRA

FONTES
http://www.numaboa.com.br/criptografia/substituicoes/polialfabeticas/805-trithemius
http://www.numaboa.com.br/criptografia/historia/347-segredo-trithemius
http://www.numaboa.com.br/criptografia/criptoanalise/1055-analise-trithemius
http://en.wikipedia.org/wiki/Tabula_recta
http://en.wikipedia.org/wiki/Trithemius_cipher

Publicado em Criptografia | Marcado com , , | Deixe um comentário

Token USB para GnuPG

Como já disse anteriormente, terminei uma especialização na área da criptografia e meu TCC foi sobre o GnuPG. Não pretendo aqui descrever a ferramenta, quem sabe mais para a frente, mas o que eu quero mostrar é como ter um token USB (como daqueles que podem ser adquiridos para certificado digital aqui no Brasil) para usar com o GnuPG.

Resolvi dividir o assunto em algumas partes para não ficar muito grande, assim, nesta primeira parte, mostro o equipamento adquirido, instalação dos drivers necessários para o uso e um teste rápido do produto.

As chaves do GnuPG ficam armazenadas no computador onde foi instalado e também podem ser armazenadas em um smart card, necessitando-se de um leitor de smart card para fazer a leitura do cartão.

Isto acaba tornando o uso das chaves com smart card pouco prático. Mas, caso se utilize um token USB, basta que o computador no qual desejamos utilizar o token tenha uma porta USB (e claro o driver apropriado do dispositivo :) ).

No momento há um projeto chamado Crypto Stick que está fabricando um dispositivo que possa ser utilizado como um token USB com suporte ao GnuPG. Recentemente eles disponibilizaram uma versão beta para quem quisesse adquirir o produto e que tem suas especificações mostradas aqui.

Mas existe um outro projeto, conhecido por OpenPGP Card, que é um smart card com suporte ao GnuPG, produzido pela g10code, uma empresa de consultoria na área de segurança fundada pelo criador do GnuPG. Há dois modelos de cartão: um similar àqueles de cartão de crédito e outro em que o chip é destacável, ficando no formato de um SIMCard.

Com este chip destacável, podemos utilizar um token USB que é produzido pela Gemalto, uma empresa que vende produtos voltados para segurança digital. O produto dela que serve para nossa finalidade é o IDBridge K30 ou USB Shell Token v2.

Adquiri um cartão e um token no site da Kernel Concepts. O cartão foi a versão com a opção de destaque do chip e o token foi o branco transparente (existe também uma versão em preto transparente).

Instalando o driver no Windows

Antes de utilizar o token, precisamos instalar o driver, que possui versões para Windows 32 ou 64 bits e está disponível aqui.

Baixei a versão Windows 64 bits  com o nome GemPcCCID_en-us_64.msi (observe que há para duas versões de Windows, uma em françês e outra em inglês; escolhi a inglês). A instalação é simples, basta seguir as indicações do instalador. Terminada esta parte vamos testar o token.

Instalando o driver no Linux

Também sou um usuário Linux, neste caso, utilizo o Lubuntu 14.04. De acordo com o site da Gemalto basta instalar a biblioteca libccid. Mas, eu descobri durante o teste, que se faz necessário uma outra biblioteca, a pcscd, pois sem ela não há comunicação com o leitor USB. Para isso proceda assim:

sudo apt-get install libccid pcscd

Testando o token USB

Com o token conectado na porta USB, abra o prompt de comando (ou terminal no Linux :) ) e digite (lembre-se que o GnuPG deve estar já instalado no sistema):

gpg --card-status

Algo similar ao resultado abaixo deve ser mostrado:

Application ID ...: D2760001240102000005000021150000
Version ..........: 2.0
Manufacturer .....: ZeitControl
Serial number ....: 00002115
Name of cardholder: [not set]
Language prefs ...: de
Sex ..............: unspecified
URL of public key : [not set]
Login data .......: [not set]
Signature PIN ....: forced
Key attributes ...: 2048R 2048R 2048R
Max. PIN lengths .: 32 32 32
PIN retry counter : 3 0 3
Signature counter : 0
Signature key ....: [none]
Encryption key....: [none]
Authentication key: [none]
General key info..: [none]

onde[1]:
Application ID – a identificação do fabricante, incluindo o tipo de cartão, a versão da implementação, o fabricante e o número serial. Este identificador é único para cada cartão.
Version – especificação OpenPGP usada.
Manufacturer – O fabricante do cartão.
Serial number – número único para todos os cartões deste fabricante.
Name of cardholder – o titular deste cartão. Somente caracteres ASCII são aceitos. gpg não usa este campo.
Language prefs – preferência de linguagem do titular do cartão. gpg ignora este valor.
Sex – Masculino ou feminino. gpg ignora este valor.
URL of public key – usado pelo comando fetch do gpg –edit-card. Pode conter uma URL que pode ser usada para recuperar a chave pública.
Login data – este campo pode ser usado para armazenar o nome da conta do titular. Pode ser usado para fins de identificação. gpg não aplica qualquer correspondência deste nome com um nome usado na chave. Veja a fonte (app-openpgp.c) para algumas características especiais do campo de login-name.
Signature PIN – quando configurado para “forced”, gpg solicita a entrada de um PIN para cada operação de assinatura. Quando configurado para “non forced”, gpg pode armazenar em cache o PIN pelo tempo em que o cartão não seja removido do leitor.
Key attributes – atributos das chaves.
Max. PIN lengths – este campo é imutável. Os valores são colocados no cartão logo após a personalização – este é o momento após o chip ser colado no cartão.
PIN retry counter – este campo salva quantas tentativas ainda restam para digitar o PIN correto. São diminuídas sempre que um PIN errado for inserido. Eles são repostos sempre que um AdminPIN correto for inserido. O primeiro e segundo PIN são para o PIN padrão. gpg garante que os dois números são sincronizados. O segundo PIN só é necessário devido às peculiaridades da norma ISO-7816; gpg tenta manter este PIN em sincronia com o primeiro PIN. O terceiro PIN representa o contador de repetição para o AdminPIN.
Signature counter – Este número mantém o controle das assinaturas realizadas com a chave armazenada. Ele só é reposto se uma nova chave de assinatura é criada ou importada para o cartão.
Signature key – esta chave é comumente usada como chave primária do OpenPGP.
Encryption key – esta chave é comumente usada como uma subchave para criptografar.
Authentication key – esta chave não é utilizada pelo gpg em tudo. Outras ferramentas como módulos PAM ou ssh usam esta chave para serviços de autenticação.
General key info – esse ID de usuário primário é mostrado se a chave pública OpenPGP correspondente está disponível.

Bom, por enquanto é só pessoal! :)

[1] https://www.gnupg.org/howtos/card-howto/en/smartcard-howto-single.html#id2505566

Publicado em Criptografia | Marcado com , | Deixe um comentário

Criptografia: Cifra ou disco de Alberti em Python

Leon Battista Alberti foi um autor, artista, arquiteto, poeta, sacerdote, linguista, filósofo e criptógrafo italiano que descreveu em um tratado (De Componendis Cifris ou De Cifris, 1466), uma técnica criptográfica que fazia uso de dois discos (um fixo e outro móvel) para cifrar e decifrar mensagens.

Como dito, os discos de Alberti são compostos por dois discos: um fixo e outro móvel. No disco fixo fica o alfabeto plano e no disco móvel fica o alfabeto cifrado. Alberti descreve dois métodos para cifragem/decifragem com os discos.

Disco de Alberti

Disco de Alberti

Para melhor exemplificar utilizaremos o disco da imagem acima, onde o disco fixo é o mais externo (com os caracteres maiúsculos) e o disco móvel é o disco interno (com os caracteres minúsculos).

Primeiro Método

Neste primeiro método escolhe-se um caracter do disco móvel que será utilizado como chave, por exemplo, a letra k. A cifragem se dá adicionando-se letras maiúsculas à mensagem a ser cifrada. Quando o usuário encontrar uma letra maiúscula no texto, a chave do disco móvel deve ser movida até que esta fique embaixo da letra maiúscula da mensagem. Agora, as demais letras são cifradas com as letras correspondentes ao disco móvel. Encontrando-se outra letra maiúscula, o disco móvel é deslocado até que a chave k fique abaixo da letra maiúscula no alfabeto plano e continua-se cifrando assim, até a mensagem acabar.

Como exemplo, vamos cifrar a mensagem ‘O sargento é o traidor’. Primeiro, todas as letras maiúsculas são convertidas em minúsculas, os espaços em branco são removidos e os caracteres especiais são trocados. Assim, a mensagem ficará ‘osargentoeotraidor’. Escolhemos a chave, neste caso a letra k, e qual será a letra inicial que será relacionada à chave. Para facilitar, escolhemos a letra B, como mostrado na imagem. Assim, a nossa mensagem deve começar com a letra B, ‘Bosargentoeotraidor’. Se adicionarmos outras letras maiúsculas na mensagem, o disco móvel deverá ser deslocado até que a chave, k, corresponda àquela letra. A mensagem final ficará assim: ‘BosargentoPeoStraidor’. Para cifrar checamos a letra minúscula da mensagem no disco fixo (com letras maiúsculas) e vemos qual é a letra correspondente no disco móvel (letras minúsculas). Abaixo um passo a passo:

Primeira iteração k -> B

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - g k l n p r t v z & x y s o m q i h f d b a c e

texto plano   - B o s a r g e n t o P e o S t r a i d o r
texto cifrado - B y q g m t p x i y P

Segunda iteração k -> P

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - o m q i h f d b a c e g k l n p r t v z & x y s

texto plano   - B o s a r g e n t o P e o S t r a i d o r
texto cifrado - B y q g m t p x i y P h g S

Terceira iteração k -> S

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - x y s o m q i h f d b a c e g k l n p r t v z &

texto plano   - B o s a r g e n t o P e o S t r a i d o r
texto cifrado - B y q g m t p x i y P h g S l g x h o a g

Nossa mensagem cifrada será ByqgmtpxiyPhgSlgxhoag.

Segundo Método

O segundo método muda um pouco, pois ao invés de se usar letras, usam-se os números que existem no disco fixo. Desta vez escolhe-se como chave um caracter do disco fixo como índice e uma letra do alfabeto cifrado para posição inicial. Ao se encontrar um número na mensagem a ser cifrada, a letra do disco móvel correspondente ao número no disco fixo é movida até corresponder com a letra escolhida como índice no disco fixo. E a cifragem continua assim até o fim da mensagem. Vamos utilizar a mesma mensagem do primeiro método: ‘O sargento é o traidor’. Trocamos todos os caracteres maiúsculos por minúsculos, removemos os caracteres em branco e trocamos os caracteres especiais. No final ficamos com a mensagem ‘osargentoeotraidor’.

Escolheremos a letra D no disco fixo como índice e a letra p no disco móvel como caracter inicial de cifragem. Adicionaremos alguns números (entre 1 e 4) e os inseriremos nos locais que desejarmos na mensagem a ser cifrada. A mensagem final será ‘Dosar1gento4eotra2idor’. Abaixo o passo a passo para cifragem:

Primeira iteração p -> D

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - k l n p r t v z & x y s o m q i h f d b a c e g

texto plano   - D o s a r 1 g e n t o 4 e o t r a 2 i d o r
texto cifrado - D s i k q 1

Segunda iteração 1 (a) -> D

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - f d b a c e g k l n p r t v z & x y s o m q i h

texto plano   - D o s a r 1 g e n t o 4 e o t r a 2 i d o r
texto cifrado - D s i k q 1 g c p x r 4

Terceira iteração 4 (h) -> D

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - m q i h f d b a c e g k l n p r t v z & x y s o

texto plano   - D o s a r 1 g e n t o 4 e o t r a 2 i d o r
texto cifrado - D s i k q 1 g c p x r 4 f k t p m 2

Quarta iteração 2 (y) -> D

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - z & x y s o m q i h f d b a c e g k l n p r t v

texto plano   - D o s a r 1 g e n t o 4 e o t r a 2 i d o r
texto cifrado - D s i k q 1 g c p x r 4 f k t p m 2 q y d c

Assim, a mensagem cifrada será Dsikq1gcpxr4fktpm2qydc.

Terceiro Método

Afora os dois métodos citados por Alberti, podemos criar um outro método que utilizaria um sistema de deslocamento automático sem que precisemos inserir outros caracteres na mensagem, bastaria somente escolher a letra inicial do disco fixo, a letra inicial do disco móvel e um número de deslocamento automático. Este número de deslocamento indicaria quantas casas o disco móvel seria deslocado, para a direita ou esquerda, a cada cifragem de um caracter. Para facilitar vamos utilizar uma mensagem menor : ‘perigo’. Escolhemos a letra O do disco fixo, a letra c do disco móvel e o número 2 como chave de deslocamento.

Primeiro caracter (p)

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - y s o m q i h f d b a c e g k l n p r t v z & x

texto plano   - p e r i g o
texto cifrado - e

Segundo caracter (e)

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - & x y s o m q i h f d b a c e g k l n p r t v z

texto plano   - p e r i g o
texto cifrado - e o

Terceiro caracter (r)

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - v z & x y s o m q i h f d b a c e g k l n p r t

texto plano   - p e r i g o
texto cifrado - e o a

Quarto caracter (i)

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - r t v z & x y s o m q i h f d b a c e g k l n p

texto plano   - p e r i g o
texto cifrado - e o a s

Quinto caracter (g)

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - n p r t v z & x y s o m q i h f d b a c e g k l

texto plano   - p e r i g o
texto cifrado - e o a s &

Sexto caracter (o)

DISCOS
FIXO  - A B C D E F G I L M N O P Q R S T V X Z 1 2 3 4
MÓVEL - k l n p r t v z & x y s o m q i h f d b a c e g

texto plano   - p e r i g o
texto cifrado - e o a s & s

A mensagem cifrada será eoas&s.

CÓDIGO

Abaixo o código da classe que implementa os três métodos acima descritos e também com funções que nos permitem adicionar alfabetos personalizados e de tamanho variado, não nos limitando ao alfabeto do disco da imagem no início do post. O código foi salvo no arquivo alberti.py.

class Alberti:
	def shift(self, shift):
		''' (int) -> None
		Desloca o disco movel a quantidade de elementos em shift.
		'''
		shift = -shift
		self.movable_disk = self.movable_disk[shift:] + self.movable_disk[:shift]

	def set_fixed_disk(self, plain_alphabet):
		''' (str) -> None
		Configura o alfabeto do disco fixo com o texto de plain_alphabet.
		'''
		self.fixed_disk = plain_alphabet.upper()

	def set_movable_disk(self, cipher_alphabet):
		''' (str) -> None
		Configura o alfabeto do disco movel com o texto de cipher_alphabet.
		'''
		self.movable_disk = cipher_alphabet.lower()

	def set_keys(self, fixed_key, movable_key):
		''' (char, charstr) -> None
		Configura as chaves do disco fixo e do disco movel;
		Desloca o disco movel de acordo com as chaves.
		'''
		self.set_fixed_key(fixed_key)
		self.set_movable_key(movable_key)
		fixed_id = self.fixed_disk.find(self.fixed_key)
		movable_id = self.movable_disk.find(self.movable_key)
		shift = fixed_id - movable_id
		self.shift(shift)

	def encrypt(self, plaintext, shift = 0, decrypt = False):
		''' (str, [int], [bool]) -> str
		Cifra o plaintext com a cifra de Alberti.
		'''
		ciphertext = ''
		for ch in plaintext:
			if ch.isupper():
				#letra maiuscula
				self.set_keys(ch, self.movable_key)
			elif ch.isdigit():
				#numero
				movable_key = self.movable_disk[self.fixed_disk.find(ch)]
				self.set_keys(self.fixed_key, movable_key)
			else:
				#letra minuscula
				if decrypt:
					#decifrando
					i = self.movable_disk.find(ch)
					ch = self.fixed_disk[i].lower()
				else:
					#cifrando
					i = self.fixed_disk.find(ch.upper())
					ch = self.movable_disk[i]
				if shift:
					#deslocamento
					self.shift(shift)
			ciphertext += ch
		return ciphertext

	def decrypt(self, ciphertext, shift = 0):
		''' (str, [int]) -> str
		Decifra utilizando a cifra de Alberti.
		'''
		#return self.encrypt(ciphertext, shift, True)
		text = ''
		plaintext = self.encrypt(ciphertext, shift, True)
		for ch in plaintext:
			if ch.islower():
				text += ch
		return text

	def set_fixed_key(self, fixed_key):
		''' (char) -> None
		Configura a chave do disco fixo.
		'''
		self.fixed_key = fixed_key.upper()

	def set_movable_key(self, movable_key):
		''' (char) -> None
		Configura a chave do disco movel.
		'''
		self.movable_key = movable_key.lower()

BitBin

TESTES

Desta feita, não vou mostrar o uso da classe, mas vou criar um arquivo de teste e importar a classe Alberti para ele e executar a cifragem/decifragem dos exemplos citados no post. Este código teste foi salvo no arquivo alberti_teste.py e deve ser salvo no mesmo diretório do arquivo alberti.py.

from alberti import Alberti
alb = Alberti()

## PRIMEIRO METODO
##alfabeto do disco fixo
alb.set_fixed_disk('ABCDEFGILMNOPQRSTVXZ1234')
##alfabeto do disco movel
alb.set_movable_disk('gklnprtvz&xysomqihfdbace')
##chave do disco movel
alb.set_movable_key('k')
cifrado = alb.encrypt('BosargentoPeoStraidor')
print 'Cifrando/Decifrando com o primeiro metodo da cifra de Alberti'
print 'Texto cifrado - ' + cifrado
print 'Texto decifrado - ' + alb.decrypt(cifrado)
print ''

## SEGUNDO METODO
##chave inicial do disco movel
alb.set_movable_key('p')
print 'Cifrando/Decifrando com o segundo metodo da cifra de Alberti'
cifrado = alb.encrypt('Dosar1gento4eotra2idor')
print 'Texto cifrado - ' + cifrado
##chave inicial do disco movel
alb.set_movable_key('p')
print 'Texto decifrado - ' + alb.decrypt(cifrado)
print ''

## TERCEIRO METODO
print 'Cifrando/Decifrando com o terceiro metodo'
##chaves do disco fixo e do disco movel
alb.set_keys('O', 'c')
cifrado = alb.encrypt('perigo', 2)
print 'Texto cifrado - ' + cifrado
alb.set_keys('O', 'c')
print 'Texto decifrado - ' + alb.decrypt(cifrado, 2)

O arquivo acima, sendo executado, tem como saída o resultado abaixo:

Cifrando/Decifrando com o primeiro metodo da cifra de Alberti
Texto cifrado - ByqgmtpxiyPhgSlgxhoag
Texto decifrado - osargentoeotraidor

Cifrando/Decifrando com o segundo metodo da cifra de Alberti
Texto cifrado - Dsikq1gcpxr4fktpm2qydc
Texto decifrado - osargentoeotraidor

Cifrando/Decifrando com o terceiro metodo
Texto cifrado - eoas&s
Texto decifrado - perigo

Fontes:
http://en.wikipedia.org/wiki/Alberti_cipher_disk
http://en.wikipedia.org/wiki/Alberti_cipher
http://www.numaboa.com.br/criptografia/historia/158-alberti
http://www.numaboa.com.br/criptografia/127-substituicao-polialfabetica/164-alberti

Publicado em Criptografia | Marcado com , , | 4 Comentários

Criptografia: Cifra de Políbio ou Quadrado de Políbio em Python

A cifra de Políbio ou quadrado de Políbio, é um cifra de substituição relatada pelo historiador grego Políbio em seu livro Histórias, que trata da ascensão do Império Romano.

Seu princípio de funcionamento consiste numa tabela quadrada (mesmo número de linhas e colunas :) ), onde os caracteres são disponibilizados um em cada célula desta tabela. Políbio utilizava um quadrado de 5×5, ou seja, 25 células e utilizava o alfabeto grego de 24 caracteres. A última célula era preenchida com um sinal para sincronização.

Trazendo para nossos dias, utilizamos o mesmo quadrado de 5×5 e o alfabeto latino de 26 letras. Como há uma letra a mais, nos utilizaremos de um artifício em unir duas letras numa mesma célula. Em alguns sites, com conteúdo em inglês, costuma-se unir as letras i e j numa mesma célula, ficando o quadrado como demonstrado abaixo:

    1   2   3    4    5
1 | a | b | c |  d  | e |
2 | f | g | h | i/j | k |
3 | l | m | n |  o  | p |
4 | q | r | s |  t  | u |
5 | v | w | x |  y  | z |

O processo de cifragem se dá pela troca da letra do alfabeto normal pelo número da linha seguido pelo número da coluna, por exemplo, a letra a ficará 11, a b, 12 e assim por diante. Assim, a palavra guerra, cifrada, ficará: 22 45 15 42 42 11 ou 224515424211. O processo de decifragem é o inverso: pega-se o número da linha e da coluna e substitui-se pela letra correspondente na célula.

Por exemplo, o código 24 34 22 34 43 14 15 22 45 15 42 42 11, decifrado, fica iogosdeguerra (note que a palavra iogos deveria ser jogos, mas, como comprimimos as letras i e j na mesma célula, na decifragem utilizamos somente uma delas, neste caso, a letra i. E como as partes envolvidas na comunicação sabem deste detalhe, fica fácil para alternar entre as duas letras).

Uma outra forma de utilizar o quadrado de Políbio é expandi-lo para a utilização das letras do alfabeto e os numerais de 0 a 9. Assim, nosso quadrado para a ser de 6×6, ficando como mostrado abaixo:

    1   2   3   4   5   6
1 | a | b | c | d | e | f |
2 | g | h | i | j | k | l |
3 | m | n | o | p | q | r |
4 | s | t | u | v | w | x |
5 | y | z | 0 | 1 | 2 | 3 |
6 | 4 | 5 | 6 | 7 | 8 | 9 |

Desta forma, não precisamos ter dois caracteres numa mesma célula. Utilizando este quadrado a frase A senha de acesso ao sistema é 1945, cifrada, fica (lembrando que desconsiderei os espaços em branco e caracteres especiais): 11 41 15 32 22 11 14 15 11 13 15 41 41 33 11 33 41 23 41 42 15 31 11 15 54 66 61 62.

Para dificultar um pouco mais o trabalho de quem tenta decifrar nossa mensagem ultra-secreta :) , há a possibilidade de se utilizar uma palavra-chave com a cifra de Políbio. Se utilizarmos a palavra-chave cavalaria, nosso quadrado ficará como mostrado abaixo:

    1   2   3   4   5   6
1 | c | a | v | l | r | i |
2 | j | k | m | n | o | p |
3 | q | s | t | u | w | x |
4 | y | z | 0 | 1 | 2 | 3 |
5 | 4 | 5 | 6 | 7 | 8 | 9 |
6 | b | d | e | f | g | h |

Utilizamos o mesmo conceito aplicado na cifra de substituição simples. As letras repetidas da palavra chave são removidas, cavalaria fica cavlri, e preenchemos as demais células com as letras restantes do alfabeto, seguidas dos numerais de 0 a 9.

E, a mesma frase, A senha de acesso ao sistema é 1945, cifrada, fica: 12 32 63 24 66 12 62 63 12 11 63 32 32 25 12 25 32 16 32 33 63 23 12 63 44 56 51 52.

CÓDIGO

O código foi salvo no arquivo Polybius.py. Lembrando que caracteres especiais não são tratados e os espaços em branco são descartados.

class Polybius:
    def __init__(self):
        ## p_alphabet nao possui a letra j, que sera substituida
        ## pela letra i na cifragem e decifragem
        self.p_alphabet = 'abcdefghiklmnopqrstuvwxyz'
        self.p_alphanum = 'abcdefghijklmnopqrstuvwxyz0123456789'

    def cipher_alphabet(self, password):
        ''' (str) -> str
        Retorna um alfabeto cifrado iniciado com
        o texto da palavra chave password
        '''
        c_alphabet = []
        p_alphabet = self.p_alphanum
        for ch in password:
            if ch not in c_alphabet:
                c_alphabet.append(ch)
                idx = p_alphabet.find(ch)
        p_alphabet = p_alphabet[idx:] + p_alphabet[:idx]
        for ch in p_alphabet:
            if ch not in c_alphabet:
                c_alphabet.append(ch)
        return ''.join(c_alphabet)

    def create_square(self, alphabet, lines):
        ''' (list, int) -> list of str
        Retorna uma tabela lista quadrada definida por lines
        com cada celula preenchida com um caracter de alphabet
        '''
        square = []
        temp = []
        count = 0
        for ch in alphabet:
            temp.append(ch)
            count += 1
            if count == lines:
                square.append(temp)
                temp = []
                count = 0
        return square

    def select_square(self, key):
        ''' (int) -> list of str
        Retorna o quadrado de Polibio referente a key utilizada.
        Se key for True, usa-se o quadrado de Polibio com letras e numerais;
        Se key for uma string, retorna o quadrado de Polibio com key como palavra chave.
        Se nao houver key, usa-se o quadrado de Polibio padrao.
        '''
        if key:
            if key == True:
                return self.create_square(self.p_alphanum, 6)
            else:
                return self.create_square(self.cipher_alphabet(str(key)), 6)
        return self.create_square(self.p_alphabet, 5)

    def encrypt(self, plaintext, key = None):
        ''' (str, str) -> str
        Retorna o plaintext cifrado com a cifra de Polibio.
        Se key = True, cifra com quadrado de Polibio com letras e numeros.
        Se key = uma string, cifra o quadrado de Polibio com key como palavra chave.
        Se nao houver key, cifra com o quadrado de polibio padrao.
        '''
        square = self.select_square(key)
        ciphertext = ''
        for ch in plaintext.lower():
            idx = 1
            if ch == 'j':
                ch = 'i'
            for linha in square:
                if ch in linha:
                    ciphertext += str(idx) + str(linha.index(ch) + 1) + ' '
                idx += 1
        return ciphertext

    def decrypt(self, ciphertext, key = None):
        ''' (str, str) -> str
        Retorna o ciphertext decifrado com a cifra de Polibio.
        Se key = True, decifra com quadrado de Polibio com letras e numeros.
        Se key = uma string, decifra o quadrado de Polibio com key como palavra chave.
        Se nao houver key, decifra com o quadrado de polibio padrao.
        '''
        square = self.select_square(key)
        plaintext = ''
        ciphertext = str(ciphertext).replace(' ', '')
        for num in range(0, len(ciphertext), 2):
            var = int(ciphertext[num:num + 2])
            i, j = var / 10, var % 10
            if i - 1 < len(square) and j - i < len(square[0]):
                plaintext += square[i - 1][j - 1]
        return plaintext.lower()

BitBin

TESTES

>>> from polybius import Polybius
>>> Polybius().encrypt('jogos de guerra')
'24 34 22 34 43 14 15 22 45 15 42 42 11 '
>>> Polybius().decrypt('24 34 22 34 43 14 15 22 45 15 42 42 11')
'iogosdeguerra'
>>> Polybius().decrypt(24342234431415224515424211)
'iogosdeguerra'
>>> Polybius().encrypt('Senha de acesso e 1986', True)
'41 15 32 22 11 14 15 11 13 15 41 41 33 15 54 66 65 63 '
>>> Polybius().decrypt('41 15 32 22 11 14 15 11 13 15 41 41 33 15 54 66 65 63', True)
'senhadeacessoe1986'
>>> Polybius().encrypt('Senha de acesso e 1986', 'cavalaria')
'32 63 24 66 12 62 63 12 11 63 32 32 25 63 44 56 55 53 '
>>> Polybius().decrypt('32 63 24 66 12 62 63 12 11 63 32 32 25 63 44 56 55 53',  'cavalaria')
'senhadeacessoe1986'

Fontes:

http://www.numaboa.com.br/criptografia/128-substituicao-tomografica/179-polibio

http://en.wikipedia.org/wiki/Polybius

Publicado em Criptografia | Marcado com , | Deixe um comentário

Criptografia: Cifra de substituição simples em Python

Depois de uma breve explicação sobre a classificação das cifras, vamos alterar uma das cifras utilizadas no blog. Já falamos da cifra de César. E, como sabemos, o algoritmo da cifra consiste na substituição de uma letra do alfabeto por sua correspondente seguindo o deslocamento indicado por uma chave numérica. No caso específico de César a chave era o número 3, mas podemos utilizar qualquer número entre 1 e 25 (pois nosso alfabeto é composto por 26 letras :) ).

Mas, se no lugar da chave numérica, usarmos uma chave composta por uma palavra? Com isso poderíamos criar um alfabeto de cifragem ou alfabeto cifrado próprio. Assim, transformamos a cifra de César em uma cifra de substituição simples. Por exemplo, se a palavra chave fosse CAVALARIA:

alfabeto normal  - |a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|
alfabeto cifrado - |C|A|V|L|R|I|J|K|M|N|O|P|Q|S|T|U|W|X|Y|Z|B|D|E|F|G|H|

Observe que as letras repetidas são excluídas (CAVALARIA fica CAVLRI) e são colocadas no início do alfabeto de cifragem; e o restante do alfabeto cifrado é completado iniciando-se a partir da última letra da palavra chave (em nosso caso a letra J). Assim, a frase ‘atacaremos ao amanhecer’, fica: CZCVCXRQTYCTCQCSKRVRX.

CÓDIGO

class SimpleSubstitution:
	def __init__(self):
		self.p_alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
		self.decrypting = False

	def cipher_alphabet(self, password):
		''' (str) -> str
		Retorna um alfabeto cifrado iniciado com
		o texto da palavra chave password
		'''
		c_alphabet = []
		password = password.upper()
		for ch in password:
			if ch not in c_alphabet:
				c_alphabet.append(ch)
				idx = self.p_alphabet.find(ch)
		p_alphabet = self.p_alphabet[idx:] + self.p_alphabet[:idx]
		for ch in p_alphabet:
			if ch not in c_alphabet:
				c_alphabet.append(ch)
		return ''.join(c_alphabet)

	def encrypt(self, plaintext, password):
		'''(str, str) -> str
		Retorna o texto plano cifrado com a cifra de
		substituicao com a palavra chave password
		'''
		txt = ''
		p_alphabet = self.p_alphabet
		text = plaintext.replace(' ', '').upper()
		cipher = self.cipher_alphabet(password)
		if self.decrypting:
			p_alphabet, cipher = cipher, p_alphabet
			self.decrypting = False
		for ch in text:
			txt += cipher[p_alphabet.find(ch)]
		return txt

	def decrypt(self, ciphertext,  password):
		'''(str, str) -> str
		Retorna o texto cifrado decifrado com a cifra de
		substituicao com a palavra chave password
		'''
		self.decrypting = True
		return self.encrypt(ciphertext, password)

BitBin

Esta classe não trata caracteres acentuados e despreza os espaços em branco.

TESTES

O código foi salvo no arquivo simple_substitution.py

>>> import simple_substitution
>>> SimpleSubstitution().encrypt('O treinamento ocorrera no periodo da manha', 'cavalaria')
'TZXRMSCQRSZTTVTXXRXCSTURXMTLTLCQCSKC'
>>> SimpleSubstitution().decrypt('TZXRMSCQRSZTTVTXXRXCSTURXMTLTLCQCSKC', 'cavalaria')
'OTREINAMENTOOCORRERANOPERIODODAMANHA'
Publicado em Criptografia | Marcado com , | Deixe um comentário