Para proteger los datos de manera segura en Python, un cifrado efectivo es esencial. En este artículo, explicamos en detalle cómo utilizar la poderosa biblioteca de cifrado de Python, cryptography, cubriendo desde métodos básicos hasta ejemplos más avanzados. La explicación es paso a paso para facilitar su comprensión, incluso para principiantes, y a través de ejemplos prácticos y ejercicios, obtendrás una comprensión más profunda de cómo utilizarla en proyectos reales. A lo largo de este artículo, aprenderás los fundamentos de la seguridad de los datos y adquirirás habilidades prácticas.
Método de instalación de la biblioteca cryptography
El primer paso para realizar cifrado en Python es instalar la biblioteca cryptography. Puedes instalarla fácilmente siguiendo los pasos a continuación.
Preparación del entorno
Asegúrate de que Python esté instalado y de que la herramienta de gestión de paquetes necesaria (pip) también esté instalada.
Verificar la instalación de Python
Ejecuta el siguiente comando en la terminal o el símbolo del sistema para verificar si Python está instalado:
python --version
Verificar la instalación de pip
Para verificar si pip está instalado, ejecuta el siguiente comando:
pip --version
Instalar la biblioteca cryptography
Usa pip para instalar la biblioteca cryptography. Ejecuta el siguiente comando en la terminal o el símbolo del sistema:
pip install cryptography
Verificación de la instalación
Para verificar que la instalación fue exitosa, abre el intérprete de Python y ejecuta el siguiente comando:
import cryptography
print(cryptography.__version__)
Si la instalación fue correcta, se mostrará el número de la versión. Ahora la instalación de la biblioteca cryptography está completa.
Conceptos básicos del cifrado simétrico
El cifrado simétrico utiliza la misma clave para cifrar y descifrar los datos. A continuación, presentamos cómo usar el cifrado simétrico básico con la biblioteca cryptography.
¿Qué es el cifrado simétrico?
El cifrado simétrico utiliza una sola clave para cifrar los datos y la misma clave para descifrar. Por lo tanto, la gestión de claves es muy importante. Un ejemplo de cifrado simétrico es AES (Advanced Encryption Standard).
Cifrado y descifrado con AES
A continuación se explica cómo cifrar y descifrar datos utilizando AES.
Importar los módulos necesarios
Primero, importamos los módulos necesarios desde la biblioteca cryptography.
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
import os
Generación de la clave y el vector de inicialización
Para el cifrado AES, necesitamos generar una clave y un vector de inicialización (IV).
key = os.urandom(32) # Clave de 256 bits
iv = os.urandom(16) # Vector de inicialización de 128 bits
Relleno de datos
En el cifrado por bloques, los datos deben ser múltiplos del tamaño del bloque. Añadimos relleno a los datos si es necesario.
def pad(data):
padder = padding.PKCS7(algorithms.AES.block_size).padder()
return padder.update(data) + padder.finalize()
Cifrado
Ahora ciframos los datos.
def encrypt(data, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()
padded_data = pad(data)
return encryptor.update(padded_data) + encryptor.finalize()
Descifrado
Ahora, desciframos los datos cifrados.
def decrypt(encrypted_data, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
padded_data = decryptor.update(encrypted_data) + decryptor.finalize()
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
return unpadder.update(padded_data) + unpadder.finalize()
Ejemplo práctico
El siguiente ejemplo muestra cómo cifrar datos en texto claro y luego descifrarlos para devolverlos a su forma original.
data = b"Este es un mensaje secreto"
encrypted_data = encrypt(data, key, iv)
print("Datos cifrados:", encrypted_data)
decrypted_data = decrypt(encrypted_data, key, iv)
print("Datos descifrados:", decrypted_data.decode())
De esta manera, puedes implementar cifrado simétrico usando la biblioteca cryptography y proteger tus datos.
Conceptos básicos del cifrado asimétrico
El cifrado asimétrico utiliza claves diferentes para cifrar y descifrar los datos. A continuación, explicamos cómo usar el cifrado asimétrico con la biblioteca cryptography.
¿Qué es el cifrado asimétrico?
El cifrado asimétrico utiliza un par de claves, una pública y una privada. Los datos cifrados con la clave pública solo pueden ser descifrados con la clave privada correspondiente. Este método se utiliza ampliamente para la transmisión segura de datos. Un ejemplo común es RSA (Rivest-Shamir-Adleman).
Cifrado y descifrado con RSA
A continuación, explicamos los pasos básicos para cifrar y descifrar datos utilizando RSA.
Importar los módulos necesarios
Primero, importamos los módulos necesarios de la biblioteca cryptography.
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
Generación de pares de claves
Generamos un par de claves (privada y pública) para la criptografía RSA.
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
Guardar y cargar claves
A continuación, mostramos cómo guardar y cargar las claves generadas.
# Guardar la clave privada
private_pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
)
# Guardar la clave pública
public_pem = public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)
# Cargar claves
loaded_private_key = serialization.load_pem_private_key(private_pem, password=None)
loaded_public_key = serialization.load_pem_public_key(public_pem)
Cifrado
Utilizamos la clave pública para cifrar los datos.
def encrypt(data, public_key):
return public_key.encrypt(
data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Descifrado
Utilizamos la clave privada para descifrar los datos cifrados.
def decrypt(encrypted_data, private_key):
return private_key.decrypt(
encrypted_data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Ejemplo práctico
El siguiente ejemplo muestra cómo cifrar datos en texto claro y luego descifrarlos usando claves pública y privada.
data = b"Este es un mensaje secreto"
encrypted_data = encrypt(data, public_key)
print("Datos cifrados:", encrypted_data)
decrypted_data = decrypt(encrypted_data, private_key)
print("Datos descifrados:", decrypted_data.decode())
De esta manera, puedes implementar cifrado asimétrico usando la biblioteca cryptography para lograr una comunicación de datos segura.
Conceptos básicos de hashing
El hashing es un proceso mediante el cual los datos se convierten en un valor de longitud fija. Los valores hash son unidireccionales, lo que significa que no pueden revertirse a sus datos originales. A continuación, explicamos cómo usar hashing con la biblioteca cryptography.
¿Qué es el hashing?
El hashing se utiliza para verificar la integridad de los datos y para almacenar contraseñas. Un algoritmo de hashing común es SHA-256 (Secure Hash Algorithm 256-bit).
Hashing con SHA-256
A continuación, explicamos cómo realizar un hash de datos usando SHA-256.
Importar los módulos necesarios
Primero, importamos los módulos necesarios de la biblioteca cryptography.
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.backends import default_backend
Hashing de datos
Ahora realizamos el hash de los datos utilizando el algoritmo SHA-256.
def hash_data(data):
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
digest.update(data)
return digest.finalize()
Ejemplo práctico
El siguiente ejemplo muestra cómo hacer hash de datos en texto claro y mostrar el resultado.
data = b"Este es un dato para hacer hash"
hashed_data = hash_data(data)
print("Datos hash:", hashed_data.hex())
Uso del valor hash
Los valores hash se pueden usar para verificar la integridad de los datos. Por ejemplo, después de descargar un archivo, se puede comparar el valor hash para asegurarse de que los datos no hayan sido alterados.
# Ejemplo de cálculo del hash de un archivo
def hash_file(file_path):
digest = hashes.Hash(hashes.SHA256(), backend=default_backend())
with open(file_path, 'rb') as f:
while chunk := f.read(8192):
digest.update(chunk)
return digest.finalize()
# Cálculo y visualización del hash de un archivo
file_path = 'ruta/a/tu/archivo'
file_hash = hash_file(file_path)
print("Hash del archivo:", file_hash.hex())
De esta manera, puedes usar la biblioteca cryptography para hacer hash de datos y verificar su integridad. El hashing juega un papel crucial en el almacenamiento de contraseñas y la verificación de la integridad de los datos.
Generación de claves privadas y públicas
La generación de un par de claves privada y pública es un paso clave en el cifrado asimétrico. A continuación, explicamos cómo generar y almacenar claves usando la biblioteca cryptography.
Generación de pares de claves RSA
Usamos el algoritmo RSA para generar un par de claves pública y privada.
Importar los módulos necesarios
Primero, importamos los módulos necesarios de la biblioteca cryptography.
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization
Generación del par de claves
Usamos RSA para generar el par de claves.
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
Guardar las claves
Guardamos las claves generadas en archivos separados.
# Guardar la clave privada
with open("private_key.pem", "wb") as private_file:
private_file.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.TraditionalOpenSSL,
encryption_algorithm=serialization.NoEncryption()
))
# Guardar la clave pública
with open("public_key.pem", "wb") as public_file:
public_file.write(public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
))
Leer las claves
Leemos las claves almacenadas desde los archivos.
# Leer la clave privada
with open("private_key.pem", "rb") as private_file:
loaded_private_key = serialization.load_pem_private_key(
private_file.read(),
password=None,
)
# Leer la clave pública
with open("public_key.pem", "rb") as public_file:
loaded_public_key = serialization.load_pem_public_key(
public_file.read()
)
Ejemplo práctico
Usamos las claves generadas para cifrar y descifrar datos de manera sencilla.
from cryptography.hazmat.primitives.asymmetric import padding
from cryptography.hazmat.primitives import hashes
# Cifrado de datos
def encrypt(data, public_key):
return public_key.encrypt(
data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Descifrado de datos
def decrypt(encrypted_data, private_key):
return private_key.decrypt(
encrypted_data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Ejemplo de cifrado y descifrado
data = b"Este es un mensaje secreto"
encrypted_data = encrypt(data, loaded_public_key)
print("Datos cifrados:", encrypted_data)
decrypted_data = decrypt(encrypted_data, loaded_private_key)
print("Datos descifrados:", decrypted_data.decode())
De esta manera, puedes generar y usar un par de claves para cifrar y descifrar datos de forma segura.
Ejemplos prácticos de cifrado y descifrado
En este apartado, describimos cómo cifrar y descifrar datos en un proyecto real utilizando tanto cifrado simétrico (AES) como cifrado asimétrico (RSA).
Cifrado y descifrado con cifrado simétrico
Importar los módulos necesarios
Primero importamos los módulos necesarios para cifrado simétrico.
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
import os
Generación de la clave y el vector de inicialización
Generamos la clave y el vector de inicialización (IV) para el cifrado AES.
key = os.urandom(32) # Clave de 256 bits
iv = os.urandom(16) # Vector de inicialización de 128 bits
Relleno de datos
Añadimos relleno para asegurar que los datos sean múltiplos del tamaño del bloque.
def pad(data):
padder = padding.PKCS7(algorithms.AES.block_size).padder()
return padder.update(data) + padder.finalize()
Cifrado de datos
Ahora ciframos los datos con la clave y el IV generados.
def encrypt(data, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
encryptor = cipher.encryptor()
padded_data = pad(data)
return encryptor.update(padded_data) + encryptor.finalize()
Descifrado de datos
Desciframos los datos y eliminamos el relleno.
def decrypt(encrypted_data, key, iv):
cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
decryptor = cipher.decryptor()
padded_data = decryptor.update(encrypted_data) + decryptor.finalize()
unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
return unpadder.update(padded_data) + unpadder.finalize()
Ejemplo práctico
Este ejemplo muestra cómo cifrar y luego descifrar datos en texto claro.
data = b"Este es un mensaje secreto"
encrypted_data = encrypt(data, key, iv)
print("Datos cifrados:", encrypted_data)
decrypted_data = decrypt(encrypted_data, key, iv)
print("Datos descifrados:", decrypted_data.decode())
Cifrado y descifrado con cifrado asimétrico
Importar los módulos necesarios
Importamos los módulos necesarios para el cifrado asimétrico.
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
Generación de claves
Generamos un par de claves pública y privada para usar RSA.
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048,
)
public_key = private_key.public_key()
Cifrado de datos
Usamos la clave pública para cifrar los datos.
def encrypt(data, public_key):
return public_key.encrypt(
data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Descifrado de datos
Usamos la clave privada para descifrar los datos cifrados.
def decrypt(encrypted_data, private_key):
return private_key.decrypt(
encrypted_data,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
Ejemplo práctico
Este ejemplo muestra cómo cifrar y luego descifrar los datos usando un par de claves pública y privada.
data = b"Este es un mensaje secreto"
encrypted_data = encrypt(data, public_key)
print("Datos cifrados:", encrypted_data)
decrypted_data = decrypt(encrypted_data, private_key)
print("Datos descifrados:", decrypted_data.decode())
De esta manera, puedes implementar cifrado asimétrico con la biblioteca cryptography para lograr una comunicación de datos segura.
Aplicación en proyectos reales
En esta sección, explicamos cómo aplicar el cifrado en proyectos reales, como la comunicación API, cifrado de bases de datos y archivos.
Cifrado en comunicación API
Explicamos cómo cifrar y asegurar los datos transmitidos a través de una API.
Uso de HTTPS
Primero, utilizamos HTTPS para asegurar la comunicación API, lo que cifra la ruta de comunicación y previene la intercepción de datos.
Cifrado de datos
Podemos cifrar los datos antes de enviarlos para mejorar la seguridad de la transmisión.
import requests
# Cifrado de datos usando clave pública
data = b"Datos importantes para la API"
encrypted_data = encrypt(data, public_key)
# Enviar los datos cifrados a la API
response = requests.post('https://api.example.com/data', data=encrypted_data)
Cifrado en bases de datos
Explicamos cómo cifrar datos sensibles antes de almacenarlos en una base de datos.
Cifrado de datos al almacenarlos
Antes de almacenar datos en la base de datos, los ciframos y los desciframos cuando sea necesario.
import sqlite3
# Establecer conexión a la base de datos
conn = sqlite3.connect('example.db')
cursor = conn.cursor()
# Cifrado de datos
data = b"Datos secretos para almacenar"
encrypted_data = encrypt(data, key, iv)
# Guardar datos cifrados
cursor.execute("INSERT INTO secrets (data) VALUES (?)", (encrypted_data,))
conn.commit()
# Recuperar y descifrar datos
cursor.execute("SELECT data FROM secrets")
encrypted_data = cursor.fetchone()[0]
decrypted_data = decrypt(encrypted_data, key, iv)
print("Datos descifrados:", decrypted_data.decode())
Cifrado de archivos
Explicamos cómo cifrar y almacenar archivos de manera segura, y cómo descifrarlos cuando sea necesario.
Cifrado de archivos
Este es el proceso de cifrar los datos de un archivo antes de guardarlo y luego descifrarlo cuando sea necesario.
# Leer y cifrar archivo
with open('example.txt', 'rb') as file:
file_data = file.read()
encrypted_data = encrypt(file_data, key, iv)
# Guardar datos cifrados
with open('example_encrypted.txt', 'wb') as file:
file.write(encrypted_data)
# Descifrar archivo
with open('example_encrypted.txt', 'rb') as file:
encrypted_data = file.read()
decrypted_data = decrypt(encrypted_data, key, iv)
# Escribir los datos descifrados
with open('example_decrypted.txt', 'wb') as file:
file.write(decrypted_data)
Gestión de claves en proyectos
Explicamos cómo gestionar las claves de manera segura en proyectos reales.
Almacenamiento seguro de claves
Usamos HSM (Módulos de Seguridad de Hardware) o servicios seguros de almacenamiento de claves. También se pueden usar variables de entorno para gestionar las claves.
import os
# Obtener claves desde variables de entorno
key = os.environ.get('SECRET_KEY').encode()
iv = os.environ.get('SECRET_IV').encode()
Resumen
En este artículo, hemos cubierto los conceptos básicos y avanzados del cifrado utilizando la biblioteca cryptography en Python. A través de ejemplos prácticos y aplicaciones reales, hemos aprendido cómo cifrar, descifrar y gestionar datos de manera segura. Estas técnicas son esenciales para proteger proyectos y garantizar la seguridad de los datos en diferentes escenarios.
Ejemplos avanzados y ejercicios
Aquí te presentamos ejemplos avanzados y ejercicios prácticos para mejorar tu comprensión sobre cómo implementar cifrado con la biblioteca cryptography.
Ejemplo avanzado 1: Aplicación de chat cifrada
Implementamos una aplicación de chat donde los mensajes se cifran y descifran de manera segura.
Cifrado y descifrado de mensajes
En la aplicación de chat, ciframos los mensajes antes de enviarlos y los desciframos cuando los recibimos.
# Cifrado del mensaje
def encrypt_message(message, public_key):
return encrypt(message.encode(), public_key)
# Descifrado del mensaje
def decrypt_message(encrypted_message, private_key):
return decrypt(encrypted_message, private_key).decode()
# Ejemplo de uso
message = "Hola, este es un mensaje secreto"
encrypted_message = encrypt_message(message, public_key)
print("Mensaje cifrado:", encrypted_message)
decrypted_message = decrypt_message(encrypted_message, private_key)
print("Mensaje descifrado:", decrypted_message)
Ejemplo avanzado 2: Sistema de intercambio de archivos seguro
Implementamos un sistema para compartir archivos de forma segura usando cifrado.
Cifrado y descifrado de archivos
Antes de compartir un archivo, lo ciframos y luego lo desciframos en el lado receptor.
# Cifrado del archivo
def encrypt_file(file_path, key, iv):
with open(file_path, 'rb') as file:
file_data = file.read()
encrypted_data = encrypt(file_data, key, iv)
with open(file_path + '.enc', 'wb') as file:
file.write(encrypted_data)
# Descifrado del archivo
def decrypt_file(encrypted_file_path, key, iv):
with open(encrypted_file_path, 'rb') as file:
encrypted_data = file.read()
decrypted_data = decrypt(encrypted_data, key, iv)
with open(encrypted_file_path.replace('.enc', ''), 'wb') as file:
file.write(decrypted_data)
# Ejemplo de uso
encrypt_file('shared_document.pdf', key, iv)
decrypt_file('shared_document.pdf.enc', key, iv)
Ejercicio práctico 1
Implementa un sistema de gestión de contraseñas usando cifrado simétrico (AES).
- Crea una función que reciba una contraseña y la cifre usando AES.
- Guarda la contraseña cifrada y crea una función para descifrarla.
Ejercicio práctico 2
Usa RSA para implementar un sistema seguro de envío de mensajes.
- Genera un par de claves públicas y privadas.
- Cifra un mensaje usando la clave pública.
- Descifra el mensaje usando la clave privada.
Ejercicio práctico 3
Usa SHA-256 para detectar modificaciones en los archivos.
- Crea una función para calcular el valor hash de un archivo.
- Calcula el hash después de modificar el archivo para verificar si ha habido cambios.
A través de estos ejemplos y ejercicios, podrás dominar el uso de la biblioteca cryptography y mejorar tus habilidades de seguridad en los datos.
Resumen final
En este artículo, hemos cubierto desde los fundamentos hasta aplicaciones avanzadas de cifrado en Python usando la biblioteca cryptography. Aprendimos cómo implementar técnicas de cifrado simétrico y asimétrico, así como hashing para proteger datos. Estas técnicas son fundamentales para garantizar la seguridad de los datos en proyectos reales. ¡Es momento de aplicar lo aprendido y asegurar tus proyectos!