Glossário Kindle para o livro Assassin’s Creed: Odyssey

Já li alguns dos livros da série Assassin’s Creed. Peguei este no Kindle Unlimited para ler e vi que ele contém um glossário logo no início do livro.

Gosto de ter um glossário separado para usar no Kindle, assim fiz um para este livro também.

Para baixar clique aqui.

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

Nestle 1904 Greek New Testament (versão Kindle para iOS)

O Kindle para iOS, possui um formato específico de seus ebooks que mantém a fonte grega que utilizo para editar os Novos Testamentos em grego. A extensão deste formato é .azk

Assim, resolvi disponibilizar, para download, este formato específico para dispositivos iOS.

O arquivo está disponível na página de Livros Digitais.

Para utilizar este formato, deve-se copiar o arquivo para o iPhone/iPad via iTunes.

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

Glossário Kindle para os livros das Crônicas de Duna

Se você já leu, está lendo ou pretende ler os livros das Crônicas de Duna, escritos por Frank Herbert, vai perceber um mundo próprio criado pelo autor, com muitos termos e conceitos criados para a saga.

Assim, resolvi adaptar os glossários do livros para um dicionário para Kindle, para facilitar a leitura, sem precisar recorrer ao fim do livro para ver o significado dos termos.

Até o momento, este dicionário cobre somente o primeiro livro da saga, Duna.

Para baixar clique aqui.

Publicado em Dicionarios | Marcado com , , | 1 Comentário

Dicas de Python: removendo caracteres repetidos em uma string

Quando eu queria remover caracteres repetidos de uma string, geralmente utilizava uma construção em loop, parecida com a abaixo:

def remove_repeated(key):
  alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  out = key.upper()
  for letter in alphabet:
    if not letter in key.upper():
      out += letter
  return out

Seu uso:

print(remove_repeated('chave'))
CHAVEBDFGIJKLMNOPQRSTUWXYZ

É um código funcional, mas que pode ser melhorado:

def remove_repeated(key):
  alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
  return "".join(list(dict.fromkeys(key.upper() + alphabet)))

print(remove_repeated('chave'))
CHAVEBDFGIJKLMNOPQRSTUWXYZ

Explicando rapidamente:

dict.fromkeys(key.upper() + alphabet)

Retorna um dicionário com as letras como chaves,

list(dict.fromkeys(key.upper() + alphabet))

Transforma o dicionário em uma lista,

"".join(list(dict.fromkeys(key.upper() + alphabet)))

Une os itens do dicionário numa string.

Fontes:
https://www.w3schools.com/python/python_howto_remove_duplicates.asp
https://appdividend.com/2019/04/11/how-to-remove-duplicate-items-from-a-python-list/

Publicado em python | Deixe um comentário

Cifra Trifid em Python

Em 1902, Félix-Marie Delastelle desenvolveu uma nova cifra baseada em sua cifra Bifid, a Trifid. Diferente da Bifid, que usa um quadrado de 5×5, na Trifid são utilizados três quadrados de 3×3 cada.

Utiliza-se o alfabeto completo mais um caracter a escolher (em nosso caso adotamos o sinal positivo (+)), assim, ABCDEFGHIJKLMNOPQRSTUVWXYZ+.

Para não facilitar as coisas, vamos embaralhar o alfabeto acima: ZRBIX+EFAUMDHTWJKYCVSLONPQG.

Preenchemos os três quadrados com os caracteres do alfabeto cifrado:

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

O princípio de cifragem é similar ao da cifra Bifid. Tomemos, por exemplo, a letra F. Ela está posicionada no QUAD 1, linha 3 e coluna 2, assim, 132 será seu número. Faremos isto para cada letra do texto plano.

Vamos exemplificar com a frase ‘o trem parte às dez’. Desconsiderando-se os espaços e acentos, para cifrar temos:

texto plano - otremparteasdez
quadrado - 3 linha - 2 coluna - 2

Fazendo isto para cada letra obtemos:

texto plano - otremparteasdez
quadrado - 321123112113211 linha - 221313312331131 coluna - 222121322133311

Agora, lemos os números, primeiro dos quadrados, depois das linhas e, por último, das colunas:

321123112113211221313312331131222121322133311

agora separamos de três em três:

321 123 112 113 211 221 313 312 331 131 222 121 322 133 311

Para cada trio de números, procuramos a letra correspondente no quadrado (onde o primeiro número corresponde ao quadrado, o segundo à linha e o terceiro à coluna):

