182 votes

Comment encoder une chaîne de caractères en fonction d'un mot de passe ?

Python dispose-t-il d'un moyen simple et intégré d'encoder/décoder des chaînes de caractères à l'aide d'un mot de passe ?

Algo así:

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

Ainsi, la chaîne "John Doe" est cryptée sous la forme "sjkl28cn2sx0". Pour obtenir la chaîne originale, je dois la "déverrouiller" avec la clé "mypass", qui est un mot de passe dans mon code source. J'aimerais que ce soit la façon dont je peux crypter/décrypter un document Word avec un mot de passe.

J'aimerais utiliser ces chaînes cryptées comme paramètres d'URL. Mon objectif est l'obscurcissement, pas une sécurité forte ; rien de critique n'est codé. Je sais que je pourrais utiliser une table de base de données pour stocker les clés et les valeurs, mais j'essaie d'être minimaliste.

29voto

poida Points 425

Avis de non-responsabilité : Comme indiqué dans les commentaires, cette ne doit pas être utilisé pour protéger les données dans une application réelle.

Quel est le problème avec le cryptage XOR ?

https://crypto.stackexchange.com/questions/56281/breaking-a-xor-cipher-of-known-key-length

https://github.com/hellman/xortool


Comme cela a été mentionné, la bibliothèque PyCrypto contient une suite de chiffrements. Le "cipher" XOR peut être utilisé pour faire le sale boulot si vous ne voulez pas le faire vous-même :

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

Le chiffrement fonctionne de la manière suivante sans qu'il soit nécessaire de remplir le texte en clair :

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

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

Crédit à https://stackoverflow.com/a/2490376/241294 pour les fonctions d'encodage/décodage base64 (je suis un débutant en python).

13voto

Marty Points 1097

Voici une implémentation de l'encryptage et du décryptage URL Safe utilisant AES (PyCrypto) et base64.

import base64
from Crypto import Random
from Crypto.Cipher import AES

AKEY = b'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))

Si vous rencontrez un problème de ce type https://bugs.python.org/issue4329 ( TypeError: character mapping must return integer, None or unicode ) utiliser str(cipher) tout en décodant comme suit :

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

Test :

In [13]: encode(b"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

11voto

gdavid7 Points 71

La bibliothèque cryptocode fournit un moyen simple d'encoder et de décoder des chaînes de caractères avec un mot de passe. Voici comment l'installer :

pip install cryptocode

Cryptage d'un message (exemple de code) :

import cryptocode

encoded = cryptocode.encrypt("mystring","mypassword")
## And then to decode it:
decoded = cryptocode.decrypt(encoded, "mypassword")

La documentation est disponible aquí

9voto

Christian Points 91

Fonctions d'encodage/décodage en python3 (adapté très légèrement de la réponse 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)

8voto

user80836 Points 1

Merci pour ces excellentes réponses. Je n'ai rien d'original à ajouter, mais voici quelques réécritures progressives de la réponse de qneill en utilisant des fonctions utiles de Python. J'espère que vous conviendrez qu'elles simplifient et clarifient le code.

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() -- associe les éléments d'une liste à leur index

itérer sur les caractères d'une chaîne de caractères

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)

construire des listes à l'aide d'une compréhension de liste

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)

Souvent, en Python, il n'est pas nécessaire d'utiliser des index de liste. Éliminez complètement les variables d'index de boucle en utilisant zip et 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)

et quelques tests...

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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X