encriptar - Cifrar/descifrar datos en python con sal
como desencriptar un codigo en python (2)
Básicamente, me gustaría saber cómo puedo cifrar los datos con una clave Salt generada y luego descifrarlos usando Python.
He revisado muchos sitios web y módulos, y todos se ven muy bien en la parte de cifrado, pero ninguno puede descifrar lo que parece.
Mi principal preocupación es tener una clave de sal fuerte, que probablemente se genere en cientos de veces, y luego usar esa clave para cifrar los datos; en particular, estoy investigando el cifrado de datos codificados en JSON con la clave de sal, enviando los datos cifrados a del otro lado (escuchar cliente) y luego descifrar los datos allí en función del algoritmo que se utiliza para generar la clave de sal.
Descubrí que el módulo mcrypt funcionaría mejor con esto, pero no hay mucha documentación para el módulo python-mcrypt (que actualmente está desactualizado y no se mantiene).
La respuesta breve a su pregunta es que usted combina la contraseña y el salt y los mezcla repetidamente para crear su clave. Luego agrega la sal al texto cifrado para que pueda generar la clave para el descifrado. Para asegurarme de tener la respuesta correcta, hice algunas funciones para hacer el trabajo. Se dan a continuación.
En mi respuesta, he hecho uso de pycrypto, por lo que necesitamos importar algunas de esas bibliotecas.
import Crypto.Random
from Crypto.Cipher import AES
import hashlib
Para facilitar la lectura, he definido algunas constantes que usaré más adelante.
# salt size in bytes
SALT_SIZE = 16
# number of iterations in the key generation
NUMBER_OF_ITERATIONS = 20
# the size multiple required for AES
AES_MULTIPLE = 16
Para usar un salt, he hecho un esquema de cifrado basado en contraseña. He utilizado el estándar RSA PKCS # 5 para la generación de claves de cifrado basadas en contraseña y el relleno, adaptado para el algoritmo de cifrado AES.
Para generar la clave, la contraseña y el salt se concatenan. Esta combinación es hash tantas veces como sea requerido.
def generate_key(password, salt, iterations):
assert iterations > 0
key = password + salt
for i in range(iterations):
key = hashlib.sha256(key).digest()
return key
Para rellenar el texto, calcula cuántos bytes adicionales tienes más allá de un múltiplo par de 16. Si es 0, agregas 16 bytes de relleno, si es 1, agregas 15, etc. De esta manera siempre agregas relleno . El carácter con el que se rellena es el que tiene el mismo valor que el número de bytes de relleno ( chr(padding_size)
), para facilitar la eliminación del relleno al final ( ord(padded_text[-1])
).
def pad_text(text, multiple):
extra_bytes = len(text) % multiple
padding_size = multiple - extra_bytes
padding = chr(padding_size) * padding_size
padded_text = text + padding
return padded_text
def unpad_text(padded_text):
padding_size = ord(padded_text[-1])
text = padded_text[:-padding_size]
return text
El cifrado requiere generar un salt aleatorio y usarlo junto con la contraseña para generar la clave de cifrado. El texto se rellena con la función pad_text
anterior y luego se cifra con un objeto de cifrado. El texto cifrado y la sal se concatenan y se devuelven como resultado. Si desea enviarlo como texto sin formato, deberá codificarlo con base64.
def encrypt(plaintext, password):
salt = Crypto.Random.get_random_bytes(SALT_SIZE)
key = generate_key(password, salt, NUMBER_OF_ITERATIONS)
cipher = AES.new(key, AES.MODE_ECB)
padded_plaintext = pad_text(plaintext, AES_MULTIPLE)
ciphertext = cipher.encrypt(padded_plaintext)
ciphertext_with_salt = salt + ciphertext
return ciphertext_with_salt
El descifrado continúa hacia atrás, extrayendo la sal del texto cifrado y usándolo para descifrar el resto del texto cifrado. Luego, el texto sin formato se unpad_text
usando unpad_text
.
def decrypt(ciphertext, password):
salt = ciphertext[0:SALT_SIZE]
ciphertext_sans_salt = ciphertext[SALT_SIZE:]
key = generate_key(password, salt, NUMBER_OF_ITERATIONS)
cipher = AES.new(key, AES.MODE_ECB)
padded_plaintext = cipher.decrypt(ciphertext_sans_salt)
plaintext = unpad_text(padded_plaintext)
return plaintext
Déjame saber si tienes alguna otra pregunta / aclaración.
No necesitas nada más que RNCryptor :
import rncryptor data = ''...'' password = ''...'' # rncryptor.RNCryptor''s methods cryptor = rncryptor.RNCryptor() encrypted_data = cryptor.encrypt(data, password) decrypted_data = cryptor.decrypt(encrypted_data, password) assert data == decrypted_data # rncryptor''s functions encrypted_data = rncryptor.encrypt(data, password) decrypted_data = rncryptor.decrypt(encrypted_data, password) assert data == decrypted_data
Proporciona cifrado semánticamente seguro (sal aleatoria y IV para cada cifrado) e incluye verificación de integridad segura (el texto cifrado no puede ser manipulado sin darse cuenta) a través de HMAC.
RNCryptor también tiene un formato de datos específico para que no tenga que pensar en eso e implementaciones en muchos idiomas .