Uma forma simples de codificar uma string de acordo com uma senha?
o Python tem uma forma simples de codificar / descodificar strings usando uma senha?
Algo do género:>>> encode('John Doe', password = 'mypass')
'sjkl28cn2sx0'
>>> decode('sjkl28cn2sx0', password = 'mypass')
'John Doe'
Então o texto "desconhecido" é encriptado como "sjkl28cn2sx0". Para obter a string original, eu "desbloquearia" essa string com a chave 'mypass', que é uma senha em meu código fonte. Eu gostaria que esta fosse a maneira que eu posso criptografar/descriptografar um documento do Word com uma senha.
gostaria de usar estes textos encriptados como parâmetros de URL. O meu objectivo é: ofuscação, não Segurança forte, nada crítico de missão está a ser codificado. Eu percebo que eu poderia usar uma tabela de banco de dados para armazenar chaves e valores, mas estou tentando ser minimalista.
15 answers
Assumindo que você está apenasprocurando por ofuscação simples que irá obscurecer as coisas do Muito observador casual, e você não está olhando para usar bibliotecas de terceiros. Recomendo algo como a cifra de Vigenere. É uma das mais fortes das simples Cifras antigas.
É rápido e fácil de implementar. Algo do género:import base64
def encode(key, string):
encoded_chars = []
for i in xrange(len(string)):
key_c = key[i % len(key)]
encoded_c = chr(ord(string[i]) + ord(key_c) % 256)
encoded_chars.append(encoded_c)
encoded_string = "".join(encoded_chars)
return base64.urlsafe_b64encode(encoded_string)
A descodificação é praticamente a mesma, só que subtrai a chave.
É muito mais difícil de quebrar se os strings que você está codificando são curtos, e / ou se é difícil adivinhar o comprimento da frase-senha usada.
Se está à procura de algo criptográfico, o PyCrypto é provavelmente a sua melhor aposta, embora as respostas anteriores ignorem alguns detalhes: o modo BCE em PyCrypto requer que a sua mensagem seja um múltiplo de 16 caracteres de comprimento. Então, tens de pad. Além disso, se você quiser usá-los como parâmetros URL, use base64.urlsafe_b64_encode()
, em vez do padrão. Este facto substitui alguns dos caracteres do alfabeto base64 com caracteres de segurança de URL (como o seu nome sugere).
Então, usando o PyCrypto:
from Crypto.Cipher import AES
import base64
msg_text = 'test some plain text here'.rjust(32)
secret_key = '1234567890123456' # create new & store somewhere safe
cipher = AES.new(secret_key,AES.MODE_ECB) # never use ECB in strong systems obviously
encoded = base64.b64encode(cipher.encrypt(msg_text))
# ...
decoded = cipher.decrypt(base64.b64decode(encoded))
print decoded.strip()
Se alguém tiver acesso à sua base de dados e à sua base de código, será capaz de descodificar os dados encriptados. Mantém a chave secreta segura!
O" encoded_c "mencionado na resposta cifrada Vigenere de @smehmood deve ser"key_c".
Aqui estão as funções de codificação/descodificação.
import base64
def encode(key, clear):
enc = []
for i in range(len(clear)):
key_c = key[i % len(key)]
enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
enc.append(enc_c)
return base64.urlsafe_b64encode("".join(enc))
def decode(key, enc):
dec = []
enc = base64.urlsafe_b64decode(enc)
for i in range(len(enc)):
key_c = key[i % len(key)]
dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
dec.append(dec_c)
return "".join(dec)
Aqui está uma versão em Python 3 das funções de @qneill ' s Resposta:
import base64
def encode(key, clear):
enc = []
for i in range(len(clear)):
key_c = key[i % len(key)]
enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
enc.append(enc_c)
return base64.urlsafe_b64encode("".join(enc).encode()).decode()
def decode(key, enc):
dec = []
enc = base64.urlsafe_b64decode(enc).decode()
for i in range(len(enc)):
key_c = key[i % len(key)]
dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
dec.append(dec_c)
return "".join(dec)
Os Codificadores/Descodificadores extra são necessários porque o Python 3 dividiu as cadeias de caracteres / bytes em dois conceitos diferentes, e actualizou as suas APIs para reflectir isso..
Como já foi mencionado, a biblioteca PyCrypto contém um conjunto de cifras. A cifra XOR pode ser usada para fazer o trabalho sujo se você não quiser fazê-lo você mesmo:
from Crypto.Cipher import XOR
import base64
def encrypt(key, plaintext):
cipher = XOR.new(key)
return base64.b64encode(cipher.encrypt(plaintext))
def decrypt(key, ciphertext):
cipher = XOR.new(key)
return cipher.decrypt(base64.b64decode(ciphertext))
Mesmo que só forneça segurança mínima, eu recomendaria usar uma chave aleatória sem quaisquer caracteres de espaço (como XOR'ing um carácter ASCII [a-zA-Z] com um espaço que vira o caso).
A cifra funciona da seguinte forma sem ter de mudar o texto simples:
>>> encrypt('notsosecretkey', 'Attack at dawn!')
'LxsAEgwYRQIGRRAKEhdP'
>>> decrypt('notsosecretkey', encrypt('notsosecretkey', 'Attack at dawn!'))
'Attack at dawn!'
Crédito a https://stackoverflow.com/a/2490376/241294 para as funções de codificar/descodificar do base64 (sou uma novata em python).
Aqui está uma implementação de encriptação segura de URL e decriptação usando AES (PyCrypto) e base64.
import base64
from Crypto import Random
from Crypto.Cipher import AES
AKEY = 'mysixteenbytekey' # AES key must be either 16, 24, or 32 bytes long
iv = Random.new().read(AES.block_size)
def encode(message):
obj = AES.new(AKEY, AES.MODE_CFB, iv)
return base64.urlsafe_b64encode(obj.encrypt(message))
def decode(cipher):
obj2 = AES.new(AKEY, AES.MODE_CFB, iv)
return obj2.decrypt(base64.urlsafe_b64decode(cipher))
Se enfrentares um problema destes https://bugs.python.org/issue4329 ( erro tipográfico: o mapeamento de caracteres deve devolver inteiro, nenhum ou unicode ) usar o str (cifra) enquanto descodifica como se segue
Devolve o obj2.decrypt(base64.urlsafe_ b64decode(str (cifra)))
In [13]: encode("Hello World")
Out[13]: b'67jjg-8_RyaJ-28='
In [14]: %timeit encode("Hello World")
100000 loops, best of 3: 13.9 µs per loop
In [15]: decode(b'67jjg-8_RyaJ-28=')
Out[15]: b'Hello World'
In [16]: %timeit decode(b'67jjg-8_RyaJ-28=')
100000 loops, best of 3: 15.2 µs per loop
Funções de codificar/descodificar em python3 (adaptado muito pouco da resposta de qneill):
def encode(key, clear):
enc = []
for i in range(len(clear)):
key_c = key[i % len(key)]
enc_c = (ord(clear[i]) + ord(key_c)) % 256
enc.append(enc_c)
return base64.urlsafe_b64encode(bytes(enc))
def decode(key, enc):
dec = []
enc = base64.urlsafe_b64decode(enc)
for i in range(len(enc)):
key_c = key[i % len(key)]
dec_c = chr((256 + enc[i] - ord(key_c)) % 256)
dec.append(dec_c)
return "".join(dec)
import base64
def qneill_encode(key, clear):
enc = []
for i in range(len(clear)):
key_c = key[i % len(key)]
enc_c = chr((ord(clear[i]) + ord(key_c)) % 256)
enc.append(enc_c)
return base64.urlsafe_b64encode("".join(enc))
def qneill_decode(key, enc):
dec = []
enc = base64.urlsafe_b64decode(enc)
for i in range(len(enc)):
key_c = key[i % len(key)]
dec_c = chr((256 + ord(enc[i]) - ord(key_c)) % 256)
dec.append(dec_c)
return "".join(dec)
enumerate()
-- juntar os itens de uma lista com o seu índiceIterar sobre os caracteres numa cadeia
def encode_enumerate(key, clear):
enc = []
for i, ch in enumerate(clear):
key_c = key[i % len(key)]
enc_c = chr((ord(ch) + ord(key_c)) % 256)
enc.append(enc_c)
return base64.urlsafe_b64encode("".join(enc))
def decode_enumerate(key, enc):
dec = []
enc = base64.urlsafe_b64decode(enc)
for i, ch in enumerate(enc):
key_c = key[i % len(key)]
dec_c = chr((256 + ord(ch) - ord(key_c)) % 256)
dec.append(dec_c)
return "".join(dec)
Construir listas usando uma compreensão de listas
def encode_comprehension(key, clear):
enc = [chr((ord(clear_char) + ord(key[i % len(key)])) % 256)
for i, clear_char in enumerate(clear)]
return base64.urlsafe_b64encode("".join(enc))
def decode_comprehension(key, enc):
enc = base64.urlsafe_b64decode(enc)
dec = [chr((256 + ord(ch) - ord(key[i % len(key)])) % 256)
for i, ch in enumerate(enc)]
return "".join(dec)
Muitas vezes em Python não há necessidade de listar de todo. Eliminar por completo as variáveis do índice do ciclo utilizando o zip e o ciclo:
from itertools import cycle
def encode_zip_cycle(key, clear):
enc = [chr((ord(clear_char) + ord(key_char)) % 256)
for clear_char, key_char in zip(clear, cycle(key))]
return base64.urlsafe_b64encode("".join(enc))
def decode_zip_cycle(key, enc):
enc = base64.urlsafe_b64decode(enc)
dec = [chr((256 + ord(enc_char) - ord(key_char)) % 256)
for enc_char, key_char in zip(enc, cycle(key))]
return "".join(dec)
E alguns testes...
msg = 'The quick brown fox jumps over the lazy dog.'
key = 'jMG6JV3QdtRh3EhCHWUi'
print('cleartext: {0}'.format(msg))
print('ciphertext: {0}'.format(encode_zip_cycle(key, msg)))
encoders = [qneill_encode, encode_enumerate, encode_comprehension, encode_zip_cycle]
decoders = [qneill_decode, decode_enumerate, decode_comprehension, decode_zip_cycle]
# round-trip check for each pair of implementations
matched_pairs = zip(encoders, decoders)
assert all([decode(key, encode(key, msg)) == msg for encode, decode in matched_pairs])
print('Round-trips for encoder-decoder pairs: all tests passed')
# round-trip applying each kind of decode to each kind of encode to prove equivalent
from itertools import product
all_combinations = product(encoders, decoders)
assert all(decode(key, encode(key, msg)) == msg for encode, decode in all_combinations)
print('Each encoder and decoder can be swapped with any other: all tests passed')
>>> python crypt.py
cleartext: The quick brown fox jumps over the lazy dog.
ciphertext: vrWsVrvLnLTPlLTaorzWY67GzYnUwrSmvXaix8nmctybqoivqdHOic68rmQ=
Round-trips for encoder-decoder pairs: all tests passed
Each encoder and decoder can be swapped with any other: all tests passed
Isto funciona, mas o comprimento da senha deve ser exactamente 8
. Isto é simples e requer pides .
from pyDes import *
def encode(data,password):
k = des(password, CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
d = k.encrypt(data)
return d
def decode(data,password):
k = des(password, CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
d = k.decrypt(data)
return d
x = encode('John Doe', 'mypass12')
y = decode(x,'mypass12')
print x
print y
Resultado:
³.\Þ\åS¾+æÅ`;Ê
John Doe
Por exemplo, o Cypher
o módulo em PyCrypto oferece uma selecção de muitos algoritmos de encriptação:
Crypto.Cipher.AES
Crypto.Cipher.ARC2
Crypto.Cipher.ARC4
Crypto.Cipher.Blowfish
Crypto.Cipher.CAST
Crypto.Cipher.DES
Crypto.Cipher.DES3
Crypto.Cipher.IDEA
Crypto.Cipher.RC5
Crypto.Cipher.XOR
O MeTooCrypto é uma embalagem Python
Para o OpenSSL , e fornece (entre outros functions) a full-strength general purpose cryptography library. Incluem-se as cifras simétricas (como AES).
Se quiser encriptação segura:
Para o python 2, deve usar o keyczar http://www.keyczar.org/
Para o python 3, até o keyczar estar disponível, escrevi simple-crypt http://pypi.python.org/pypi/simple-crypt
Ambos irão usar o reforço da chave, o que os torna mais seguros do que a maioria das outras respostas aqui. e como eles são tão fáceis de usar, você pode querer usá-los mesmo quando a segurança não é crítica...
Se queres ser Seguro, podes usar a Fernet, que é criptograficamente sÃ. Você pode usar um "sal" estático se você não quiser armazená - lo separadamente-você só vai perder dicionário e prevenção de ataque arco-íris. Eu escolhi porque eu posso escolher senhas longas ou curtas, o que não é tão fácil com AES.
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
import base64
#set password
password = "mysecretpassword"
#set message
message = "secretmessage"
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt="staticsalt", iterations=100000, backend=default_backend())
key = base64.urlsafe_b64encode(kdf.derive(password))
f = Fernet(key)
#encrypt
encrypted = f.encrypt(message)
print encrypted
#decrypt
decrypted = f.decrypt(encrypted)
print decrypted
Se isso é muito complicado, alguém sugeriu simplecrypt
from simplecrypt import encrypt, decrypt
ciphertext = encrypt('password', plaintext)
plaintext = decrypt('password', ciphertext)
Pode usar o AES para cifrar o seu texto com uma senha. No entanto, você vai querer escolher uma senha forte o suficiente para que as pessoas não podem facilmente adivinhar o que é (desculpe, eu não posso ajudá-lo. Eu sou um aspirante a segurança weenie).
O AES é forte com um bom tamanho de chave, mas também é fácil de usar com o PyCrypto.
Uma outra implementação do Código @qneill que inclui o código CRC da mensagem original, abre uma excepção se a verificação falhar:
import hashlib
import struct
import zlib
def vigenere_encode(text, key):
text = '{}{}'.format(text, struct.pack('i', zlib.crc32(text)))
enc = []
for i in range(len(text)):
key_c = key[i % len(key)]
enc_c = chr((ord(text[i]) + ord(key_c)) % 256)
enc.append(enc_c)
return base64.urlsafe_b64encode("".join(enc))
def vigenere_decode(encoded_text, key):
dec = []
encoded_text = base64.urlsafe_b64decode(encoded_text)
for i in range(len(encoded_text)):
key_c = key[i % len(key)]
dec_c = chr((256 + ord(encoded_text[i]) - ord(key_c)) % 256)
dec.append(dec_c)
dec = "".join(dec)
checksum = dec[-4:]
dec = dec[:-4]
assert zlib.crc32(dec) == struct.unpack('i', checksum)[0], 'Decode Checksum Error'
return dec