321 123 112 113 211 221 313 312 331 131 222 121 322 133 311
L + R B U H S V P E T I O A C

Assim, o texto inicial cifrado fica: L+RBUHSVPETIOAC

Pode-se usar uma palavra como chave para gerar o alfabeto. Por exemplo, se utilizarmos a palavra chave, geramos um alfabeto assim: CHAVEBDFGIJKLMNOPQRSTUWXYZ+

O mesmo texto plano, cifrado com o novo alfabeto cifrado fica: QEGAARNCIXDMTPE

CÓDIGO

O código faz uso da classe Cipher (que pode ser salva em um arquivo cipher.py) e foi criada a classe Trifid (que pode ser salva no arquivo trifid.py).

cipher.py

# -*- coding: utf-8 -*-
from random import shuffle
""" Classe com metodos basicos para cifras classicas """

class Cipher(object):
    """ Classe base para as cifras classicas """
    plain_alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    plain_alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

    def format_str(self, text):
        '''Retorna text sem espacos e em maiusculas'''
        return text.replace(' ', '').upper()

    def shift_alphabet(self, alphabet, shift):
        '''Retorna alphabet com deslocamento de valor shift'''
        return alphabet[shift:] + alphabet[:shift]

    def create_square(self, alphabet = [], key = '', alphanum = False, replace = ['J', 'I'], sequence = False):
        """ Retorna um alfabeto numa matriz de num x num
        Por padrao, retorna uma matriz formada pelo alfabeto ABCDEFGHIKLMNOPQRSTUVWXYZ
        Se key, retorna um square com key iniciando o square
        alphanum square com letras e numeros
        replace letras a serem trocadas, so funciona se for usado somente o alfabeto
        sequence se True continua a preencher o square a partir do ultimo caracter da key
        """
        square = []
        if alphabet:
            if alphanum:
                replace = ['', '']
            # num = 5
            alfabeto = alphabet
        elif alphanum:
            # num = 6
            alfabeto = self.plain_alphanum
            replace = ['', '']
        else:
            # num = 5
            alfabeto = self.plain_alphabet
        alfabeto = self.create_alphabet(key.upper(), alfabeto, replace, sequence)##
        num = 5 + len(alfabeto) % 5
        for idx in range(0, len(alfabeto), num):
            square.append(alfabeto[idx:idx + num])
        return square

    def create_alphabet(self, key = '', alfabeto = plain_alphabet, replace = ['', ''], sequence = False):
        """ Retorna um alfabeto com key como chave e no inicio do alfabeto """
        if key:
            key = self.key_repeated(key)
            if replace[0] in key:
                key = key.replace(replace[0], replace[1])
            if sequence:
                idx = alfabeto.index(key[-1])
                alfabeto = self.shift_alphabet(alfabeto, idx)
        cipher = alfabeto.replace(replace[0], '')
        for ch_key in key:
            if ch_key in cipher:
                cipher = cipher.replace(ch_key, '')
        return key + cipher

    def random_alphabet(self, alphanum=False):
        """ Retorna um alfabeto aleatório """
        if alphanum:
            alfabeto = list(self.create_alphabet(alfabeto=self.plain_alphanum))
        else:
            alfabeto = list(self.create_alphabet())
        shuffle(alfabeto)
        return ''.join(alfabeto)

    def key_repeated(self, key):
        ''' Remove caracteres repetidos da senha key '''
        temp = ''
        for ch in key.upper():
            if ch not in temp:
                temp += ch
        return temp

trifid.py

# -*- coding: utf-8 -*-
from cipher import Cipher

