Простой способ кодирования строки в соответствии с паролем?



есть ли у Python встроенный простой способ кодирования / декодирования строк с помощью пароля?



что-то вроде этого:



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


таким образом, строка "John Doe" шифруется как 'sjkl28cn2sx0'. Чтобы получить исходную строку, я бы "разблокировать" эту строку с ключом "mypass", который является паролем в моем исходном коде. Я бы хотел, чтобы это было так, как я могу зашифровать/расшифровать документ Word с паролем.



Я хотел бы использовать эти зашифрованные строки в URL-адрес параметры. Моя цель-запутывание, а не сильная безопасность; ничего критически важного не кодируется. Я понимаю, что могу использовать таблицу базы данных для хранения ключей и значений, но пытаюсь быть минималистичным.

683   15  

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.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 это 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

    Ничего не найдено.