Простой способ кодирования строки в соответствии с паролем?
есть ли у Python встроенный простой способ кодирования / декодирования строк с помощью пароля?
что-то вроде этого:
>>> encode('John Doe', password = 'mypass')
'sjkl28cn2sx0'
>>> decode('sjkl28cn2sx0', password = 'mypass')
'John Doe'
таким образом, строка "John Doe" шифруется как 'sjkl28cn2sx0'. Чтобы получить исходную строку, я бы "разблокировать" эту строку с ключом "mypass", который является паролем в моем исходном коде. Я бы хотел, чтобы это было так, как я могу зашифровать/расшифровать документ Word с паролем.
Я хотел бы использовать эти зашифрованные строки в URL-адрес параметры. Моя цель-запутывание, а не сильная безопасность; ничего критически важного не кодируется. Я понимаю, что могу использовать таблицу базы данных для хранения ключей и значений, но пытаюсь быть минималистичным.
15 ответов:
Если вы только ищет простой обфускации, которые будут скрывать вещи от очень стороннего наблюдателя, и вы не хотите использовать сторонние библиотеки. Я бы порекомендовал что-то вроде шифра Вигенера. Это один из самых сильных простых древних шифров.
это быстро и легко осуществить. Что-то вроде:
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)декодировать в значительной степени то же самое, за исключением вас вычтите ключ.
гораздо сложнее сломать, если строки, которые вы кодируете, короткие, и/или если трудно угадать длину используемой парольной фразы.
Если вы ищете что-то криптографическое, PyCrypto, вероятно, ваш лучший выбор, хотя предыдущие ответы упускают некоторые детали: режим ECB в PyCrypto требует, чтобы ваше сообщение было кратным 16 символам в длину. Итак,вы должны прокладывать. Кроме того, если вы хотите использовать их в качестве параметров URL, используйте
base64.urlsafe_b64_encode(), а чем стандартный один. Это заменяет несколько символов в алфавите base64 символами URL-safe (как следует из названия).однако, вы должны быть абсолютно уверены, что это очень тонкий слой обфускации достаточно для ваших потребностей перед использованием этого. Статья в Википедии, на которую я ссылался, содержит подробные инструкции по взлому шифра, поэтому любой человек с умеренным количеством решимости может легко его сломать.
поскольку вы явно заявляете, что хотите неизвестности, а не Безопасности, мы не будем выговаривать вам за слабость того, что вы предлагаете:)
Итак, используя 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()Если кто-то завладеет вашей базой данных и вашей базой кода, они смогут декодировать зашифрованные данные. Держите ваш secret_key в безопасности!
" encoded_c", упомянутый в ответе шифра Vigenere @smehmood, должен быть"key_c".
здесь работают функции кодирования / декодирования.
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)
вот версия Python 3 функций из @qneill ' s ответ:
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)дополнительное кодирование / декодирование необходимо, потому что Python 3 разделил строки/байтовые массивы на две разные концепции и обновил их API, чтобы отразить это..
Как уже упоминалось библиотека PyCrypto содержит набор шифров. Шифр XOR может быть использован для выполнения грязной работы, если вы не хотите делать это самостоятельно:
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))несмотря на то, что он обеспечивает минимальную безопасность, я все равно рекомендую использовать случайный ключ без пробелов (поскольку XOR'ING символ ASCII [a-zA-Z] с пробелом просто переворачивает дело).
шифр работает следующим образом без необходимости прокладывать открытый текст:
>>> encrypt('notsosecretkey', 'Attack at dawn!') 'LxsAEgwYRQIGRRAKEhdP' >>> decrypt('notsosecretkey', encrypt('notsosecretkey', 'Attack at dawn!')) 'Attack at dawn!'кредит на https://stackoverflow.com/a/2490376/241294 для функций кодирования/декодирования base64 (я новичок в python).
вот реализация безопасного шифрования и дешифрования URL с использованием AES (PyCrypto) и 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))Если вы столкнулись с какой-то проблемой, как это https://bugs.python.org/issue4329 ( TypeError: сопоставление символов должно возвращать целое число, None или unicode ) используйте str (шифр) при декодировании следующим образом
вернуться obj2.расшифровать(в base64.urlsafe_b64decode(str (шифр)))
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
рабочие функции кодирования / декодирования в python3 (адаптированы очень мало из ответа 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)
Спасибо за некоторые хорошие ответы. Ничего оригинального добавить, но вот некоторые прогрессивные перезаписи ответа qneill с использованием некоторых полезных средств Python. Надеюсь, вы согласитесь, что они упрощают и уточняют код.
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()-- сопряжение элементов в списке с их индексомперебирать символы в строке
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)создание списков с помощью списка понимания
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)часто в Python нет необходимости в индексах списка вообще. Полностью исключите переменные индекса цикла, используя zip и 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)и некоторые тесты...
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
это работает, но длина пароля должна быть точно
8. Это просто и требует pyDes.from pyDes import * def encode(data,password): k = des(password, CBC, "", pad=None, padmode=PAD_PKCS5) d = k.encrypt(data) return d def decode(data,password): k = des(password, CBC, "", pad=None, padmode=PAD_PKCS5) d = k.decrypt(data) return d x = encode('John Doe', 'mypass12') y = decode(x,'mypass12') print x print yвыход:
³.\Þ\åS¾+æÅ`;Ê John Doe
простой способ-это использование библиотеки, и PyCrypto - это хорошо.
внешние библиотеки предоставляют алгоритмы шифрования с секретным ключом.
например,
Cypherмодуль в PyCrypto предлагает выбор из многих шифрования алгоритмы:
Crypto.Cipher.AESCrypto.Cipher.ARC2Crypto.Cipher.ARC4Crypto.Cipher.BlowfishCrypto.Cipher.CASTCrypto.Cipher.DESCrypto.Cipher.DES3Crypto.Cipher.IDEACrypto.Cipher.RC5Crypto.Cipher.XORMeTooCrypto это
Pythonобертка для OpenSSL, и обеспечивает (среди других функций) полнофункциональную библиотеку криптографии общего назначения. Включены симметричные шифры (например, AES).
Если вы хотите безопасное шифрование:
для python 2, вы должны использовать keyczar http://www.keyczar.org/
для python 3, пока keyczar не доступен, я написал simple-crypt http://pypi.python.org/pypi/simple-crypt
Как это использовать ключ активизации, что делает их более безопасными, чем большинство других ответов здесь. и поскольку они настолько просты в использовании, вы можете использовать их, даже если безопасность не является критический...
Если вы хотите быть в безопасности, вы можете использовать Fernet, который является криптографически звук. Вы можете использовать статическую "соль", если вы не хотите хранить ее отдельно - вы потеряете только словарь и предотвращение атаки радуги. Я выбрал его, потому что я могу выбрать длинные или короткие пароли, что не так просто с 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Если это слишком сложно, кто-то предложил simplecrypt
from simplecrypt import encrypt, decrypt ciphertext = encrypt('password', plaintext) plaintext = decrypt('password', ciphertext)
вы можете использовать AES для шифрования строки с паролем. Хотя, вы захотите выбрать достаточно сильный пароль, чтобы люди не могли легко догадаться, что это такое (извините, я не могу помочь. Я подражатель безопасности weenie).
AES является сильным с хорошим размером ключа, но он также прост в использовании с PyCrypto.
другая реализация кода @qneill, которая включает контрольную сумму CRC исходного сообщения, вызывает исключение, если проверка не выполняется:
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
Comments