Criptografia avançada
Importante: Esta página não se encontra completa, por favor ajude a melhorá-la Na própria documentação do Python (seja qual for a versão que você tem), há um exemplo super básico de como usar as bibliotecas embutidas de criptografia.
Mecanismos de criptografias permitem a transformação reversível da informação de forma a torná-la ininteligível a terceiros. Utiliza-se para tal, algoritmos determinados e uma chave secreta para, a partir de um conjunto de dados não cifrados, produzir uma sequência de dados cifrados. A operação inversa é a decifração.
IMPORTATE SABER: Os módulos nativos do Python não são usados para criptografia propriamente dita, ou seja, são usados somente para hashing (checagem) como o md5, sha e hashlib. Para cifrar dados, terá que usar libs de criptografia simétrica, ou seja, que faz uso de chave (publica ou privada), mas isto não é problema, pois na web você encontrará uma infinidade de ferramentas, tanto para Python, quanto para qualquer outra linguagem de programação.
Estes modulos abaixo são nativos do Python: hashlib - Secure hash and message digest algorithms. hmac - Keyed-Hashing for Message Authentication (HMAC) implementation for Python. md5 - RSA's MD5 message digest algorithm. sha - NIST's secure hash algorithm, SHA.
Mais abaixo, darei exemplos avançados que encontrei na web, mas para começar, darei uma explicação básica. Não pretendo narrar toda historia da criptografia na humanidade, mas resumindo, a criptografia, em geral, é a forma de codificar uma mensagem, ou algum dado qualquer, de forma que somente seja "humanamente" compreendida por uma pessoa que saiba descodificar esta mesma mensagem. Em tempos passados, quando povos entravam em guerra, e quando queriam se comunicar entre si de forma que outras pessoas, ou outros povos não soubesse, se usavam todo tipo de artimanha.
Pombos correios; Sinal de Fumaça; Gravuras em pedras; Desenhos nas árvores, Pintando o corpo, e até gestos com as mãos.
Em era passadas, os índios de guerra usavam o famoso sinal de fumaça para se comunicarem, e assim, saberem aonde atacar, em que momento atacar e a quem atacar, ou qualquer outra coisa que nenhum outro povo deveria saber.
O espião infiltrado em território inimigo, usava o código morse para se comunicar com a base dele. Na minha opinião, sempre foi um fetiche do homem querer guardar segredo, e para isto, com a ajuda da Matemática, foi se desenvolvendo vários métodos de cifrar algum texto, varias formas de "embaralhar" algum dados, vários algoritmos de manter um determinado dado, ilegível a certas pessoas.
Com a chegada da "era digital", e o aumento de Computadores ligados em redes, o uso da criptografia foi se tornando mais comum e indispensável na "troca de informações", por isto, foram criados várias formas de cifrar. Sempre um algoritmo mais complexo que o outro, alguns algoritmos que conheço são:
Criptografia de Cesar; Criptografia Blowfish; AES;
Outros que servem tanto para construção de cifragem quanto para hashing são:
ARC2; ARC4; CAST; DES; DES3; IDEA; RC5; XOR; RSA; base64; etc.
Vamos começar com a cifragem em md5:
import md5
m = md5.new()
m.update("Nobody inspects")
m.update(" the spammish repetition")
m.digest()
'xbbdx9cx83xddx1exa5xc9xd9xdexc9xa1x8dxf0xffxe9'
Viu o output? Agora vamos usar a base64, exemplo com base64:
import base64
encoded = base64.b64encode('data to be encoded')
>>> encoded
'ZGF0YSB0byBiZSBlbmNvZGVk'
data = base64.b64decode(encoded)
>>> data
'data to be encoded'
Viu agora a diferença no output?, que tal misturamos?
# Gerador de MD5
import md5, binascii
nome = '?'
while nome:
m = md5.new()
nome = raw_input('Digite seu nome (ou nada para encerrar):')
if nome:
m.update(nome)
senha = raw_input('Digite sua senha:')
m.update(senha)
print 'MD5: ', binascii.b2a_base64(m.digest())
Digite um nome e uma senha e terá um hash md5 cifrado em base64 de output. Neste caso, usou-se base64 como construtor, mas poderá ser usado outros construtores (Base16, Base32, Base64).
Simples, não?
Um simples exemplo didáctico de criptografia simétrica da web que usa o algoritmo de César:
# criptografia.py
# -*- coding: iso-8859-1 -*-
#
# Exemplo de um algoritmo de criptografia com chave
# usando o algoritmo criptográfico de Cesar
#
# /! Este algoritmo é extremamente fraco e serve
# apenas para demonstração
maintable = [
" 0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.;/áéíóúÁÉÍÓÚàÀãõÃÕüÜ",
"mübõaÚfSÀy,NtvKcJ0ouICHB nT2kzóÕD;Lw/3rlZÉRÃ4ãP6éjiÜAGÍYM8OX5àÓWsVqFUxEpÁQ7hgúá1í9.de",
".UPeZO/hIxJlzgcáCÀL5õsvE7au1fóÍ,Q8úq9DéãHGXr3jàR ;oyüdíNMÁwiTÜ24tm6nBÕSÓWKÉb0YÃFVAkpÚ",
"fuNDEbmlJ2RÀãovCUGta8AÓ,áXúFYÕWQwh/ rZ1MeSTOPs3yd.IKÜ5BknÃqóíÉ7Íõc4zgÚ9üVjéxHàÁ;0L6ip",
"0É;2vtóQwqaIiKzcBVyG9éãCfsHkmüPFngx/8 WÕeíÜÍDÃULu.ZoMhpbú,NAOÚJ5á7r3ÀSlÓ4T6d1RõàÁjEYX",
"JhYb1OGÁáIKremü78H2Bsgã.õ69P/Qu;AlVWXàzoCf4íDSNZóÜtRkyipÍajÉ ÓqéFMdúLUEn5xTÕ3,0ÃvÚwcÀ",
"ÜãÃHYaQÁi94rGm8ÀxZcàóy2kÚqvU7FouP3VzLXBlgjúÍáIJApWsKtÓCwfdSéíeM0hnbõü1OÕ,T5 ./N6D;ERÉ",
"Zõsd8u1V6aGÀÓÚ/9ÁíÃ2áRH5;X4AvCãWwDüióxÉéjcgJKoyú.eIf7YzhTtUSbBO,mP3pqQÜN0ÍàEkrFlnMLÕ ",
"6;áMua /.ÍcéP2Ysm,ówÁ347í9iJLnpFHK5àeARÜDõúZüÀgQoÓyqkxObÚÉvBlNrXWÕCETIhd8zV10GtSfÃUjã",
"hÉÍ,P7úN;zQõÁocDUàI6rC qOB0ãítMYa8.3pÃyT/2ükdEKxf5éJZÓÜÀRuiH4sASXFó91áwjLGWvlÚngbVÕem",
]
def normalize_key(key):
key = [ ord(k) % 10 for k in key ]
return len(key), key
def crypt(text, key, table):
size, key = normalize_key(key)
text = list(text)
for pos,char in enumerate(text):
subtable = table[key[pos % size]]
new_char_position = table[0].find(char)
if new_char_position < 0:
new_char = char
else:
new_char = subtable[new_char_position]
text[pos] = new_char
return ''.join(text)
def uncrypt(text, key, table):
size, key = normalize_key(key)
text = list(text)
for pos,char in enumerate(text):
subtable = table[key[pos % size]]
new_char_position = subtable.find(char)
if new_char_position < 0:
new_char = char
else:
new_char = table[0][new_char_position]
text[pos] = new_char
return ''.join(text)
def generate_maintable():
import random
print "maintable = ["
x = list("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,.;/áéíóúÁÉÍÓÚàÀãõÃÕüÜ")
for i in range(10):
print ' "%s",' % (''.join(x))
random.shuffle(x)
print "]"
Exemplo de uso do modulo acima:
import criptografia
mensagem = "Vamos invadir a região amanhã às 15hs GMT"
chave = "mitzuplick"
mensagem_cifrada = crypt(mensagem, chave, maintable)
print "Mensagem original: %s" % (mensagem)
print "Mensagem cifrada: %s" % (mensagem_cifrada)
print "Mensagem de retorno: %s" % (uncrypt(mensagem_cifrada, chave, maintable))
Criptografia avançada
Python tem um toolkit chamado PyCrypto, que te fornece os algoritmos mais usados para criptografia. Se você tem uma boa noção de programação, seja em qual linguagem for, e também uma excelente noção em Matemática, poderá criar seu próprio método de cifrar, ou seja, seu próprio algoritmo, mas isto seria inviável, é uma péssima ideia usar um algoritmo criptográfico desconhecido, o mais indicado é usar os já existentes no mercado, pois já foram testados e aperfeiçoados.
Um exemplo da web:
# -*- coding: UTF-8 -*-
# Por Diogo V. Kerting diogovk@gmail.com
# Sob GNU GPL
from optparse import OptionParser
import sys
usage = "usage: %prog [options] [mensagem]"
# Objeto que manipula a linha de comando
parser = OptionParser()
parser.add_option("-o", "--saida", dest="arquivo_saida", help="Imprime em arquivo",metavar="ARQUIVO")
parser.add_option("-e", "--encripta", action="store_true", dest="encriptar",default=False,help="Encriptar mensagem",metavar="ENCRIPTA")
parser.add_option("-d", "--decripta", action="store_true", dest="decriptar",default=False,help="Decriptar mensagem",metavar="DECRIPTA")
parser.add_option("-c", "--chave", action="store", dest="chave",type='int',help="Chave utilizada para encriptar ou decriptar a mensagem",metavar="CHAVE")
(options, args) = parser.parse_args()
if options.encriptar and options.decriptar:
print 'Opções conflitantes -e e -d'
if not options.encriptar and not options.decriptar:
options.encriptar=True
if options.chave == None:
print 'É necessaria uma chave para a ação selecionada.nTente passar uma atraves do parametro -c'
sys.exit(1)
if options.chave > 25 or options.chave < 1:
print 'A chave deve ser de 1 a 25'
print options.chave
sys.exit(1)
if args == ['']:
mensagem=raw_input()
else:
mensagem=''
for string in args:
mensagem+=string+' '
chave=options.chave
mensagem_encriptada=''
if options.encriptar:
for byte in mensagem:
if byte.isalpha():
byte_encriptado=chr(ord(byte)+chave)
if byte.isupper() and ord(byte_encriptado) > 90:
byte_encriptado=chr(ord(byte_encriptado)-26)
if byte.islower() and ord(byte_encriptado) > 122:
byte_encriptado=chr(ord(byte_encriptado)-26)
else:
byte_encriptado=byte
mensagem_encriptada+=byte_encriptado
else:
for byte in mensagem:
if byte.isalpha():
byte_encriptado=chr(ord(byte)-chave)
if byte.isupper() and ord(byte_encriptado) < 65:
byte_encriptado=chr(ord(byte_encriptado)+26)
if byte.islower() and ord(byte_encriptado) < 97:
byte_encriptado=chr(ord(byte_encriptado)+26)
else:
byte_encriptado=byte
mensagem_encriptada+=byte_encriptado
print mensagem_encriptada
Boa? não sei!
Mais exemplos:
Na toolkit PyCrypto tem vários algoritmos para se usar, um deles é o Blowfish. Particularmente, eu uso este, e se você não puder baixar toda toolkit, então tenha a lib blowfish somente:
#
# blowfish.py
# Copyright (C) 2002 Michael Gilfix <mgilfix@eecs.tufts.edu>;
#
# This module is open source; you can redistribute it and/or
# modify it under the terms of the GPL or Artistic License.
# These licenses are available at http://www.opensource.org
#
# This software must be used and distributed in accordance
# with the law. The author claims no liability for its
# misuse.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
"""
Blowfish Encryption
This module is a pure python implementation of Bruce Schneier's
encryption scheme 'Blowfish'. Blowish is a 16-round Feistel Network
cipher and offers substantial speed gains over DES.
The key is a string of length anywhere between 64 and 448 bits, or
equivalently 8 and 56 bytes. The encryption and decryption functions operate
on 64-bit blocks, or 8 byte strings.
Send questions, comments, bugs my way:
Michael Gilfix <mgilfix@eecs.tufts.edu>;
"""
__author__ = "Michael Gilfix <mgilfix@eecs.tufts.edu>"
class Blowfish:
"""Blowfish encryption Scheme
This class implements the encryption and decryption
functionality of the Blowfish cipher.
Public functions:
def __init__ (self, key)
Creates an instance of blowfish using 'key'
as the encryption key. Key is a string of
length ranging from 8 to 56 bytes (64 to 448
bits). Once the instance of the object is
created, the key is no longer necessary.
def encrypt (self, data):
Encrypt an 8 byte (64-bit) block of text
where 'data' is an 8 byte string. Returns an
8-byte encrypted string.
def decrypt (self, data):
Decrypt an 8 byte (64-bit) encrypted block
of text, where 'data' is the 8 byte encrypted
string. Returns an 8-byte string of plaintext.
def cipher (self, xl, xr, direction):
Encrypts a 64-bit block of data where xl is
the upper 32-bits and xr is the lower 32-bits.
'direction' is the direction to apply the
cipher, either ENCRYPT or DECRYPT constants.
returns a tuple of either encrypted or decrypted
data of the left half and right half of the
64-bit block.
Private members:
def __round_func (self, xl)
Performs an obscuring function on the 32-bit
block of data 'xl', which is the left half of
the 64-bit block of data. Returns the 32-bit
result as a long integer.
"""
# Cipher directions
ENCRYPT = 0
DECRYPT = 1
# For the __round_func
modulus = long (2) ** 32
def __init__ (self, key):
if not key or len (key) < 8 or len (key) > 56:
raise RuntimeError, "Attempted to initialize Blowfish cipher with key of invalid length: %s" %len (key)
self.p_boxes = [
0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344,
0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89,
0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C,
0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917,
0x9216D5D9, 0x8979FB1B
]
self.s_boxes = [
[
0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7,
0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99,
0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16,
0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E,
0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE,
0x7B54A41D, 0xC25A59B5, 0x9C30D539, 0x2AF26013,
0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF,
0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E,
0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60,
0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440,
0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE,
0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A,
0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E,
0xAFD6BA33, 0x6C24CF5C, 0x7A325381, 0x28958677,
0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193,
0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032,
0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88,
0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239,
0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E,
0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0,
0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3,
0x6EEF0B6C, 0x137A3BE4, 0xBA3BF050, 0x7EFB2A98,
0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88,
0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE,
0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6,
0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D,
0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B,
0x075372C9, 0x80991B7B, 0x25D479D8, 0xF6E8DEF7,
0xE3FE501A, 0xB6794C3B, 0x976CE0BD, 0x04C006BA,
0xC1A94FB6, 0x409F60C4, 0x5E5C9EC2, 0x196A2463,
0x68FB6FAF, 0x3E6C53B5, 0x1339B2EB, 0x3B52EC6F,
0x6DFC511F, 0x9B30952C, 0xCC814544, 0xAF5EBD09,
0xBEE3D004, 0xDE334AFD, 0x660F2807, 0x192E4BB3,
0xC0CBA857, 0x45C8740F, 0xD20B5F39, 0xB9D3FBDB,
0x5579C0BD, 0x1A60320A, 0xD6A100C6, 0x402C7279,
0x679F25FE, 0xFB1FA3CC, 0x8EA5E9F8, 0xDB3222F8,
0x3C7516DF, 0xFD616B15, 0x2F501EC8, 0xAD0552AB,
0x323DB5FA, 0xFD238760, 0x53317B48, 0x3E00DF82,
0x9E5C57BB, 0xCA6F8CA0, 0x1A87562E, 0xDF1769DB,
0xD542A8F6, 0x287EFFC3, 0xAC6732C6, 0x8C4F5573,
0x695B27B0, 0xBBCA58C8, 0xE1FFA35D, 0xB8F011A0,
0x10FA3D98, 0xFD2183B8, 0x4AFCB56C, 0x2DD1D35B,
0x9A53E479, 0xB6F84565, 0xD28E49BC, 0x4BFB9790,
0xE1DDF2DA, 0xA4CB7E33, 0x62FB1341, 0xCEE4C6E8,
0xEF20CADA, 0x36774C01, 0xD07E9EFE, 0x2BF11FB4,
0x95DBDA4D, 0xAE909198, 0xEAAD8E71, 0x6B93D5A0,
0xD08ED1D0, 0xAFC725E0, 0x8E3C5B2F, 0x8E7594B7,
0x8FF6E2FB, 0xF2122B64, 0x8888B812, 0x900DF01C,
0x4FAD5EA0, 0x688FC31C, 0xD1CFF191, 0xB3A8C1AD,
0x2F2F2218, 0xBE0E1777, 0xEA752DFE, 0x8B021FA1,
0xE5A0CC0F, 0xB56F74E8, 0x18ACF3D6, 0xCE89E299,
0xB4A84FE0, 0xFD13E0B7, 0x7CC43B81, 0xD2ADA8D9,
0x165FA266, 0x80957705, 0x93CC7314, 0x211A1477,
0xE6AD2065, 0x77B5FA86, 0xC75442F5, 0xFB9D35CF,
0xEBCDAF0C, 0x7B3E89A0, 0xD6411BD3, 0xAE1E7E49,
0x00250E2D, 0x2071B35E, 0x226800BB, 0x57B8E0AF,
0x2464369B, 0xF009B91E, 0x5563911D, 0x59DFA6AA,
0x78C14389, 0xD95A537F, 0x207D5BA2, 0x02E5B9C5,
0x83260376, 0x6295CFA9, 0x11C81968, 0x4E734A41,
0xB3472DCA, 0x7B14A94A, 0x1B510052, 0x9A532915,
0xD60F573F, 0xBC9BC6E4, 0x2B60A476, 0x81E67400,
0x08BA6FB5, 0x571BE91F, 0xF296EC6B, 0x2A0DD915,
0xB6636521, 0xE7B9F9B6, 0xFF34052E, 0xC5855664,
0x53B02D5D, 0xA99F8FA1, 0x08BA4799, 0x6E85076A
],
[
0x4B7A70E9, 0xB5B32944, 0xDB75092E, 0xC4192623,
0xAD6EA6B0, 0x49A7DF7D, 0x9CEE60B8, 0x8FEDB266,
0xECAA8C71, 0x699A17FF, 0x5664526C, 0xC2B19EE1,
0x193602A5, 0x75094C29, 0xA0591340, 0xE4183A3E,
0x3F54989A, 0x5B429D65, 0x6B8FE4D6, 0x99F73FD6,
0xA1D29C07, 0xEFE830F5, 0x4D2D38E6, 0xF0255DC1,
0x4CDD2086, 0x8470EB26, 0x6382E9C6, 0x021ECC5E,
0x09686B3F, 0x3EBAEFC9, 0x3C971814, 0x6B6A70A1,
0x687F3584, 0x52A0E286, 0xB79C5305, 0xAA500737,
0x3E07841C, 0x7FDEAE5C, 0x8E7D44EC, 0x5716F2B8,
0xB03ADA37, 0xF0500C0D, 0xF01C1F04, 0x0200B3FF,
0xAE0CF51A, 0x3CB574B2, 0x25837A58, 0xDC0921BD,
0xD19113F9, 0x7CA92FF6, 0x94324773, 0x22F54701,
0x3AE5E581, 0x37C2DADC, 0xC8B57634, 0x9AF3DDA7,
0xA9446146, 0x0FD0030E, 0xECC8C73E, 0xA4751E41,
0xE238CD99, 0x3BEA0E2F, 0x3280BBA1, 0x183EB331,
0x4E548B38, 0x4F6DB908, 0x6F420D03, 0xF60A04BF,
0x2CB81290, 0x24977C79, 0x5679B072, 0xBCAF89AF,
0xDE9A771F, 0xD9930810, 0xB38BAE12, 0xDCCF3F2E,
0x5512721F, 0x2E6B7124, 0x501ADDE6, 0x9F84CD87,
0x7A584718, 0x7408DA17, 0xBC9F9ABC, 0xE94B7D8C,
0xEC7AEC3A, 0xDB851DFA, 0x63094366, 0xC464C3D2,
0xEF1C1847, 0x3215D908, 0xDD433B37, 0x24C2BA16,
0x12A14D43, 0x2A65C451, 0x50940002, 0x133AE4DD,
0x71DFF89E, 0x10314E55, 0x81AC77D6, 0x5F11199B,
0x043556F1, 0xD7A3C76B, 0x3C11183B, 0x5924A509,
0xF28FE6ED, 0x97F1FBFA, 0x9EBABF2C, 0x1E153C6E,
0x86E34570, 0xEAE96FB1, 0x860E5E0A, 0x5A3E2AB3,
0x771FE71C, 0x4E3D06FA, 0x2965DCB9, 0x99E71D0F,
0x803E89D6, 0x5266C825, 0x2E4CC978, 0x9C10B36A,
0xC6150EBA, 0x94E2EA78, 0xA5FC3C53, 0x1E0A2DF4,
0xF2F74EA7, 0x361D2B3D, 0x1939260F, 0x19C27960,
0x5223A708, 0xF71312B6, 0xEBADFE6E, 0xEAC31F66,
0xE3BC4595, 0xA67BC883, 0xB17F37D1, 0x018CFF28,
0xC332DDEF, 0xBE6C5AA5, 0x65582185, 0x68AB9802,
0xEECEA50F, 0xDB2F953B, 0x2AEF7DAD, 0x5B6E2F84,
0x1521B628, 0x29076170, 0xECDD4775, 0x619F1510,
0x13CCA830, 0xEB61BD96, 0x0334FE1E, 0xAA0363CF,
0xB5735C90, 0x4C70A239, 0xD59E9E0B, 0xCBAADE14,
0xEECC86BC, 0x60622CA7, 0x9CAB5CAB, 0xB2F3846E,
0x648B1EAF, 0x19BDF0CA, 0xA02369B9, 0x655ABB50,
0x40685A32, 0x3C2AB4B3, 0x319EE9D5, 0xC021B8F7,
0x9B540B19, 0x875FA099, 0x95F7997E, 0x623D7DA8,
0xF837889A, 0x97E32D77, 0x11ED935F, 0x16681281,
0x0E358829, 0xC7E61FD6, 0x96DEDFA1, 0x7858BA99,
0x57F584A5, 0x1B227263, 0x9B83C3FF, 0x1AC24696,
0xCDB30AEB, 0x532E3054, 0x8FD948E4, 0x6DBC3128,
0x58EBF2EF, 0x34C6FFEA, 0xFE28ED61, 0xEE7C3C73,
0x5D4A14D9, 0xE864B7E3, 0x42105D14, 0x203E13E0,
0x45EEE2B6, 0xA3AAABEA, 0xDB6C4F15, 0xFACB4FD0,
0xC742F442, 0xEF6ABBB5, 0x654F3B1D, 0x41CD2105,
0xD81E799E, 0x86854DC7, 0xE44B476A, 0x3D816250,
0xCF62A1F2, 0x5B8D2646, 0xFC8883A0, 0xC1C7B6A3,
0x7F1524C3, 0x69CB7492, 0x47848A0B, 0x5692B285,
0x095BBF00, 0xAD19489D, 0x1462B174, 0x23820E00,
0x58428D2A, 0x0C55F5EA, 0x1DADF43E, 0x233F7061,
0x3372F092, 0x8D937E41, 0xD65FECF1, 0x6C223BDB,
0x7CDE3759, 0xCBEE7460, 0x4085F2A7, 0xCE77326E,
0xA6078084, 0x19F8509E, 0xE8EFD855, 0x61D99735,
0xA969A7AA, 0xC50C06C2, 0x5A04ABFC, 0x800BCADC,
0x9E447A2E, 0xC3453484, 0xFDD56705, 0x0E1E9EC9,
0xDB73DBD3, 0x105588CD, 0x675FDA79, 0xE3674340,
0xC5C43465, 0x713E38D8, 0x3D28F89E, 0xF16DFF20,
0x153E21E7, 0x8FB03D4A, 0xE6E39F2B, 0xDB83ADF7
],
[
0xE93D5A68, 0x948140F7, 0xF64C261C, 0x94692934,
0x411520F7, 0x7602D4F7, 0xBCF46B2E, 0xD4A20068,
0xD4082471, 0x3320F46A, 0x43B7D4B7, 0x500061AF,
0x1E39F62E, 0x97244546, 0x14214F74, 0xBF8B8840,
0x4D95FC1D, 0x96B591AF, 0x70F4DDD3, 0x66A02F45,
0xBFBC09EC, 0x03BD9785, 0x7FAC6DD0, 0x31CB8504,
0x96EB27B3, 0x55FD3941, 0xDA2547E6, 0xABCA0A9A,
0x28507825, 0x530429F4, 0x0A2C86DA, 0xE9B66DFB,
0x68DC1462, 0xD7486900, 0x680EC0A4, 0x27A18DEE,
0x4F3FFEA2, 0xE887AD8C, 0xB58CE006, 0x7AF4D6B6,
0xAACE1E7C, 0xD3375FEC, 0xCE78A399, 0x406B2A42,
0x20FE9E35, 0xD9F385B9, 0xEE39D7AB, 0x3B124E8B,
0x1DC9FAF7, 0x4B6D1856, 0x26A36631, 0xEAE397B2,
0x3A6EFA74, 0xDD5B4332, 0x6841E7F7, 0xCA7820FB,
0xFB0AF54E, 0xD8FEB397, 0x454056AC, 0xBA489527,
0x55533A3A, 0x20838D87, 0xFE6BA9B7, 0xD096954B,
0x55A867BC, 0xA1159A58, 0xCCA92963, 0x99E1DB33,
0xA62A4A56, 0x3F3125F9, 0x5EF47E1C, 0x9029317C,
0xFDF8E802, 0x04272F70, 0x80BB155C, 0x05282CE3,
0x95C11548, 0xE4C66D22, 0x48C1133F, 0xC70F86DC,
0x07F9C9EE, 0x41041F0F, 0x404779A4, 0x5D886E17,
0x325F51EB, 0xD59BC0D1, 0xF2BCC18F, 0x41113564,
0x257B7834, 0x602A9C60, 0xDFF8E8A3, 0x1F636C1B,
0x0E12B4C2, 0x02E1329E, 0xAF664FD1, 0xCAD18115,
0x6B2395E0, 0x333E92E1, 0x3B240B62, 0xEEBEB922,
0x85B2A20E, 0xE6BA0D99, 0xDE720C8C, 0x2DA2F728,
0xD0127845, 0x95B794FD, 0x647D0862, 0xE7CCF5F0,
0x5449A36F, 0x877D48FA, 0xC39DFD27, 0xF33E8D1E,
0x0A476341, 0x992EFF74, 0x3A6F6EAB, 0xF4F8FD37,
0xA812DC60, 0xA1EBDDF8, 0x991BE14C, 0xDB6E6B0D,
0xC67B5510, 0x6D672C37, 0x2765D43B, 0xDCD0E804,
0xF1290DC7, 0xCC00FFA3, 0xB5390F92, 0x690FED0B,
0x667B9FFB, 0xCEDB7D9C, 0xA091CF0B, 0xD9155EA3,
0xBB132F88, 0x515BAD24, 0x7B9479BF, 0x763BD6EB,
0x37392EB3, 0xCC115979, 0x8026E297, 0xF42E312D,
0x6842ADA7, 0xC66A2B3B, 0x12754CCC, 0x782EF11C,
0x6A124237, 0xB79251E7, 0x06A1BBE6, 0x4BFB6350,
0x1A6B1018, 0x11CAEDFA, 0x3D25BDD8, 0xE2E1C3C9,
0x44421659, 0x0A121386, 0xD90CEC6E, 0xD5ABEA2A,
0x64AF674E, 0xDA86A85F, 0xBEBFE988, 0x64E4C3FE,
0x9DBC8057, 0xF0F7C086, 0x60787BF8, 0x6003604D,
0xD1FD8346, 0xF6381FB0, 0x7745AE04, 0xD736FCCC,
0x83426B33, 0xF01EAB71, 0xB0804187, 0x3C005E5F,
0x77A057BE, 0xBDE8AE24, 0x55464299, 0xBF582E61,
0x4E58F48F, 0xF2DDFDA2, 0xF474EF38, 0x8789BDC2,
0x5366F9C3, 0xC8B38E74, 0xB475F255, 0x46FCD9B9,
0x7AEB2661, 0x8B1DDF84, 0x846A0E79, 0x915F95E2,
0x466E598E, 0x20B45770, 0x8CD55591, 0xC902DE4C,
0xB90BACE1, 0xBB8205D0, 0x11A86248, 0x7574A99E,
0xB77F19B6, 0xE0A9DC09, 0x662D09A1, 0xC4324633,
0xE85A1F02, 0x09F0BE8C, 0x4A99A025, 0x1D6EFE10,
0x1AB93D1D, 0x0BA5A4DF, 0xA186F20F, 0x2868F169,
0xDCB7DA83, 0x573906FE, 0xA1E2CE9B, 0x4FCD7F52,
0x50115E01, 0xA70683FA, 0xA002B5C4, 0x0DE6D027,
0x9AF88C27, 0x773F8641, 0xC3604C06, 0x61A806B5,
0xF0177A28, 0xC0F586E0, 0x006058AA, 0x30DC7D62,
0x11E69ED7, 0x2338EA63, 0x53C2DD94, 0xC2C21634,
0xBBCBEE56, 0x90BCB6DE, 0xEBFC7DA1, 0xCE591D76,
0x6F05E409, 0x4B7C0188, 0x39720A3D, 0x7C927C24,
0x86E3725F, 0x724D9DB9, 0x1AC15BB4, 0xD39EB8FC,
0xED545578, 0x08FCA5B5, 0xD83D7CD3, 0x4DAD0FC4,
0x1E50EF5E, 0xB161E6F8, 0xA28514D9, 0x6C51133C,
0x6FD5C7E7, 0x56E14EC4, 0x362ABFCE, 0xDDC6C837,
0xD79A3234, 0x92638212, 0x670EFA8E, 0x406000E0
],
[
0x3A39CE37, 0xD3FAF5CF, 0xABC27737, 0x5AC52D1B,
0x5CB0679E, 0x4FA33742, 0xD3822740, 0x99BC9BBE,
0xD5118E9D, 0xBF0F7315, 0xD62D1C7E, 0xC700C47B,
0xB78C1B6B, 0x21A19045, 0xB26EB1BE, 0x6A366EB4,
0x5748AB2F, 0xBC946E79, 0xC6A376D2, 0x6549C2C8,
0x530FF8EE, 0x468DDE7D, 0xD5730A1D, 0x4CD04DC6,
0x2939BBDB, 0xA9BA4650, 0xAC9526E8, 0xBE5EE304,
0xA1FAD5F0, 0x6A2D519A, 0x63EF8CE2, 0x9A86EE22,
0xC089C2B8, 0x43242EF6, 0xA51E03AA, 0x9CF2D0A4,
0x83C061BA, 0x9BE96A4D, 0x8FE51550, 0xBA645BD6,
0x2826A2F9, 0xA73A3AE1, 0x4BA99586, 0xEF5562E9,
0xC72FEFD3, 0xF752F7DA, 0x3F046F69, 0x77FA0A59,
0x80E4A915, 0x87B08601, 0x9B09E6AD, 0x3B3EE593,
0xE990FD5A, 0x9E34D797, 0x2CF0B7D9, 0x022B8B51,
0x96D5AC3A, 0x017DA67D, 0xD1CF3ED6, 0x7C7D2D28,
0x1F9F25CF, 0xADF2B89B, 0x5AD6B472, 0x5A88F54C,
0xE029AC71, 0xE019A5E6, 0x47B0ACFD, 0xED93FA9B,
0xE8D3C48D, 0x283B57CC, 0xF8D56629, 0x79132E28,
0x785F0191, 0xED756055, 0xF7960E44, 0xE3D35E8C,
0x15056DD4, 0x88F46DBA, 0x03A16125, 0x0564F0BD,
0xC3EB9E15, 0x3C9057A2, 0x97271AEC, 0xA93A072A,
0x1B3F6D9B, 0x1E6321F5, 0xF59C66FB, 0x26DCF319,
0x7533D928, 0xB155FDF5, 0x03563482, 0x8ABA3CBB,
0x28517711, 0xC20AD9F8, 0xABCC5167, 0xCCAD925F,
0x4DE81751, 0x3830DC8E, 0x379D5862, 0x9320F991,
0xEA7A90C2, 0xFB3E7BCE, 0x5121CE64, 0x774FBE32,
0xA8B6E37E, 0xC3293D46, 0x48DE5369, 0x6413E680,
0xA2AE0810, 0xDD6DB224, 0x69852DFD, 0x09072166,
0xB39A460A, 0x6445C0DD, 0x586CDECF, 0x1C20C8AE,
0x5BBEF7DD, 0x1B588D40, 0xCCD2017F, 0x6BB4E3BB,
0xDDA26A7E, 0x3A59FF45, 0x3E350A44, 0xBCB4CDD5,
0x72EACEA8, 0xFA6484BB, 0x8D6612AE, 0xBF3C6F47,
0xD29BE463, 0x542F5D9E, 0xAEC2771B, 0xF64E6370,
0x740E0D8D, 0xE75B1357, 0xF8721671, 0xAF537D5D,
0x4040CB08, 0x4EB4E2CC, 0x34D2466A, 0x0115AF84,
0xE1B00428, 0x95983A1D, 0x06B89FB4, 0xCE6EA048,
0x6F3F3B82, 0x3520AB82, 0x011A1D4B, 0x277227F8,
0x611560B1, 0xE7933FDC, 0xBB3A792B, 0x344525BD,
0xA08839E1, 0x51CE794B, 0x2F32C9B7, 0xA01FBAC9,
0xE01CC87E, 0xBCC7D1F6, 0xCF0111C3, 0xA1E8AAC7,
0x1A908749, 0xD44FBD9A, 0xD0DADECB, 0xD50ADA38,
0x0339C32A, 0xC6913667, 0x8DF9317C, 0xE0B12B4F,
0xF79E59B7, 0x43F5BB3A, 0xF2D519FF, 0x27D9459C,
0xBF97222C, 0x15E6FC2A, 0x0F91FC71, 0x9B941525,
0xFAE59361, 0xCEB69CEB, 0xC2A86459, 0x12BAA8D1,
0xB6C1075E, 0xE3056A0C, 0x10D25065, 0xCB03A442,
0xE0EC6E0E, 0x1698DB3B, 0x4C98A0BE, 0x3278E964,
0x9F1F9532, 0xE0D392DF, 0xD3A0342B, 0x8971F21E,
0x1B0A7441, 0x4BA3348C, 0xC5BE7120, 0xC37632D8,
0xDF359F8D, 0x9B992F2E, 0xE60B6F47, 0x0FE3F11D,
0xE54CDA54, 0x1EDAD891, 0xCE6279CF, 0xCD3E7E6F,
0x1618B166, 0xFD2C1D05, 0x848FD2C5, 0xF6FB2299,
0xF523F357, 0xA6327623, 0x93A83531, 0x56CCCD02,
0xACF08162, 0x5A75EBB5, 0x6E163697, 0x88D273CC,
0xDE966292, 0x81B949D0, 0x4C50901B, 0x71C65614,
0xE6C6C7BD, 0x327A140A, 0x45E1D006, 0xC3F27B9A,
0xC9AA53FD, 0x62A80F00, 0xBB25BFE2, 0x35BDD2F6,
0x71126905, 0xB2040222, 0xB6CBCF7C, 0xCD769C2B,
0x53113EC0, 0x1640E3D3, 0x38ABBD60, 0x2547ADF0,
0xBA38209C, 0xF746CE76, 0x77AFA1C5, 0x20756060,
0x85CBFE4E, 0x8AE88DD8, 0x7AAAF9B0, 0x4CF9AA7E,
0x1948C25C, 0x02FB8A8C, 0x01C36AE4, 0xD6EBE1F9,
0x90D4F869, 0xA65CDEA0, 0x3F09252D, 0xC208E69F,
0xB74E6132, 0xCE77E25B, 0x578FDFE3, 0x3AC372E6
]
]
# Cycle through the p-boxes and round-robin XOR the
# key with the p-boxes
key_len = len (key)
for i in range (len (self.p_boxes)):
val = (ord (key[(i * 4) % key_len]) << 24) +
(ord (key[(i * 4 + 1) % key_len]) << 16) +
(ord (key[(i * 4 + 2) % key_len]) << 8) +
ord (key[(i * 4 + 3) % key_len])
self.p_boxes[i] ^= val
# For the chaining process
l, r = 0, 0
# Begin chain replacing the p-boxes
for i in range (0, len (self.p_boxes), 2):
l, r = self.cipher (l, r, self.ENCRYPT)
self.p_boxes[i] = l
self.p_boxes[i + 1] = r
# Chain replace the s-boxes
for i in range (len (self.s_boxes)):
for j in range (0, len (self.s_boxes[i]), 2):
l, r = self.cipher (l, r, self.ENCRYPT)
self.s_boxes[i][j] = l
self.s_boxes[i][j + 1] = r
def cipher (self, xl, xr, direction):
if direction == self.ENCRYPT:
for i in range (16):
xl ^= self.p_boxes[i]
xr = self.__round_func (xl) ^ xr
xl, xr = xr, xl
xl, xr = xr, xl
xr ^= self.p_boxes[16]
xl ^= self.p_boxes[17]
else:
for i in range (17, 1, -1):
xl ^= self.p_boxes[i]
xr = self.__round_func (xl) ^ xr
xl, xr = xr, xl
xl, xr = xr, xl
xr ^= self.p_boxes[1]
xl ^= self.p_boxes[0]
return xl, xr
def __round_func (self, xl):
a = (xl & 0xFF000000) >> 24
b = (xl & 0x00FF0000) >> 16
c = (xl & 0x0000FF00) >> 8
d = xl & 0x000000FF
# Perform all ops as longs then and out the last 32-bits to
# obtain the integer
f = (long (self.s_boxes[0][a]) + long (self.s_boxes[1][b])) % self.modulus
f ^= long (self.s_boxes[2][c])
f += long (self.s_boxes[3][d])
f = (f % self.modulus) & 0xFFFFFFFF
return f
def encrypt (self, data):
if not len (data) == 8:
raise RuntimeError, "Attempted to encrypt data of invalid block length: %s" %len (data)
# Use big endianess since that's what everyone else uses
xl = ord (data[3]) | (ord (data[2]) << 8) | (ord (data[1]) << 16) | (ord (data[0]) << 24)
xr = ord (data[7]) | (ord (data[6]) << 8) | (ord (data[5]) << 16) | (ord (data[4]) << 24)
cl, cr = self.cipher (xl, xr, self.ENCRYPT)
chars = ''.join ([
chr ((cl >> 24) & 0xFF), chr ((cl >> 16) & 0xFF), chr ((cl >> 8) & 0xFF), chr (cl & 0xFF),
chr ((cr >> 24) & 0xFF), chr ((cr >> 16) & 0xFF), chr ((cr >> 8) & 0xFF), chr (cr & 0xFF)
])
return chars
def decrypt (self, data):
if not len (data) == 8:
raise RuntimeError, "Attempted to encrypt data of invalid block length: %s" %len (data)
# Use big endianess since that's what everyone else uses
cl = ord (data[3]) | (ord (data[2]) << 8) | (ord (data[1]) << 16) | (ord (data[0]) << 24)
cr = ord (data[7]) | (ord (data[6]) << 8) | (ord (data[5]) << 16) | (ord (data[4]) << 24)
xl, xr = self.cipher (cl, cr, self.DECRYPT)
chars = ''.join ([
chr ((xl >> 24) & 0xFF), chr ((xl >> 16) & 0xFF), chr ((xl >> 8) & 0xFF), chr (xl & 0xFF),
chr ((xr >> 24) & 0xFF), chr ((xr >> 16) & 0xFF), chr ((xr >> 8) & 0xFF), chr (xr & 0xFF)
])
return chars
def blocksize (self):
return 8
def key_length (self):
return 56
def key_bits (self):
return 56 * 8
##############################################################
# Module testing
if __name__ == '__main__':
key = 'This is a test key'
cipher = Blowfish (key)
print "Testing encryption:"
xl = 123456
xr = 654321
print "tPlain text: (%s, %s)" %(xl, xr)
cl, cr = cipher.cipher (xl, xr, cipher.ENCRYPT)
print "tCrypted is: (%s, %s)" %(cl, cr)
dl, dr = cipher.cipher (cl, cr, cipher.DECRYPT)
print "tUnencrypted is: (%s, %s)" %(dl, dr)
print "Testing buffer encrypt:"
text = 'testtest'
print "tText: %s" %text
crypted = cipher.encrypt (text)
print "tEncrypted: %s" %crypted
decrypted = cipher.decrypt (crypted)
print "tDecrypted: %s" %decrypted
Este exemplo acima é Criptografia extremamente forte e pode ser usado para criptografar um texto grande por exemplo, e para usa-lo, tem um segredinho.
A entrada para parte de criptografia ou descriptografia do algoritmo é de 64 bits. Então temos que 64 bits = 8 Bytes = 8 caracteres. Para quem não entendeu ainda, 64 bits / 8 bits = 8 Bytes
O blowfish só recebe em blocos de 8 caracteres as entradas, então vamos ter que separar a string com muitos caracteres em vários blocos de 8 caracteres apenas.
Faremos isso com um laço for e vamos cortar a string em vários blocos de 8 caracteres. Mas e se o último bloco conter apenas 6 caracteres? Para termos certeza de que a string contem 8 caracteres podemos forçar com o método string.ljust(variavel, 8 )
A senha também não deve ter menos de 8 caracteres, então está a outra dica: Usar o ljust() na senha também.
Abaixo uma classe bem simples que criptografa e descriptografa com Blowfish.
# cript.py
# Feito em 22/08/2007
#
import sys
import string
import base64
import blowfish
__author__ = "Felipe Ferreri Tonello <felipe.tonello@gmail.com>"
class BFCript:
"""
Classe que usa criptografia Blowfish juntamente com encodificacão Base64
uso: cript.py cript|descript ’senha’ ‘texto’
PS: Quando for descriptografar, o texto deve estar codificado em Base64
"""
CRIPTOGRAFAR = 0
DESCRIPTOGRAFAR = 1
def cript(self, sKey, sTxt, iAction):
bf = blowfish.Blowfish((len(sKey) < 8 and [string.ljust(sKey, 8)] or [sKey])[0])
if iAction == self.DESCRIPTOGRAFAR:
sTxt = base64.b64decode(sTxt)
sCript = ""
for i in range(0, len(sTxt), 8) :
sSBox = sTxt[i:i+8]
if len(sSBox) > 0 :
if iAction == self.CRIPTOGRAFAR:
sCript += bf.encrypt(string.ljust(sSBox, 8))
elif iAction == self.DESCRIPTOGRAFAR:
sCript += bf.decrypt(sSBox)
if iAction == self.CRIPTOGRAFAR:
return base64.b64encode(sCript)
elif iAction == self.DESCRIPTOGRAFAR:
return sCript
##################################################
if __name__ == "__main__" :
bfc = BFCript()
if len(sys.argv) != 4 or (sys.argv[1] != "cript" and sys.argv[1] != "descript"):
print BFCript.__doc__
sys.exit(0)
elif sys.argv[1] == "cript" :
print bfc.cript(sys.argv[2], sys.argv[3], bfc.CRIPTOGRAFAR)
elif sys.argv[1] == "descript" :
print bfc.cript(sys.argv[2], sys.argv[3], bfc.DESCRIPTOGRAFAR)
Está gostando? Então para testar descriptografe esta menssagem:
"[color=blue]9M39agUxnX8PRznCylaC1/6rEXVP5R85QTO/be8XAO+WRJ2nAGDQ4PWq SOGSQe/CRDkegrH242gpfOcBHPZ6TURUMcQZXkSV8g7WcEIQiCLTuejOt0HCExewS XUgxg8wRlvO6G2ZrKOv6YLzcsXmBHB/JbZ5nuMnlIYQNGj1ncYHbxyJrGHj1Xr7Q696E+u WfcZAm9z/iRfZ9rb79EXY7f/5BBEvdkluxDpedPzam33CQLZoEVixSOwVI18USigj45W6fDk+ yFTGkLF1tmh5Zg==[/color]"
O que será?? ... descubra
Abaixo mais um belo exemplo (pyCrypto):
from Crypto.Cipher import AES
from md5 import md5
def padded(s, block_size):
return s.ljust(len(s) + block_size - (len(s) % block_size))
aes = AES.new(md5('secret password').digest(), AES.MODE_ECB)
plaintext = 'secret text'
ciphertext = aes.encrypt(padded(plaintext, AES.block_size))
print 'ciphertext:', `ciphertext`
aes = AES.new(md5('secret password').digest(), AES.MODE_ECB)
plaintext = aes.decrypt(ciphertext).strip()
print 'plaintext:', `plaintext`
Neste caso se usa o AES no modo ECB para cifrar o texto 'secret text' com a chave 'secret password' (na verdade, o MD5 dela) e depois decifra.
Agora com o construtor RSA (exemplo da web):
from Crypto.PublicKey import RSA
from Crypto.Util.randpool import RandomPool
texto = "texto a encriptar"
# Você deve usar a melhor fonte de dados aleatórios que tiver à
# disposição. Pra manter o exemplo mais portável, usaremos o
# RandomPool do próprio PyCrypto:
pool = RandomPool(384)
pool.stir()
# randfunc(n) deve retornar uma string de dados aleatórios de
# comprimento n, no caso de RandomPool, o método get_bytes
randfunc = pool.get_bytes
# Se tiver uma fonte segura (como /dev/urandom em sistemas unix), ela
# deve ser usada ao invés de RandomPool
# pool = open("/dev/urandom")
# randfunc = pool.read
# Tamanho da chave, em bits
N = 256
# O algoritmo RSA usado aqui não utiliza K, que pode ser uma string
# nula.
K = ""
# Geramos a chave (contendo a chave pública e privada):
key = RSA.generate(N, randfunc)
# Criptografamos o texto com a chave:
enc = key.encrypt(texto, K)
# Podemos decriptografar usando a chave:
dec = key.decrypt(enc)
# Separando apenas a chave pública:
pub_key = key.publickey()
# Criptografando com a chave pública:
enc = pub_key.encrypt(texto, K)
# Decriptografando com a chave privada:
dec = key.decrypt(enc)
# As informações da chave são compostas de seis atributos: 'n', 'e',
# 'd', 'p', 'q' e 'u'. Se quiser armazenar ou enviar uma chave você
# pode usar pickle ou simplesmente usar esses atributos com o método
# construct. Por exemplo:
# Os atributos 'n' e 'e' correspondem à chave pública:
n, e = key.n, key.e
# E recriamos a chave pública com esses dados:
pub_key = RSA.construct((n, e))
Para terminar, vou deixar um super exemplo de dedicação. Este cara faz até uma GUI em Tkinter para implementar seu próprio método de criptografia:
#Created By:Patrick T. Cossette (Nobis Software) <www.nobis-development.com>
#Feel free to use this code however you see fit,
#if you intend to use it's encryption methods it
#would be wise to make some slight alterations to
#the 'special' and 'alpha' dictionaries, as well as
#possibly change up 'num' a little bit. (perhaps times
#it by int((num % (num*.82))+1) or something like that
#(you get the idea)
from Tkinter import *
import tkMessageBox
from ScrolledText import ScrolledText
import tkFileDialog
#from tkColorButton import * I use this module to make my buttons look nicer, it doesn't come with Tk; but can be found on www.python-forum.org
import string
import random
import bz2
from os import getcwd, sys;cwd = getcwd()
d = {}
rd = {}
#If you intedt to change these dictionaries up a little bit, only change the VALUES, NOT THE KEYS! Changing the keys would raise a KeyError during encryption/decryption
special = {'1':'xff', '2':'xaa', '3':'xdb', '4':'xe4', '5':'xf1', '6':'xfb', '7':'xdd', '9':'xf3', '0':'xxf5', '8':'xfa'} #"Special" Characters
alpha = {'1':'F', '2':'w]', '3':'H', '4':'%', 'j':')', '6':'Y', '7':'k', '9':'Z', '0':'{', '8':'*'} #Ascii Characters
txtz = special
#The following code prevents error messages from being seen
class errorLog: #Create class to replace sys.stderr
def write(self, x):#Dummy function
pass #errors will go unheard.
ERR = errorLog
sys.stderr = ERR #Re-route error messages to dummy class
#If errors occur when using this script, comment out or delete
#the above block of code, so you can see the error messages
crypted = False #Attempts to keep track if the text is encrypted or not
ALL_ASCII = string.ascii_letters + " " + string.punctuation + string.digits + 'nt'
def encrypt(Event = None):
if UP.get():setState("disabled")
root.update()
global crypted
a = False
if crypted:a = tkMessageBox.askyesno(title = "Procede?", message = "The text appears to already have beep Encryptednand cannot be encrypted twice. Would you like tonattempt to encrypt it anyway?")
if not crypted or a:
num = random.randint(1, strength.get()) #Grab a random number to base the encryption on
rd = {} #Create the two dictionaries that will be used to "jumble up" the original text
d = {}
for char, index in zip(ALL_ASCII, range(num, 101*num, num)):
d[index] = char
for char, index in zip(ALL_ASCII, range(num, 101*num, num)):
rd[char] = index
result = []
for char in txt.get(0.0, (END))[:-1]: #Go through the text character by character (disguarding the trailing '\n')
try:
result.append(str(rd[char])) #Fine each character's alternate value, and add it to a list (not added to a string so that a character can be inserted to seperate them later. This is because one character may have a length of up to 6 or 7 after being translated)
except:
tkMessageBox.showwarning(title = "ERROR", message = "An Error Occured During Decryption") #Something bad happened
txt.delete(0.0, (END))
final = str(num) +(7-len(str(num)))*" " + "xdf".join(result) + 'xdff' #Join each changed character with a certain special character, placing the EOF "xdff" at the end, and what number to base the decryption on at the beginning
if asciiOnly.get():
for char,val in txtz.items():
final = final.replace(char, val)
txt.insert((END),final)
if jump.get():
txt.yview_moveto(1)
crypted = True #Set text status to "encrypted"
elif crypted and a:
tkMessageBox.showwarning(title = "Double Encryption", message = "You cannot encrypt something twice!")
setState("normal")
def setState(state):
for widget in [c1, c2, b1, b2, b3]: #Disable control buttons at the bottom of the window so the user cannot press them while the program is working
widget['state'] = state
def decrypt(Event = None): #This version seems to freeze up when decrypting large amounts of text. Not sure why, the original has no problem.
root.update() #Pop the button back out :P
if UP.get():setState("disabled")
global crypted
a = False
if not crypted:
if tkMessageBox.askyesno(title = "Procede?", message = "The text does not appear to be encrypted, Would you like to attempt decryption anyway?"):crypted, a = True, True
if crypted:
x = txt.get(0.0, (END))[:-1]#Grab the text, disguarding the trailing '\n'
for i in alpha.values(): #Look for any value that may indicate the text was encrypted using "TEXT ONLY"
if i in x:
txtz = alpha
break
for i in special.values():#Look for any value that may indicate the text was encrypted using "SPECIAL ONLY"
if i in x:
txtz = special
break
if asciiOnly.get(): #Some Confusion here when it comes to decrypting "Numeric", THEN decrypting "SPECIAL" characters. I have yet to find the cause of the error...
for char,val in txtz.items(): #Get rid of the encrpted text to make room for the result
x = x.replace(val, char) #If "Numbers Only" was selected, this will replace nothing
try:
num = int(x[:7].strip()) #Retrieve the number used to encrypt the text, and remove any white space (which will only be there if 'num' was <= 99999)
except:
tkMessageBox.showwarning(title = "ERROR", message = "An Error Occured During Decryption") #Could not find a number to base decryption on
x = x[7:] #assign the encrypted text to 'x'
rd = {} #Redefined every time because their contents change every time something is encrypted, they do not hold static values
d = {}
for char, index in zip(ALL_ASCII, range(num, 101*num, num)):
d[index] = char
for char, index in zip(ALL_ASCII, range(num, 101*num, num)):
rd[char] = index
result = ""
f = ""
go = False
for char in x:
if char == "xdf":#Because one character may have a length of more than 1
go = True
if go:
try:
result += d[int(f)] #Peice the result together character by character
if UP.get():
txt.insert((END), d[int(f)])
root.update()
if jump.get():
txt.yview_moveto(1)
except:
pass
go = False
f = ""
else:
f += char
txt.delete(0.0, (END))
txt.insert((END), result)
if jump.get():
txt.yview_moveto(1)
crypted = False
elif not crypted and a:
tkMessageBox.showwarning(title = "ERROR", message = "An Error Occured During Decryption")
setState("normal")
def clear(): #Reset
global crypted
crypted = False
txt.delete(0.0, (END))
root = Tk()
strength = IntVar()
strength.set(9999999)
#The original version of this program required that certain files
#be present to operate, but has been modified to run without them
#These files included a license file, as well as logo images for
#the "about" window.
#logo2 = PhotoImage(file = "%sResourceslogo2.gif" %cwd)
#rocket = PhotoImage(file = "%sResourcesrocket.gif" %cwd)
def about(Event=None):
master = Toplevel(root)
master.title('About Basic Encryption Tool')
master.focus_set()
photolabel1 = Label(master, text = "No Image")#image = logo2) XXX Image removed so that this code can be sent raw, and still operate correctly (not dependant on other files)
photolabel1.grid(row = 1, sticky = NW, column = 0, padx = 10, rowspan = 2)
photolabel2 = Label(master, text = "No Image")#image = logo2)
photolabel2.grid(sticky = NE, row = 1, padx = 10, rowspan = 2)
a = Label(master, text='www.nobis-development.comnCreated By:Patrick T. CossettenCold_Soul79078@yahoo.com', font = ('Trebuchet MS', 7, 'bold'))
a.grid(row = 0)
photolabel = Label(master, text = "No Image")#image = rocket) #Nobis Software logo. www.nobis-development.com
photolabel.grid(row = 2)
copyright = ScrolledText(master, width = 68, height = 16, bg = 'light grey', font = ("arial", 8))
#copyright.insert((END), file("%slicense.txt" %cwd, 'r').read()) WAS under a more "strict" license, but I decided to be much more 'lax' with this program
copyright.insert((END), "OpenSource Freeware.. do with it what you wish...nnnttttm/>.<m/ -- Spade42") #Use it, don't use it, change it, post it.. whatever
copyright.grid(row = 3, padx = 5, pady = 5)
f = Frame(master)
back = Button(f, text='Exit', command = master.destroy, width = 8, font = ("arial", 10))
back.grid(pady=10,row = 0, column = 8, padx = 5)
f.grid(pady=10,row = 4, sticky = E)
master.minsize(480, 456)
master.maxsize(480, 456)
master.resizable(width = False, height = False)
master.grab_set()
def setDictionary(x = None):
global txtz
if x != None:
asciiOnly.set(x)
if asciiOnly.get() == 1:
txtz = alpha
elif asciiOnly.get() == 2:
txtz = special
def openFile(Event = None):
global crypted
file = tkFileDialog.askopenfile(title = "Open Encrypted Text File", filetypes = (("Text File", (".txt", )), ("All File Types", ("*.*",))))
if file != None:
txt.delete(0.0, (END))
a = file.read()
if a.startswith("BZh"): #Auto-detect BZ2 compression, if found, attempt to decompress the file first
try:
a = bz2.decompress(a)
except:
pass
#Check for encryption method
if "xdf" in a:
crypted = True
elif "xdc" in a:
a = a.replace("xdc", "xdf") #Reverse compatability feature
crypted = True
txt.insert((END), a)
file.close()
if crypted:decrypt() #If encryption was detected, decrypt the text automatically.
def saveFile(Event = None):
writeT = writeT = txt.get(0.0,(END))
file = tkFileDialog.asksaveasfile(title = "Save Encrypted Text File", filetypes = (("Text File", (".txt", )), ), defaultextension = (("Text File", (".txt", )), ))
if file != None:
if compress.get():
writeT = bz2.compress(txt.get(0.0,(END))) #Compressing the encrypted text is EXTREMEMLY iffy, but it should work fine to just compress normal text (not encrypted)
file.write(writeT)
file.close()
def setCompress():
if compress.get(): #I wouldn't risk compressing encrypted text, only really good for compressing plain text
if not tkMessageBox.askyesno(title = "Compress?", message = """
Are you sure you want to compress the output? Doing so may cause this file to be permanantly
lost. You may want to save a backup file that is not compressed, and make sure the compressed
file CAN be opened successfully."""):compress.set(0)
def copyAll():
root.clipboard_append(txt.get(0.0, (END)))
def paste(): #Paste and decrypt
global crypted
txt.delete(0.0, (END))
txt.insert(0.0, root.clipboard_get())
crypted = True
decrypt()
def pasteE(): #Paste and encrypt
global crypted
txt.delete(0.0, (END))
txt.insert(0.0, root.clipboard_get())
crypted = False
encrypt()
def endApp(): #Just a fance 'destroy' function I suppose..
if tkMessageBox.askyesno(title = "Exit?", message = "Are you sure you want to exit?"):
root.iconify() #Just looks nice =]
root.destroy()
UP = IntVar()
UP.set(0)
jump = IntVar()
jump.set(1)
compress = IntVar()
compress.set(0)
asciiOnly = IntVar()
asciiOnly.set(2)
root.title("Encryption Tool")
#Create event bindings
root.bind("<Control-o>", openFile)
root.bind("<Control-s>", saveFile)
root.bind("<Control-e>", encrypt)
root.bind("<Control-d>", decrypt)
root.bind("<Control-t>", lambda Event:setDictionary(1))
root.bind("<Control-n>", lambda Event:setDictionary(2))
root.bind("<Control-p>", lambda Event:setDictionary(0))
txt = ScrolledText(root, width = 100, height = 28, font = ("Arial", 12))
txt.grid(row = 0, column = 0, columnspan = 25, rowspan = 10, padx = 10, pady = 7)
txt.focus()
c1 = Checkbutton(root, text = "Auto Scroll", variable =jump, font = ("arial", 10))
c1.grid(row = 11, column = 16)
c2 = Checkbutton(root, text = "Realtime Decryption Update", variable = UP, font = ("arial", 10))
c2.grid(row = 11, column = 17, columnspan = 3)
b1 = Button(root, text = "Clear", font = ("Arial", 10), command = clear, width = 10)
b1.grid(row = 11, pady = 5, pady = 5, column = 21)
b2 = Button(root, text = "Decrypt", font = ("Arial", 10), command = decrypt, width = 10)
b2.grid(row = 11, pady = 5, pady = 5, column = 22)
b3 = Button(root, text = "Encrypt", font = ("Arial", 10), command = encrypt, width = 10)
b3.grid(row = 11, pady = 5, pady = 5, column = 23)
menu = Menu(root)
txt.bind("<Button-3>", lambda Event:editmenu.post(Event.x_root, Event.y_root)) #Enables you to right-click the text area
root.config(menu=menu)
filemenu = Menu(menu, tearoff = False, activeforeground = 'red', activebackground = 'white', bg = 'white')
helpmenu = Menu(menu, tearoff = False, activeforeground = 'red', activebackground = 'white', bg = 'white')
actionmenu = Menu(menu, tearoff = False, activeforeground = 'red', activebackground = 'white', bg = 'white')
strengthmenu = Menu(menu, tearoff = False, activeforeground = 'red', activebackground = 'white', bg = 'white')
outputmenu = Menu(menu, tearoff = False, activeforeground = 'red', activebackground = 'white', bg = 'white')
editmenu = Menu(menu, tearoff = False, activeforeground = 'red', activebackground = 'white', bg = 'white')
menu.add_cascade(label = "File", menu = filemenu)
menu.add_cascade(label = "Edit", menu = editmenu)
menu.add_cascade(label = "Action", menu = actionmenu)
menu.add_cascade(label = "Help", menu = helpmenu)
filemenu.add_command(label = "Open Text File Ctrl+O", command = openFile)
filemenu.add_command(label = "Save Text File Ctrl+S", command = saveFile)
filemenu.add_separator()
filemenu.add_command(label = "Exit", command = endApp)
helpmenu.add_command(label = "About F1", command = about)
editmenu.add_command(label = "Copy All", command = copyAll)
editmenu.add_command(label = "Paste",command = lambda:txt.insert((END), root.clipboard_get()))
editmenu.add_command(label = "Paste And Encrypt",command = pasteE)
editmenu.add_command(label = "Paste And Decrypt",command = paste)
actionmenu.add_command(label = "Encrypt Ctrl+E", command = encrypt)
actionmenu.add_command(label = "Decrypt Ctrl+D", command = decrypt)
actionmenu.add_separator()
actionmenu.add_cascade(label = "Strength", menu = strengthmenu)
actionmenu.add_cascade(label = "Output", menu = outputmenu)
outputmenu.add_radiobutton(label = "Text Only Alt+T", variable = asciiOnly, value = 1, command = setDictionary)
outputmenu.add_radiobutton(label = "Numeric Only Alt+N", variable = asciiOnly, value = 0, command = setDictionary)
outputmenu.add_radiobutton(label = "Special Only Alt+P", variable = asciiOnly, value = 2, command = setDictionary)
outputmenu.add_separator()
outputmenu.add_checkbutton(label = "Compress Output", command = setCompress, variable = compress)
strengthmenu.add_radiobutton(label = "Very Strong Alt+Z", variable = strength, value = 9999999)
strengthmenu.add_radiobutton(label = "Strong Alt+X", variable = strength, value = 500000)
strengthmenu.add_radiobutton(label = "Medium Alt+C", variable = strength, value = 250000)
strengthmenu.add_radiobutton(label = "Weak Alt+V", variable = strength, value = 99999)
strengthmenu.add_radiobutton(label = "Very Weak Alt+B", variable = strength, value = 5)
strengthmenu.add_radiobutton(label = "Almost Pointless Alt+N", variable = strength, value = 1)
root.bind("<Alt-n>", lambda Event:strength.set(1)) #Attempted to use Alt+1, 2, 3, 4 etc. But couldn't figure out how to tell Tk I wasn't talkint about the mouse buttons o.0
root.bind("<Alt-b>", lambda Event:strength.set(5))
root.bind("<Alt-v>", lambda Event:strength.set(99999))
root.bind("<Alt-c>", lambda Event:strength.set(250000))
root.bind("<Alt-x>", lambda Event:strength.set(500000))
root.bind("<Alt-z>", lambda Event:strength.set(9999999)) #Number being passed to set() represents the number of possible encryption combinations
root.bind("<F1>", about)
root.resizable(height = 0, width = 0) #Disables the "Maximize" button
root.protocol("WM_DELETE_WINDOW", endApp) #Use the "fancy" shutdown function no matter how the program is closed
root.mainloop()#GO!!!!