Prosty sposób na zakodowanie łańcucha zgodnie z hasłem?

Czy Python ma wbudowany, prosty sposób kodowania / dekodowania ciągów za pomocą hasła?

Coś takiego:

>>> encode('John Doe', password = 'mypass')
'sjkl28cn2sx0'
>>> decode('sjkl28cn2sx0', password = 'mypass')
'John Doe'

Tak więc łańcuch "John Doe" zostaje zaszyfrowany jako 'sjkl28cn2sx0'. Aby uzyskać oryginalny ciąg znaków, chciałbym "odblokować" ten ciąg za pomocą klucza 'mypass' , który jest hasłem w moim kodzie źródłowym. Chciałbym, aby był to sposób, w jaki mogę zaszyfrować/odszyfrować dokument Word za pomocą hasła.

Chciałbym użyć tych zaszyfrowanych łańcuchów jako parametrów URL. Moim celem jest zaciemnienie, brak silnych zabezpieczeń; nic krytycznych dla misji nie jest kodowane. Zdaję sobie sprawę, że mogę użyć tabeli bazy danych do przechowywania kluczy i wartości, ale staram się być minimalistyczny.

Author: RexE, 2010-03-22

15 answers

Zakładając, że jesteś Tylko szukając prostego zaciemnienia, które zasłoniłoby rzeczy z Bardzo przypadkowego obserwatora, i nie chcesz korzystać z bibliotek stron trzecich. Polecam coś takiego jak szyfr Vigenere ' a. Jest to jeden z najsilniejszych prostych starożytnych szyfrów.

Szyfr Vigenère ' a

Jest szybki i łatwy do wdrożenia. Coś w stylu:
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)

Dekodowanie jest prawie takie samo, tyle że odejmujesz klucz.

Jest dużo trudniejsze do złamania, jeśli ciągi, które kodujesz, są krótkie i / lub jeśli trudno jest odgadnąć długość używanego hasła.

Jeśli szukasz czegoś kryptograficznego, PyCrypto jest prawdopodobnie najlepszym rozwiązaniem, choć poprzednie odpowiedzi pomijają pewne szczegóły: Tryb ECB w PyCrypto wymaga, aby Twoja wiadomość była wielokrotnością 16 znaków. Więc musisz padnąć. Ponadto, jeśli chcesz użyć ich jako parametrów URL, użyj base64.urlsafe_b64_encode(), zamiast standardowego. To zastępuje kilka z znaki w alfabecie base64 ze znakami bezpiecznymi dla URL (jak sama nazwa wskazuje).

Jednak, powinieneś być absolutnie pewien, że taBardzo cienka warstwa zaciemnienia wystarcza na twoje potrzeby przed użyciem tego. Artykuł w Wikipedii, do którego podlinkowałem, zawiera szczegółowe instrukcje złamania szyfru, więc każdy z umiarkowaną determinacją może go łatwo złamać.

 45
Author: smehmood,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-30 19:40:36

Ponieważ wyraźnie stwierdzasz, że chcesz zaciemnienia, a nie Bezpieczeństwa, unikniemy nagany za słabość tego, co sugerujesz:)

Więc, używając 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()

Jeśli ktoś zdobędzie twoją bazę danych i bazę kodu, będzie w stanie dekodować zaszyfrowane dane. Keep your secret_key safe!

 52
Author: Will,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-24 02:24:02

"encoded_c" wspomniane w odpowiedzi szyfru Vigenere @smehmood powinno być "key_c".

Tutaj działają funkcje kodowania/dekodowania.

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,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-01 16:07:29

Oto wersja Pythona 3 funkcji z @qneill 'S answer :

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)

Dodatkowe kodowanie / dekodowanie są potrzebne, ponieważ Python 3 podzielił tablice łańcuchów / bajtów na dwie różne koncepcje i zaktualizował swoje API, aby to odzwierciedlić..

 33
Author: Ryan Barrett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:54:18

Jak już wspomniano, Biblioteka PyCrypto zawiera zestaw szyfrów. Szyfr XOR może być użyty do wykonania brudnej roboty, jeśli nie chcesz tego zrobić sam: {]}

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