class Trifid(Cipher):
    def create_alphabet(self, key=''):
        alphabet = super().create_alphabet(key) + '+'
        return alphabet
        
    def _create_squares(self, alphabet):
        square_lines = []
        for i in range(0, 9):
            square_lines.append(alphabet[0 + 3 * i:3 + 3 * i])

        squares = {
            "1": square_lines[0:3],
            "2": square_lines[3:6],
            "3": square_lines[6:9]
        }
        return squares
    
    def encrypt(self, plaintext, alphabet=''):
        quads = ''
        lines = ''
        cols = ''
        ciphertext = ''
        plaintext = plaintext.upper()
        if alphabet:
            square = self._create_squares(alphabet)
        else:
            square = self._create_squares(self.create_alphabet())
        print(square)
        ### busca letra dentro do tres quadrados
        for letra in plaintext:
            for quad in square.keys():
                for line in square[quad]:
                    if letra in line:
                        quads += quad
                        lines += str(square[quad].index(line) + 1)
                        cols += str(line.index(letra) + 1)
        cipher_num = quads + lines + cols
        # varre cipher_num e usa cada tres numeros para varrer os tres quadrados
        for i in range(0, len(cipher_num), 3):
            idx = cipher_num[i:i + 3]
            quad = idx[0]
            line = int(idx[1]) - 1
            col = int(idx[2]) - 1
            ciphertext += square[quad][line][col]
        return ciphertext

    def decrypt(self, ciphertext, alphabet=''):
        text = ciphertext.upper()
        cipher_num = ''
        if alphabet:
            square = self._create_squares(alphabet)
        else:
            square = self._create_squares(self.create_alphabet())
        ### busca letra dentro do tres quadrados
        for letra in text:
            for quad in square.keys():
                for line in square[quad]:
                    if letra in line:
                        lines = str(square[quad].index(line) + 1)
                        cols = str(line.index(letra) + 1)
                        cipher_num += quad + lines + cols
        squares = []
        for i in range(0, len(cipher_num), len(text)):
            squares.append(cipher_num[i:i + len(text)])
        plaintext = ''
        for col in range(0, len(text)):
            item = ''
            for lin in range(0, 3):
                item += squares[lin][col]
            plaintext += square[item[0]][int(item[1]) - 1][int(item[2]) - 1]
        return plaintext

TESTE

>>> cifra = Trifid()
>>> alfabeto = 'ZRBIX+EFAUMDHTWJKYCVSLONPQG'
>>> cifrado = cifra.encrypt('otremparteasdez', alfabeto)
>>> print(cifrado)
L+RBUHSVPETIOAC
>>> print(cifra.decrypt(cifrado, alfabeto))
OTREMPARTEASDEZ
>>> alfabeto = cifra.create_alphabet('senha')
>>> cifrado = cifra.encrypt('otremparteasdez', alfabeto)
>>> print(cifrado)
QAFSNRBGHUHPIKL
>>> print(cifra.decrypt(cifrado, alfabeto))
OTREMPARTEASDEZ

FONTES
https://en.wikipedia.org/wiki/Trifid_cipher
http://practicalcryptography.com/ciphers/trifid-cipher/
https://www.dcode.fr/triliteral-cipher

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

Cifra Bifid em Python

Em 1901, o criptógrafo francês, Félix-Marie Delastelle, em seu livro Traité Élémentaire de Cryptographie, descreveu uma cifra criptográfica que mistura o quadrado de Políbio com transposição de colunas. Esta recebeu o nome de Bifid.

Seu princípio de funcionamento começa com um quadrado de Políbio de 5×5 (o J é substituído pelo I). Utilizando-se o alfabeto PLNCYZSMUETBXWVQOAJDKRGFHI temos a tabela abaixo:

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

Vamos exemplificar com a frase ‘o trem parte às dez’. Desconsiderando-se os espaços e acentos, para cifrar procedemos assim: pegamos a linha e a coluna da letra e escrevemos o número abaixo da letra.

texto plano - otremparteasdez
linha       - 4
coluna      - 2

Fazendo isto para cada letra obtemos:

texto plano - otremparteasdez
linha       - 435221453242422
coluna      - 211531311532451

Agora, lemos os números, primeiro das linhas, depois das colunas:

435221453242422211531311532451

agora separamos de dois em dois:

43 52 21 45 32 42 42 22 11 53 13 11 53 24 51

Para cada par de número, procuramos a letra correspondente no quadrado (onde o primeiro número do par corresponde à linha e o segundo, à coluna):

43 52 21 45 32 42 42 22 11 53 13 11 53 24 51
A  G  Z  K  B  O  O  S  P  F  N  P  F  U  R

Assim, o texto inicial cifrado fica: AGZKBOOSPFNPFUR

CÓDIGO

O código faz uso da classe Cipher (que pode ser salva em um arquivo cipher.py) e foi criada a classe Bifid (que pode ser salva no arquivo bifid.py).

cipher.py

# -*- coding: utf-8 -*-
from random import shuffle
""" Classe com metodos basicos para cifras classicas """

