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.

Author: RexE, 2010-03-22

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.

Cifra de Vigenère

É 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).

No entanto, deve ter a certeza absoluta de que esta camada fina de ofuscação é suficiente para as suas necessidades antes de usar isto. O Artigo da Wikipedia I ligado fornece instruções detalhadas para quebrar a cifra, então qualquer um com uma quantidade moderada de determinação poderia facilmente quebrá-la.
 45
Author: smehmood, 2017-11-30 19:40:36
Como afirma explicitamente que quer obscuridade e não Segurança, evitaremos repreendê-lo pela fraqueza do que 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!
 52
Author: Will, 2015-06-24 02:24:02

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)
 40
Author: qneill, 2013-05-01 16:07:29

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..

 33
Author: Ryan Barrett, 2017-05-23 11:54:18

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).

 23
Author: poida, 2017-05-23 11:46:24

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
 7
Author: All Іѕ Vаиітy, 2018-06-05 09:29:41

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)
 5
Author: Christian, 2016-03-15 01:51:49
Obrigado por algumas boas respostas. Nada original para adicionar, mas aqui estão algumas reescritas progressivas da resposta do qneill usando algumas instalações Python úteis. Espero que concordem que simplificam e clarificam o código.
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 índice

Iterar 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
 2
Author: Nick, 2017-10-24 22:21:15

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
 1
Author: Pratik Deoghare, 2010-03-22 07:28:55

A maneira simples é usar a biblioteca, e PyCrypto é a boa.

 0
Author: YOU, 2010-03-22 06:27:09
As bibliotecas externas fornecem algoritmos de encriptação de chave secreta.

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).

 0
Author: gimel, 2010-03-22 06:47:53

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...

 0
Author: andrew cooke, 2013-01-03 13:35:53

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)
 0
Author: HCLivess, 2017-01-10 16:10:44

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.

 0
Author: Alan, 2018-01-26 16:13:50

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
 -1
Author: ahmed, 2016-06-28 13:51:30