Mimo że zapewnia tylko minimalne bezpieczeństwo, nadal zalecam użycie losowego klucza bez znaków spacji (ponieważ XOR ' ING znak ASCII [a-zA-z] ze spacją po prostu odwraca sprawę).

Szyfr działa w następujący sposób bez konieczności umieszczania zwykłego tekstu:

>>> encrypt('notsosecretkey', 'Attack at dawn!')
'LxsAEgwYRQIGRRAKEhdP'

>>> decrypt('notsosecretkey', encrypt('notsosecretkey', 'Attack at dawn!'))
'Attack at dawn!'

Kredyt na https://stackoverflow.com/a/2490376/241294 dla funkcji kodowania/dekodowania base64 (Jestem początkującym Pythonem).

 23
Author: poida,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:46:24

Oto implementacja bezpiecznego szyfrowania i deszyfrowania URL przy użyciu AES (PyCrypto) i 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))

Jeśli napotkasz jakiś problem jak ten https://bugs.python.org/issue4329 (TypeError: mapowanie znaków musi zwracać liczbę całkowitą, None lub unicode ) użyj str (cipher) podczas dekodowania w następujący sposób

Return obj2.decrypt (base64.urlsafe_b64decode(str (cipher)))

    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,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-05 09:29:41

Działające funkcje kodowania/dekodowania w python3 (zaadaptowane bardzo niewiele z odpowiedzi qneilla):

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,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-15 01:51:49

Dzięki za świetne odpowiedzi. Nic oryginalnego do dodania, ale oto kilka progresywnych przepisań odpowiedzi qneill za pomocą przydatnych funkcji Pythona. Mam nadzieję, że zgadzasz się z tym, że upraszczają i wyjaśniają Kodeks.

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()-- sparuj elementy na liście z ich indeksem

Iteracja nad znakami w łańcuchu

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)

Tworzenie list za pomocą rozumienia list

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)

Często w Pythonie nie ma potrzeby indeksowania list w wszystkie. Wyeliminowanie zmiennych indeksu pętli całkowicie za pomocą zip i cycle:

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)
I kilka testów...
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,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-24 22:21:15

To działa, ale długość hasła powinna być dokładnie 8. Jest to proste i wymaga pyDes .

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

Wyjście:

³.\Þ\åS¾+æÅ`;Ê
John Doe
 1
Author: Pratik Deoghare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-22 07:28:55

Prosty sposób polega na użyciu biblioteki, a PyCrypto jest tym dobrym.

 0
Author: YOU,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-22 06:27:09

Zewnętrzne biblioteki zapewniają algorytmy szyfrowania klucza tajnego.

Na przykład Cypher moduł PyCrypto oferuje wybór wielu algorytmów szyfrowania:

  • 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

MeTooCrypto jest opakowaniem Python dla OpenSSL i zapewnia (między innymi funkcje) pełnowymiarowa biblioteka kryptografii ogólnego przeznaczenia. W zestawie znajdują się szyfry symetryczne (jak AES).

 0
Author: gimel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-03-22 06:47:53

Jeśli chcesz Bezpieczne szyfrowanie:

Dla Pythona 2, powinieneś użyć keyczar http://www.keyczar.org/

Dla Pythona 3, dopóki keyczar nie będzie dostępny, napisałem simple-crypt http://pypi.python.org/pypi/simple-crypt

Oba te będą używać wzmocnienia klucza, co czyni je bezpieczniejszymi niż większość innych odpowiedzi tutaj. a ponieważ są one tak łatwe w użyciu, możesz chcieć ich używać nawet wtedy, gdy bezpieczeństwo nie ma krytycznego znaczenia...

 0
Author: andrew cooke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-01-03 13:35:53

/ Align = "center" bgcolor = "# e0ffe0 " / cesarz Chin / / align = center / Możesz użyć statycznej "soli", jeśli nie chcesz jej przechowywać osobno - stracisz tylko słownik i zapobieganie atakom rainbow. Wybrałem go, ponieważ mogę wybrać długie lub krótkie hasła, co nie jest takie łatwe z 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

Jeśli to zbyt skomplikowane, ktoś zasugerował simplecrypt

from simplecrypt import encrypt, decrypt
ciphertext = encrypt('password', plaintext)
plaintext = decrypt('password', ciphertext)
 0
Author: HCLivess,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-10 16:10:44

Możesz użyć AES do zaszyfrowania łańcucha za pomocą hasła. Jednak będziesz chciał wybrać wystarczająco silne hasło, aby ludzie nie mogli łatwo zgadnąć, co to jest (przykro mi, że nic na to nie poradzę. I ' m a wannabe security weenie).

AES jest mocny z dobrym rozmiarem klucza, ale jest również łatwy w użyciu z PyCrypto.

 0
Author: Alan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-26 16:13:50

Inna implementacja kodu @ qneill, która zawiera sumę kontrolną CRC oryginalnej wiadomości, rzuca wyjątek, jeśli sprawdzenie się nie powiedzie:

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,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-28 13:51:30