class Cipher(object):
    """ Classe base para as cifras classicas """
    plain_alphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
    plain_alphanum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'

    def format_str(self, text):
        '''Retorna text sem espacos e em maiusculas'''
        return text.replace(' ', '').upper()

    def shift_alphabet(self, alphabet, shift):
        '''Retorna alphabet com deslocamento de valor shift'''
        return alphabet[shift:] + alphabet[:shift]

    def create_square(self, alphabet = [], key = '', alphanum = False, replace = ['J', 'I'], sequence = False):
        """ Retorna um alfabeto numa matriz de num x num
        Por padrao, retorna uma matriz formada pelo alfabeto ABCDEFGHIKLMNOPQRSTUVWXYZ
        Se key, retorna um square com key iniciando o square
        alphanum square com letras e numeros
        replace letras a serem trocadas, so funciona se for usado somente o alfabeto
        sequence se True continua a preencher o square a partir do ultimo caracter da key
        """
        square = []
        if alphabet:
            if alphanum:
                replace = ['', '']
            # num = 5
            alfabeto = alphabet
        elif alphanum:
            # num = 6
            alfabeto = self.plain_alphanum
            replace = ['', '']
        else:
            # num = 5
            alfabeto = self.plain_alphabet
        alfabeto = self.create_alphabet(key.upper(), alfabeto, replace, sequence)##
        num = 5 + len(alfabeto) % 5
        for idx in range(0, len(alfabeto), num):
            square.append(alfabeto[idx:idx + num])
        return square

    def create_alphabet(self, key = '', alfabeto = plain_alphabet, replace = ['', ''], sequence = False):
        """ Retorna um alfabeto com key como chave e no inicio do alfabeto """
        if key:
            key = key_repeated(key)
            if replace[0] in key:
                key = key.replace(replace[0], replace[1])
            if sequence:
                idx = alfabeto.index(key[-1])
                alfabeto = self.shift_alphabet(alfabeto, idx)
        cipher = alfabeto.replace(replace[0], '')
        for ch_key in key:
            if ch_key in cipher:
                cipher = cipher.replace(ch_key, '')
        return key + cipher

    def random_alphabet(self, alphanum=False):
        """ Retorna um alfabeto aleatório """
        if alphanum:
            alfabeto = list(self.create_alphabet(alfabeto=self.plain_alphanum))
        else:
            alfabeto = list(self.create_alphabet())
        shuffle(alfabeto)
        return ''.join(alfabeto)

    def key_repeated(self, key):
        ''' Remove caracteres repetidos da senha key '''
        temp = ''
        for ch in key.upper():
            if ch not in temp:
                temp += ch
        return temp

bifid.py

# -*- coding: utf-8 -*-
from cipher import Cipher

class Bifid(Cipher):
    def encrypt(self, plaintext, alphabet=None):
        lins = ''
        cols = ''
        plaintext = plaintext.upper()
        matriz = self.create_square(alphabet)
        for letra in plaintext:
            for lin in matriz:
                if letra in lin:
                    cols += str(lin.find(letra) + 1)
                    lins += str(matriz.index(lin) + 1)
        cipher_num = lins + cols
        ciphertext = ''
        for i in range(0, len(cipher_num), 2):
            ref = cipher_num[i:i + 2]
            ciphertext += matriz[int(ref[0]) - 1][int(ref[1]) - 1]
        return ciphertext

    def decrypt(self, texto, alphabet=None):
        num = ''
        plain = ''
        texto = texto.upper()
        matriz = self.create_square(alphabet)
        for letra in texto:
            for linha in matriz:
                if letra in linha:
                    num += str(matriz.index(linha) + 1) + str(linha.find(letra) + 1)
        linhas = num[:len(num)//2]
        colunas = num[len(num)//2:]
        for i in range(0, len(linhas)):
            plain += matriz[int(linhas[i]) - 1][int(colunas[i]) - 1]
        return plain

TESTE

>>> bifid = Bifid()
>>> cifrado = bifid.encrypt('OTREMPARTEASDEZ', 'PLNCYZSMUETBXWVQOAJDKRGFHI')
>>> print(cifrado)
>>> print(bifid.decrypt(cifrado, 'PLNCYZSMUETBXWVQOAJDKRGFHI'))

Resultado:

AGZKBOOSPFNPFUR
OTREMPARTEASDEZ

FONTES
https://en.wikipedia.org/wiki/Bifid_cipher
http://practicalcryptography.com/ciphers/bifid-cipher/
http://rumkin.com/tools/cipher/bifid.php
https://www.dcode.fr/bifid-cipher

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