Bíblia ACF 2007 com subtítulos (ePub, mobi)

Atendendo ao pedido do LoiltonJC, consegui converter para ePub e mobi a Bíblia ACF 2007 com subtítulos entre os versículos. Os subtítulos servem como pequenos resumos do que será tratado nos versículos que o seguem.

Para exemplificar, observe a imagem abaixo. A imagem da esquerda é a versão da Bíblia sem os subtítulos e a da direita com eles.

telas

Como de costume, o download está disponível no box.com ou pela página de livros digitais. Os arquivos com esta opção são ACF2007-sub.epub e ACF2007-sub.mobi.

 

Publicado em Bíblia | Marcado com , , | 1 Comentário

Criptografia: Cifra Playfair em Python

A cifra Playfair, também conhecida como quadrado de Playfair, foi uma cifra inventada por Charles Wheastone em 1854, mas que recebeu seu nome por causa de Lyon Playfair ou Lorde Playfair, que conseguiu que fosse utilizada pelo governo britânico. É uma cifra de substituição e cuja técnica principal consiste no uso de digramas ou bigramas (um par de letras) no processo de cifragem/decifragem.

Seu princípio de funcionamento usa uma tabela 5×5 preenchida com as 26 letras do alfabeto latino (como a tabela é um quadrado de 5×5, resultando em 25 células, optamos por unir as letras i e j numa mesma célula, onde todo j na mensagem a ser cifrada será substituído por i) e uma palavra-chave ou senha.

Usando como senha a palavra ESPIAO, preenchemos a tabela como mostrado abaixo:

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

A primeira etapa da cifragem consiste na divisão da mensagem em digramas (pares de letras). Assim, a frase temos um agente infiltrado, ficará assim:

te mo su ma ge nt ei nf il tr ad ow

Quando dividimos a frase em digramas, vemos que a última letra da frase ficou sozinha. Assim, adicionamos uma letra (adotarei o w) a ela para formar o par.

A segunda etapa é pegarmos cada par de letras e as localizarmos na tabela.

Há três regras para cifrar um par de letras.

1) se as letras estão na mesma linha, cada letra é trocada pela letra da coluna da direita; caso a letra esteja no final da linha troca-se pela primeira letra da mesma linha. Exemplo, o par nt (n linha 4 e coluna 1, t linha 4 e coluna 4 – em vermelho) é trocado por QU (Q linha 4 e coluna 2, U linha 4 e coluna 5 – em verde);

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

2) se as letras estão na mesma coluna, cada letra é trocada pela letra da linha logo abaixo; caso a letra esteja no final da coluna, troca-se a letra pela letra do início da mesma coluna. Exemplo, o par il (i L1 C4, l L3 C4) é trocado por DT (D L2 C4, T L4 C4);

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

3) já, se as letras estiverem em linhas e colunas diferentes, a troca se dará assim: a primeira letra será trocada pela letra que estiver na mesma linha da primeira letra e na coluna da segunda letra; a segunda letra será trocada pela letra que estiver na mesma linha da segunda letra e na coluna da primeira letra. Exemplo, o par ow (o L2 C1, w L5 C2) é trocado por BV (B L2 C2, V L5 C1).

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

Assim, nossa mensagem cifrada ficará assim:

NIGFAQUFNOQUSAUODTUTIFBV

Vale uma observação. Pode ocorrer o caso quando dividimos a frase em digramas, de um ou mais digramas ficarem com letras iguais. Neste caso, o digrama será separado e acrescentada uma letra entre eles (no meu caso, resolvi adicionar a letra w).

Por exemplo, a frase nossa esperança é a sua vinda, os digramas ficariam assim:

no ss ae sp er an ca ea su av in da

Como há o digrama ss, acrescentamos o w entre eles e nossa frase ficará assim:

no sw sa es pe ra nc ae as ua vi nd aw

E o texto cifrado:

NIGFAQUFNOQUSAUODTUTIFBV

CÓDIGO

