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

Correção dos módulos das Bíblias ACF e ACF 2007 para o e-Sword

Conforme relatado no comentário do Hiroshi, os módulos da ACF e da ACF 2007 estavam com os versículos 23 a 29 do capítulo 3 do livro de Daniel faltando.

Corrigi o erro e estou disponibilizando os módulos novamente. Ambos foram testados com o e-Sword 10.2.1.

Para instalar baixe os arquivo ACF.bblx ou ACF2007.bblx e copie-os para o diretório onde está instalado o e-Sword.

[ATUALIZAÇÃO 22/01/2014]

Conforme relatado no comentário do Jean, o livro de Hebreus, na ACF 1994, não estava aparecendo. Problema corrigido e novo arquivo disponibilizado.

[ATUALIZAÇÃO 28/11/2013]

Corrigido o problema da busca com palavras acentuadas. E, como crédito, o tamanho dos arquivos diminuiu. :) .

Publicado em Bíblia | Marcado com , , | 6 Comentários

Criptografia: cifras de transposição e cifras de substituição

Até o momento apresentamos quatro cifras diferentes. Mas elas podem ser classificadas de acordo com seu método de cifragem.

Cifras de Transposição

Uma cifra é caracterizada como cifra de transposição quando os caracteres do texto plano são trocados de posição entre si seguindo uma determinada regra (o algoritmo da cifra). Assim, as cifras rail fence (cerca de trilhos) e scytale espartano, caracterizam-se como cifras de transposição.

Cifras de Substituição

Uma cifra de substituição tem como característica a permanência do caracter do texto plano em sua posição original, mas o mesmo é substituído por outro caracter ou símbolo de um conjunto pré-escolhido, chamado de alfabeto de substituição ou alfabeto de cifra. Além de caracteres isolados, palavras ou até mesmo frases podem ser substituídas.

Existem algumas classificações para as cifras de substituição: monoalfabéticas ou simples, homófonas, polialfabéticas, poligrâmicas e poligráficas.

A substituição simples ou monoalfabética é aquela em que para cada caracter do texto plano corresponde um só caracter ou símbolo do alfabeto de substituição.

A substituição homófona possui um ou mais símbolos para alguns caracteres do alfabeto normal.

Já as cifras de substituição polialfabéticas são as que utilizam mais de um alfabeto de substituição para o alfabeto normal.

Por último, as cifras de substituição poligráficas substituem grupos de caracteres da mensagem por símbolos.

A cifra de César e as cifras hebraicas são exemplos de cifras de substituição simples.

Publicado em Criptografia | Marcado com , , , | 1 comentário

Criptografia: cifras hebraicas (Atbash, Atbah e Albam) em Python

Você já leu a Bíblia? Não? Mas deve saber de que livro estou falando.

Se você já a leu, deve ter lido o livro do profeta Jeremias, certo?

Pois bem, neste livro, algumas palavras do texto foram cifradas utilizando a cifra Atbash.

O Atbash vem da grafia das letras hebraicas Aleph, Tav, Beth, Shin. O seu funcionamento é bem simples: a primeira letra do alfabeto é trocada pela última, a segunda letra pela penúltima e assim sucessivamente. Abaixo um resumo com os caracteres latinos do alfabeto português:

texto plano  - |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|
cifra Atbash - |Z|Y|X|W|V|U|T|S|R|Q|P|O|N|M|L|K|J|I|H|G|F|E|D|C|B|A|

Como exemplo, a palavra biblia em Atbash fica: YRYORZ.

Há duas outras cifras hebraicas chamadas Atbah e Albam.

Seguindo o mesmo procedimento a cifra Atbah vem da grafia das letras hebraicas Aleph, Teth, Beth e Heth e a cifra Albam das letras  Aleph, Lamed, Beth e Mem.

Para cifrar com Albam, primeiro divide-se o alfabeto normal em duas metades. A segunda metade do alfabeto é colocada na frente da primeira metade e a cifragem se dá pela troca da primeira letra do alfabeto normal pela primeira letra deste alfabeto trocado; a segunda letra do alfabeto normal pela segunda do alfabeto trocado e assim por diante. A tabela abaixo demonstra isto melhor.

texto plano - |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|
cifra Albam - |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|Z|

Então, a palavra biblia em Albam fica: OVOYVN.

Já a cifra Atbah segue uma sequência própria para a cifragem. Abaixo a tabela com a cifra.

texto plano - |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|
cifra Atbah - |I|H|G|F|N|D|C|B|A|R|Q|P|O|E|M|L|K|J|Z|Y|X|W|V|U|T|S|

A palavra biblia em Albam: HAHPAI.

CÓDIGO

Resolvi implementar as três cifras numa classe só e a chamei de hebrew.py. A classe descarta os espaços em branco e não trata caracteres especiais.

class HebrewCipher:
    atbash = 'ZYXWVUTSRQPONMLKJIHGFEDCBA'
    albam = 'NOPQRSTUVWXYZABCDEFGHIJKLM'
    atbah = 'IHGFNDCBARQPOEMLKJZYXWVUTS'

    def __init__(self):
        self.__plain = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

    def encrypt(self, text, cipher):
        ''' (HebrewCipher, str, str) -> str
        Retorna o texto cifrado com
        a cifra hebraica escolhida
        '''

        txt = ''
        text = text.replace(' ', '').upper()
        for ch in text:
            idx = self.__plain.find(ch)
            txt += cipher[idx]
        return txt

    def decrypt(self, text, cipher):
        ''' (HebrewCipher, str, str) -> str
        Retorna o texto decifrado com
        a cifra hebraica escolhida
        '''
        return self.encrypt(text, cipher).lower()

BitBin

TESTES

>>> from hebrew import HebrewCipher
>>> HebrewCipher().encrypt('o livro cristao e a biblia', HebrewCipher.atbash)
'LOREILXIRHGZLVZYRYORZ'
>>> HebrewCipher().decrypt('LOREILXIRHGZLVZYRYORZ', HebrewCipher.atbash)
'olivrocristaoeabiblia'
>>> HebrewCipher().encrypt('o livro cristao e a biblia', HebrewCipher.albam)
'BYVIEBPEVFGNBRNOVOYVN'
>>> HebrewCipher().decrypt('BYVIEBPEVFGNBRNOVOYVN', HebrewCipher.albam)
'olivrocristaoeabiblia'
>>> HebrewCipher().encrypt('o livro cristao e a biblia', HebrewCipher.atbah)
'MPAWJMGJAZYIMNIHAHPAI'
>>> HebrewCipher().decrypt('MPAWJMGJAZYIMNIHAHPAI', HebrewCipher.atbah)
'olivrocristaoeabiblia'

Fontes:
http://www.numaboa.com.br/criptografia/124-substituicao-simples/168-atbash
http://en.wikipedia.org/wiki/Atbash
http://mysteriouswritings.com/the-atbash-cipher-and-jeremiah-511/

Publicado em Criptografia | Marcado com , , , , | 1 comentário