Простой способ кодировать строку в соответствии с паролем? - PullRequest
105 голосов
/ 22 марта 2010

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

Примерно так:

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

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

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

Ответы [ 18 ]

3 голосов
/ 13 марта 2019

Примечание: у меня были проблемы с использованием Windows + Python 3.6 + все ответы, включающие pycrypto (не удалось pip install pycrypto в Windows) или pycryptodome (ответы здесь с from Crypto.Cipher import XOR не удалось, потому что XOR поддерживается этой pycrypto вилкой, и решения, использующие ... AES, тоже не сработали с TypeError: Object type <class 'str'> cannot be passed to C code). Кроме того, библиотека simple-crypt имеет pycrypto в качестве зависимости, поэтому это не вариант.


Вот решение с использованием пакета cryptography, которое вы можете установить как обычно с помощью pip install cryptography:

import base64
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

def encrypt(plaintext, password):
    f = Fernet(base64.urlsafe_b64encode(PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=b'abcd', iterations=1000, backend=default_backend()).derive(password.encode())))
    return f.encrypt(plaintext.encode()).decode()

def decrypt(ciphertext, password):
    f = Fernet(base64.urlsafe_b64encode(PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=b'abcd', iterations=1000, backend=default_backend()).derive(password.encode())))
    return f.decrypt(ciphertext.encode()).decode()

Использование:

>>> encrypt('John Doe', password='mypass')
'gAAAAABciC64VNUoeLVoPKut7HxlPcsqJZTFf99EMYTmnR9jFkZBNMxklIDc5WZ6k3TxfcFSDO-4PRZUsOvywtGLSFwOzToO_g=='

>>> decrypt('gAAAAABciC64VNUoeLVoPKut7HxlPcsqJZTFf99EMYTmnR9jFkZBNMxklIDc5WZ6k3TxfcFSDO-4PRZUsOvywtGLSFwOzToO_g==', password='mypass')
'John Doe'

Примечание:

  • вы можете адаптировать свою собственную соль, количество итераций и т. Д.

  • не очень далеко от ответа @ HCLivess, но цель в том, чтобы иметь готовые к использованию функции encrypt и decrypt

  • Источник: https://cryptography.io/en/latest/fernet/#using-passwords-with-fernet

2 голосов
/ 22 марта 2010

Это работает, но длина пароля должна быть точно 8. Это просто и требует 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

ВЫВОД:

³.\Þ\åS¾+æÅ`;Ê
John Doe
2 голосов
/ 28 июня 2016

Другая реализация кода @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
2 голосов
/ 22 марта 2010

Вы можете использовать AES для шифрования вашей строки с помощью пароля. Тем не менее, вы захотите выбрать достаточно надежный пароль, чтобы люди не могли легко догадаться, что это такое (извините, я не могу с этим поделать. Я подонок по безопасности).

AES обладает хорошим размером ключа, но его также легко использовать с PyCrypto.

1 голос
/ 22 марта 2010

Внешние библиотеки предоставляют алгоритмы шифрования с секретным ключом.

Например, модуль 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).

1 голос
/ 14 марта 2019

Кто бы ни пришел сюда (и баунтер), казалось, искал однострочники без особых настроек, которые другие ответы не дают.Итак, я выдвигаю base64.

Теперь, имейте в виду, что это только базовая запутанность, и она находится в ** НЕТ ПУТИ ДЛЯ БЕЗОПАСНОСТИ **, но вот некоторые-liners:

from base64 import urlsafe_b64encode, urlsafe_b64decode

def encode(data, key):
    return urlsafe_b64encode(bytes(key+data, 'utf-8'))

def decode(enc, key):
    return urlsafe_b64decode(enc)[len(key):].decode('utf-8')

print(encode('hi', 'there')) # b'dGhlcmVoaQ=='
print(decode(encode('hi', 'there'), 'there')) # 'hi'

Несколько замечаний:

  • вы захотите иметь дело с более / менее кодированием / декодированием байтов в строку самостоятельно, в зависимости отваш ввод / вывод.Посмотрите на bytes() и bytes::decode()
  • base64, легко узнаваемый по типам используемых символов и часто заканчивающийся = символами.Такие люди, как я, абсолютно безразлично декодируют их в консоли javascript, когда мы видим их на веб-сайтах.Это так же просто, как btoa(string) (js)
  • порядок - ключ + данные, как в b64, какие символы появляются в конце, зависит от того, какие символы находятся в начале (из-за смещения байтов. Википедия имеет несколько хороших объяснений).В этом случае начало закодированной строки будет одинаковым для всего, что закодировано этим ключом.Плюс в том, что данные будут более запутанными.Если сделать это наоборот, то часть данных будет одинаковой для всех, независимо от ключа.

Теперь, если для того, что вы хотели, даже не нужен какой-либо ключ, нопросто немного запутывания, вы можете снова использовать base64, без каких-либо ключей:

from base64 import urlsafe_b64encode, urlsafe_b64decode

def encode(data):
    return urlsafe_b64encode(bytes(data, 'utf-8'))

def decode(enc):
    return urlsafe_b64decode(enc).decode()

print(encode('hi')) # b'aGk='
print(decode(encode('hi'))) # 'hi'
0 голосов
/ 19 марта 2019

Итак, поскольку ничего критически важного не кодируется , и вы просто хотите зашифровать для обфускация .

Позвольте мне представить шифр Цезера

enter image description here

Шифр ​​Цезаря, или Цезарь, является одним из самых простых и широко известных методов шифрования. Это тип шифра замещения, в котором каждая буква в открытом тексте заменяется буквой с фиксированным числом позиций по алфавиту. Например, при сдвиге влево на 3 D будет заменен на A, E станет B и т. Д.

Пример кода для вашей справки:

def encrypt(text,s): 
        result = "" 

        # traverse text 
        for i in range(len(text)): 
            char = text[i] 

            # Encrypt uppercase characters 
            if (char.isupper()): 
                result += chr((ord(char) + s-65) % 26 + 65) 

            # Encrypt lowercase characters 
            else: 
                result += chr((ord(char) + s - 97) % 26 + 97) 

        return result 

    def decrypt(text,s): 
        result = "" 

        # traverse text 
        for i in range(len(text)): 
            char = text[i] 

            # Encrypt uppercase characters 
            if (char.isupper()): 
                result += chr((ord(char) - s-65) % 26 + 65) 

            # Encrypt lowercase characters 
            else: 
                result += chr((ord(char) - s - 97) % 26 + 97) 

        return result 

    #check the above function 
    text = "ATTACKATONCE"
    s = 4
    print("Text  : " + text) 
    print("Shift : " + str(s)) 
    print("Cipher: " + encrypt(text,s))
    print("Original text: " + decrypt(encrypt(text,s),s))

Преимущества: он отвечает вашим требованиям, прост и выполняет кодировку 'y'.

Недостаток: может быть взломан простыми алгоритмами перебора (очень маловероятно, что кто-либо попытается пройти через все дополнительные результаты).

0 голосов
/ 03 января 2013

, если вы хотите безопасное шифрование:

для Python 2, вы должны использовать keyczar http://www.keyczar.org/

для Python 3, пока не доступен keyczar, я написал simple-crypt http://pypi.python.org/pypi/simple-crypt

оба они будут использовать усиление клавиш, что делает их более безопасными, чем большинство других ответов здесь. и так как они так просты в использовании, вы можете использовать их, даже если безопасность не критична ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...