Criptografia: Cifra ADFGX em Python

Em 1918, durante a Primeira Guerra Mundial, o coronel alemão Fritz Nebel, oficial de inteligência, desenvolveu um cifra criptográfica, utilizada pela primeira vez em 5 de março de 1918.

Uma combinação de vários métodos (tais como o quadrado de Políbio com uma transposição de colunas) resultou na cifra ADFGX.

Como o quadrado de Políbio, a cifra utiliza um quadrado de 5×5, onde cada coluna e cada linha é identificada por uma letra (A, D, F, G, X).

A cifragem ADFGX tem dois passos: o primeiro consiste em distribuir o alfabeto cifrado no quadrado de 5×5 e o segundo passo consiste numa tabela de transposição com um índice de coluna determinado por uma senha.

Escolhemos um alfabeto de 25 letras (neste caso, o J será substituído pelo I) e o distribuímos no quadrado criado. Escolhemos o alfabeto cifrado ZCBDMHAOINLRSPQWXEUTYFGKV.

  A|D|F|G|X
A|Z|C|B|D|M
D|H|A|O|I|N
F|L|R|S|P|Q
G|W|X|E|U|T
X|Y|F|G|K|V

Para cifrarmos um texto, procuramos a letra do texto a ser cifrado, identificando a linha e a coluna e copiamos seus respectivos índices. Por exemplo, a letra A cifrada ficará como DD. Vamos cifrar a frase ‘guerra mundial’. Lembre-se que se o texto contiver o J, este deve ser cifrado como I.

O texto da primeira etapa fica assim: XF GG GF FD FD DD AX GG DX AG DG DD FA

A segunda parte da cifram consiste no uso de uma senha de até 26 caracteres, não repetidos. Para cada letra será criada uma coluna e as linhas serão compostas pelo texto cifrado resultante do primeiro passo. O preenchimento se dá da primeira coluna até chegar a última, e se ainda restarem caracteres, uma nova linha é criada. O processo segue até o último caractere. Vamos usar, como exemplo, a senha CHAVE:

C|H|A|V|E
X|F|G|G|G
F|F|D|F|D
D|D|A|X|G
G|D|X|A|G
D|G|D|D|F
A| | | |

Terminado o preenchimento, vem a parte da transposição das colunas. Neste caso as colunas e seus conteúdos, são transpostos para que as letras fiquem em sentido crescente do alfabeto. Sendo assim:

A|C|E|H|V
G|X|G|F|G
D|F|D|F|F
A|D|G|D|X
X|G|G|D|A
D|D|F|G|D
 |A| | |

Agora, para formamos o texto cifrado final, basta que efetuemos a leitura de cada coluna, de cima para baixo. Assim, o texto ‘guerra mundial’, cifrado, ficará:

GDAXDXFDGDAGDGGFFFDDGGFXAD

CÓDIGO

O código foi salvo no arquivo adfgx.py.

# -*- coding: utf-8 -*-
""" Cifra ADFGX """
from cipher import Cipher

class ADFGX(Cipher):
    """ Cifra ADFGX """
    def __init__(self):
        self.chars = {
            'A': 0, 'D': 1, 'F': 2,
            'G': 3, 'X': 4
        }
        self.replace = ()

    def create_square(self, alphabet):
        """ Cria o quadrado para o alfabeto cifrado """
        self.square = Cipher.create_square(self, alphabet=alphabet)

    def get_adfgx(self, col, lin):
        """ Com as coordenadas, retorna o par de letras ADFGX correspondente """
        out = ''
        for char, value in self.chars.items():
            if col == value:
                out = char + out
            if lin == value:
                out += char
        return out

    def get_letter(self, ch):
        """ Com um par ADFGX, retorna uma letra do quadrado """
        i = self.chars[ch[0]]
        j = self.chars[ch[1]]
        return self.square[i][j]

    def set_replace(self, ch1, ch2):
        """ Substitui ch1 por ch2 """
        self.replace = (ch1, ch2)

    def encrypt(self, text, key):
        """ Cifra o texto com a cifra ADFGX """
        text = self.format_str(text)
        if self.replace:
            if self.replace[0] in text:
                text = text.replace(self.replace[0], self.replace[1])
        txt = []
        for letra in text:
            for col, text in enumerate(self.square):
                if letra in text:
                    lin = text.index(letra)
                    txt.append(self.get_adfgx(col, lin))
        ctxt = {}
        idx = 0
        for ch in ''.join(txt):
            if ctxt.get(key[idx]):
                ctxt[key[idx]] = ctxt.get(key[idx]) + ch
            else:
                ctxt[key[idx]] = ch
            if idx < len(key) - 1:
                idx += 1
            else:
                idx = 0
        ciphertext = ''
        for ch in sorted(ctxt):
            ciphertext += ctxt[ch]
        return ciphertext

    def decrypt(self, text, key):
        """ Decifra texto cifrado com a cifra ADFGX """
        extra = ''
        tam = len(text) % len(key)
        if tam:
            extra = key[:tam]
        fix = len(text) // len(key)
        okey = sorted(key)
        ptxt = {}
        idx = 0
        ext = 0
        for ch in okey:
            if ch in extra:
                ext = 1
            else:
                ext = 0
            ptxt[ch] = text[idx:idx + fix + ext]
            idx += fix + ext
        adfgx = ''
        for i in range(len(ptxt[key[0]])):
            for ch in key:
                if i < len(ptxt[ch]):
                    adfgx += ptxt[ch][i]
        plain = ''
        for _ in range(0, len(adfgx), 2):
            plain += self.get_letter(adfgx[_:_+2])
        return plain

TESTE

from ciphers import ADFGX

cifra = ADFGX()
cifra.create_square('ZCBDMHAOINLRSPQWXEUTYFGKV')
cifrado = cifra.encrypt('guerra mundial', 'chave')
print('Texto cifrado: ' + cifrado)
print('Texto decfrado: ' + cifra.decrypt(cifrado, 'chave'))

Resultado:

Texto cifrado: GDAXDXFDGDAGDGGFFFDDGGFXAD
Texto decfrado: GUERRAMUNDIAL

Fontes:
https://en.wikipedia.org/wiki/ADFGVX_cipher
http://practicalcryptography.com/ciphers/adfgx-cipher/
http://crypto.interactive-maths.com/adfgvx-cipher.html

Anúncios

Sobre Fábio Medeiros

Meu nome é Fábio Medeiros. Cearense de nascença e com muito orgulho (daí o nome do blog, uma referência à minha terra). Sou formado em Tecnologia em Telemática, pelo CEFET-CE. Escrevi alguns artigos sobre programação JavaME e dispositivos portáteis (PDA) para a revista WebMobile.
Esse post foi publicado em Criptografia e marcado , . Guardar link permanente.

Deixe um comentário

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s