O código foi salvo no arquivo playfair.py e precisa do arquivo cipher.py (que está abaixo e é utilizada em alguns outras cifras publicadas no blog).

# -*- coding: utf-8 -*-
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]]

cipher.py

# -*- coding: utf-8 -*-
""" 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, 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
        """
        square = []
        if alphanum:
            num = 6
            alfabeto = self.plain_alphanum
            replace = ['', '']
        else:
            num = 5
            alfabeto = self.plain_alphabet
        alfabeto = self.create_alphabet(key, alfabeto, replace, sequence)
        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.upper()
            temp = ''
            for ch in key:
                if ch not in temp:
                    temp += ch
            key = temp
            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

Estas cifras, bem como todas as outras estão disponíveis em meu GitHub.

TESTES

from playfair import Playfair

versao = sys.version_info[0]
 
if versao == 2:
    leitura = raw_input
elif versao == 3:
    leitura = input

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

cifra = Playfair()
cifrado = cifra.encrypt(txt_in, password)
print(cifrado)
print(cifra.decrypt(cifrado, password))

Cujo resultado de saída será:

Texto a ser cifrado: temos um agente infiltrado
Senha: espiao
NIGFAQUFNOQUSAUODTUTIFBV
temosumagenteinfiltradow
Fontes:
http://www.numaboa.com.br/criptografia/substituicoes/poligramicas/1041-playfair
https://en.wikipedia.org/wiki/Playfair_cipher
http://practicalcryptography.com/ciphers/playfair-cipher/
https://learncryptography.com/classical-encryption/playfair-cipher
http://crypto.interactive-maths.com/playfair-cipher.html
Publicado em Criptografia | Marcado com , | 2 Comentários

Como exportar as notas de documentos pessoais no Kindle para iPad

Então, você está lendo aquele documento pessoal no Kindle para iPad e fez várias anotações nele. Agora, por um motivo qualquer você quer exportar estas notas. Mas como fazer?

No Kindle para iPad há uma opção que permite exportar estas notas enviado-as por email. Para fazer basta proceder assim.

Com o livro aberto (para este exemplo vamos utilizar a Bíblia ACF 2007, disponível aqui),

image00

clique no ícone de anotações (canto superior direito).

image01

Ao abrir a tela do Meu caderno de anotações, clique no ícone de exportar (canto superior direito),

image02

selecione E-mail.

image03

Escolha um estilo (eu optei por Nenhum) e clique em Exportar.

image04

Digite o endereço de email para o qual quer enviar o arquivo exportado em formato HTML e clique em Enviar.

image05

Abaixo, como fica o HTML do arquivo exportado.

nota

Publicado em Soluções | Marcado com , | Deixe um comentário

Instalando/atualizando a lxml no Windows 8.1 para Python 2.7

Hoje, ao tentar atualizar a biblioteca lxml pelo pip, obtive um erro de compilação e não consegui atualizar.

Pesquisando, descobri que podia instalar/atualizar a lxml para a versão mais atual utilizando um arquivo no formato wheel (.whl) disponibilizado em um repositório nã0-oficial de pacotes de extensão Python para Windows.

No repositório, baixei a versão lxml-3.5.0-cp27-none-win32.whl (versão 3.5 para Python 2.7). No diretório onde baixei o arquivo executei o comando pip install lxml-3.5.0-cp27-none-win32.whl. E pronto, problema resolvido🙂

Publicado em Soluções | Marcado com , | Deixe um comentário

Reduzindo o tamanho de um arquivo PDF com Ghostscript

Dia destes, no trabalho, me solicitaram a redução ou divisão de um arquivo PDF para o tamanho máximo de 10 MB.

Como já utilizei o Ghostscript para desbloquear arquivos PDF, procurei uma solução em que pudesse utilizá-lo.

É possível, utilizando-se o comando abaixo (que deve ser digitado em uma linha só):

