from cipher import Cipher
class Playfair(Cipher):
def encrypt(self, text, key = '', decrypt = False):
"""Retorna text cifrado com a cifra de Playfair.
key - chave a ser usada; havendo chave, o alfabeto sera iniciado com ela
decrypt - se True, decifra; se False, cifra
"""
ciphertext = ''
text = text.upper()
text = text.replace('J', 'I').replace(' ', '')
# checa se o texto contem par de letras iguais
text = self.check_double(text)
# se text nao tiver numero par de letras
if len(text) % 2:
text += 'W'
# cria a tabela
self.square = self.create_square(key)
for i in range(0, len(text), 2):
ciphertext += self.change_pair(text[i:i + 2], decrypt)
return ciphertext.upper()
def decrypt(self, ciphertext, key = ''):
"""Retorna o ciphertext decifrado com a cifra de Playfair"""
return self.encrypt(ciphertext.upper(), key, True).lower()
def check_double(self, text):
out = ''
for idx in range(0, len(text), 2):
pair = text[idx:idx+2]
if len(pair) > 1 and pair[0] == pair[1]:
out += pair[0] + 'W' + pair[1]
else:
out += pair
return out
def change_pair(self, pair, decrypt = False):
"""Retorna as posicoes de um par de letras de uma matriz 5x5."""
# retorno - valor a ser retornado quando se atinge o limite da tabela
# limite - valor de limite das celulas da tabela
# passo - valor de incremento/decremento
if decrypt:
retorno = 4
limite = -1
passo = -1
else:
retorno = 0
limite = 5
passo = 1
coord1, coord2 = self.coords(pair)
if coord1[0] == coord2[0]:
# caso em que as duas letras estao na mesma linha
coord1[1] += passo
coord2[1] += passo
elif coord1[1] == coord2[1]:
# caso em que as duas letras estao na mesma coluna
coord1[0] += passo
coord2[0] += passo
else:
# caso em que as duas letras nao estao na mesma linha nem mesma coluna
coord1[1], coord2[1] = coord2[1], coord1[1]
coord1 = [retorno if x == limite else x for x in coord1]
coord2 = [retorno if x == limite else x for x in coord2]
return self.letter(coord1) + self.letter(coord2)
def coords(self, pair):
"""Retorna as coordenadas de um par de letras numa matriz."""
coords = []
for letter in pair:
for line in range(len(self.square)):
if letter in self.square[line]:
coords.append([line, self.square[line].index(letter)])
break
return coords
def letter(self, coord):
"""Retorna a letra com a coordenada dada"""
return self.square[coord[0]][coord[1]]