gswin64 -dNOPAUSE -dBATCH -sDEVICE=pdfwrite
-dCompatibilityLevel=1.4 -dPDFSETTINGS=/screen
-sOutputFile=PDF_REDUZIDO.pdf PDF_ORIGINAL.pdf

onde:
gswin64 – comando do Ghostscript no Windows 64 bits;
-dNOPAUSE – desabilita o prompt ao final de cada página processada;
-dBATCH – habilita o processamento em lote;
-sDEVICE=pdfwrite – determina o dispositivo de saída; o pdfwrite é para a geração do PDF;
-dCompatibilityLevel=1.4 – determina o nível de compatibilidade; aqui foi usado o nívl 1.4, compatível com o Adobe Reader 5 ou superior;
-dPDFSETTINGS=/screen – qualidade do PDF gerado (aqui fica com a qualidade de imagem de 72 dpi, para visualização em tela)
-sOutputFile=PDF_REDUZIDO.pdf – especifica o nome do arquivo a ser gerado
PDF_ORIGINAL.pdf – nome do PDF original que se deseja reduzir

Em meu caso, o arquivo original que tinha 21,1 MB ficou com 9,60 MB após a redução.

Fontes:
http://www.vivaolinux.com.br/dica/GhostScript-Reduzindo-o-tamanho-de-arquivos-PDF-pelo-terminal
http://milan.kupcevic.net/ghostscript-ps-pdf/
http://www.peteryu.ca/tutorials/publishing/pdf_manipulation_tips

Publicado em Soluções | Marcado com , | Deixe um comentário

Código Morse em Python

Recentemente, em seu twitter, o escritor Eduardo Spohr escreveu duas mensagens em código Morse. O que me levou a escrever uma classe em Python que codificasse e decodificasse este código.

O código Morse é um sistema binário desenvolvido em 1835 por Samuel Finley Breese Morse para representar as letras do alfabeto bem como os numerais. Utiliza sons curtos e longos ou pontos e traços para transmissão de mensagens.

Código Morse Internacional

CÓDIGO

O código em Python foi implementado conforme a tabela acima. O código morse para ser decodificado deve ter espaços em brancos para separar cada código. Código salvo no arquivo morse.py.

class Morse(object):
    def __init__(self):
        self.morse_code = {
            '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': '--..',
            '0': '-----', '1': '.----',
            '2': '..---', '3': '...--',
            '4': '....-', '5': '.....',
            '6': '-....', '7': '--...',
            '8': '---..', '9': '----.'
        }

    def decode(self, morsecode):
        ''' Decodifica codigo morse '''
        code = morsecode.split(' ')
        text = ''
        for item in code:
            for key, value in self.morse_code.iteritems():
                if item == value:
                    text += key
                    break
        return text

    def encode(self, plaintext):
        ''' Codifica em codigo morse '''
        code = ''
        for char in plaintext.upper():
            if char in self.morse_code.keys():
                code += self.morse_code[char] + ' '
        return code

TESTE

Com o módulo abaixo podemos testar a classe Morse.

# -*- coding: utf-8 -*-
from morse import Morse
import sys

versao = sys.version_info[0]

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

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

morse = Morse()
codigo = morse.encode(txt_in)
print
print('Codigo Morse: {0}'.format(codigo))
print(' Texto plano: {0}'.format(morse.decode(codigo)))

Executando, temos como saída:

Texto a ser codificado: a reuniao sera as 10h

Codigo Morse: .- .-. . ..- -. .. .- --- ... . .-. .- .- ... .---- ----- ....
 Texto plano: AREUNIAOSERAAS10H

Fontes:
https://en.wikipedia.org/wiki/Morse_code

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

Cifras criptográficas em repositório no GitHub

Bom, depois de tanto tempo ausente, resolvi postar algo útil🙂

Meus últimos posts foram de cifras criptográficas implementadas na linguagem Python. Para facilitar, resolvi disponibilizar os códigos-fontes num repositório no GitHub: https://github.com/fabmedeiros.

Assim, todas as cifras que eu for implementando serão disponibilizadas aqui no blog e lá.

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