🚨 ADVERTENCIA 🚨: Esta será una de las entradas más largas y un tanto avanzadas, recomiendo leer detenidamente y si pondrá en practica algo aqui visto deberá hacerlo bajo su propio riesgo. Difficulty Level: ⭐⭐⭐
Te recomiendo ir al CheatSheet para una versión mas dinamica y divertida de aprender estos terminos. Click para encontrar el CheatSheet Completo
CRIPTOGRAFIA: Es el arte de representar información mediante simbolos y sistemas de codificación para transmitir la información de manera segura y confiable. ¿Cual es su uso?: Cifrar confidenciales o privados para mantenerlos seguros ante cualquier tipo de ataque y para cumplir la normativa de seguridad de la información, (aunque esto no siempre es infalible).
Nombre | Descripción |
---|---|
🐦 AES | (Advanced Encryption Standard) Es un estándar ampliamente utilizado por su eficacia y seguridad, Algunos Softwares que lo usan son Encrypto, GIE, PassPai |
🐦 DES | (Data Encryption Standard) Es un algoritmo más antiguo que ha sido reemplazado en gran medida por AES. |
🐦 Blowfish | Es un algoritmo de cifrado de bloque que es rápido y eficiente para datos de tamaño variable muy usado en WooCommerce. |
#JSX1import * as crypto from 'crypto'; 2import { createReadStream, createWriteStream, PathLike } from 'fs'; 3import { pipeline } from 'stream'; 4 5const cipher = ( 6 password: string, 7 salt: string, 8 size: 128|192|256, 9 input: PathLike, 10 output: PathLike, 11) => { 12 const cipher = crypto.createCipheriv( 13 `aes-${size}-cbc`, 14 crypto.scryptSync(password, salt, size / 8), 15 new Uint8Array(16) 16 ); 17 18 pipeline(createReadStream(input), cipher, createWriteStream(output), (error)=> { 19 if(error) throw error; 20 }); 21}; 22
Este fragmento de código TypeScript define una función llamada cipher
que realiza el cifrado utilizando el algoritmo Advanced Encryption Standard (AES).
La función recibe los siguientes parámetros:
password
: Una cadena que representa la contraseña utilizada para cifrar los datos.salt
: Una cadena que representa la sal utilizada en el proceso de cifrado.size
: Un número que representa el tamaño de la clave (128, 192 o 256).input
: Un objeto PathLike
que representa la ruta del fichero a cifrar.: Un objeto
PathLike` que representa la ruta al fichero de salida cifrado.Dentro de la función, crea un cifrado utilizando el método createCipheriv
del módulo crypto
. Especifica el algoritmo de cifrado como aes-{size}-cbc
, donde {size}
es el valor del parámetro size
. También genera una clave utilizando el método scryptSync
, pasando la password
, salt
, y size / 8
como argumentos.
A continuación, la función utiliza el método pipeline
para leer el contenido del fichero de entrada, encriptar lo utilizando el cifrado, y escribir el resultado encriptado en el fichero de salida. Si se produce un error durante el proceso de cifrado, lanza el error.
#JSX1import * as crypto from 'crypto';s 2import { createReadStream, createWriteStream, PathLike } from 'fs'; 3import { pipeline } from 'stream'; 4 5const decipher = ( 6 password: string, 7 salt: string, 8 size: 128|192|256, 9 input: PathLike, 10 output: PathLike, 11) => { 12 const decipher = crypto.createDecipheriv( 13 `aes-${size}-cbc`, 14 crypto.scryptSync(password, salt, size / 8), 15 new Uint8Array(16) 16 ); 17 18 pipeline(createReadStream(input), decipher, createWriteStream(output), (error) => { 19 if(error) throw error; 20 }); 21}; 22 23export default decipher; 24
Esto descifra el contenido del anterior codigo.
Nombre | Descripción |
---|---|
🐦 RSA | (Rivest-Shamir-Adleman) Es uno de los primeros sistemas de criptografía asimétrica, utilizado para cifrado y firma digital. |
🐦 DSA | (Digital Signature Algorithm) Utilizado principalmente para la creación de firmas digitales. |
🐦 ECC | (Elliptic Curve Cryptography) Ofrece la misma seguridad que RSA pero con claves más cortas, lo que lo hace más eficiente, Algunos Softwares que lo usan son GIE. |
#JSX1// Importa módulos necesarios 2import * as crypto from "crypto"; 3import { PathLike, mkdirSync, writeFileSync } from "fs"; 4import { join } from "path"; 5 6// Función para generar un par de claves RSA o RSA-PSS 7const keygen = ( 8 // Tipo de clave a generar ("rsa" o "rsa-pss") 9 type: "rsa" | "rsa-pss", 10 // Tamaño de cifrado para la clave privada (128, 192 o 256 bits) 11 size: 128 | 192 | 256, 12 // Frase de contraseña para proteger la clave privada 13 passphrase: string, 14 // Formato de salida de las claves ("pem" o "der") 15 format: "pem" | "der", 16 // Longitud del módulo para la clave (2048, 3072 o 4096 bits) 17 modulusLength: 2048 | 3072 | 4096 18 // Define las opciones de generación de claves según el tipo 19) => { 20 switch (type) { 21 case "rsa": { 22 // Opciones para claves RSA 23 const options: crypto.RSAKeyPairOptions< 24 crypto.KeyFormat, 25 crypto.KeyFormat 26 > = { 27 modulusLength, // Longitud del módulo 28 publicKeyEncoding: { 29 type: "spki", // Formato estándar para clave pública 30 format, // Formato de salida 31 }, 32 privateKeyEncoding: { 33 type: "pkcs8", // Formato estándar para clave privada 34 format, // Formato de salida 35 cipher: `aes-${size}-cbc`, // Algoritmo de cifrado para la clave privada 36 passphrase, // Frase de contraseña 37 }, 38 }; 39 return crypto.generateKeyPairSync("rsa", options); // Genera el par de claves 40 } 41 case "rsa-pss": { 42 // Opciones para claves RSA-PSS (similar a RSA pero con firma PSS) 43 const options: crypto.RSAPSSKeyPairOptions< 44 crypto.KeyFormat, 45 crypto.KeyFormat 46 > = { 47 modulusLength, // Longitud del módulo 48 publicKeyEncoding: { 49 type: "spki", // Formato estándar para clave pública 50 format, // Formato de salida 51 }, 52 privateKeyEncoding: { 53 type: "pkcs8", // Formato estándar para clave privada 54 format, // Formato de salida 55 cipher: `aes-${size}-cbc`, // Algoritmo de cifrado para la clave privada 56 passphrase, // Frase de contraseña 57 }, 58 }; 59 return crypto.generateKeyPairSync("rsa-pss", options); // Genera el par de claves 60 } 61 } 62}; 63 64// Función para crear un par de claves y guardarlas en archivos 65const keypair = ( 66 type: "rsa" | "rsa-pss", 67 size: 128 | 192 | 256, 68 passphrase: string, 69 outDir: string, 70 outFormat: "pem" | "der", 71 modulusLength: 2048 | 3072 | 4096 72) => { 73 // Genera el par de claves usando la función keygen 74 const { publicKey, privateKey } = keygen( 75 type, 76 size, 77 passphrase, 78 outFormat, 79 modulusLength 80 ); 81 // Crea la carpeta de salida si no existe 82 mkdirSync(outDir, { recursive: true }); 83 // Guarda la clave pública en un archivo 84 writeFileSync(join(outDir, `public.${outFormat}`), publicKey.toString()); 85 // Guarda la clave privada en un archivo (cifrada con la frase de contraseña) 86 writeFileSync(join(outDir, `private.${outFormat}`), privateKey.toString()); 87}; 88 89// Exporta la función keypair para usarla en otros módulos 90export default keypair; 91 92
El código anterior es una función TypeScript llamada keygen
que genera un par de claves RSA o RSA-PSS. Toma cinco parámetros:
type
: el tipo de clave a generar, ya sea «rsa» o «rsa-pss».size
: el tamaño de cifrado de la clave privada (128, 192 o 256 bits)format
: el formato de salida de las claves («pem» o «der»)modulusLength
: la longitud del módulo de la clave (2048, 3072 o 4096 bits)La función utiliza una sentencia switch
para determinar qué tipo de clave generar, y luego crea un objeto options con los parámetros especificados. Luego llama a la función crypto.generateKeyPairSync
para generar el par de claves, pasando el objeto options.
En resumen, esta función genera un par de claves RSA o RSA-PSS con tamaño de cifrado, protección por contraseña, formato de salida y longitud de módulo personalizables.
Nombre | Descripción |
---|---|
🐦 SHA-256 | (Secure Hash Algorithm 256 bits) Parte de la familia SHA-2, ampliamente utilizada en aplicaciones como Bitcoin. |
🐦 MD5 | (Message-Digest Algorithm 5) Aunque es rápido, ya no se recomienda debido a vulnerabilidades encontradas. |
🐦 Whirlpool | Un algoritmo hash que produce un hash de 512 bits. |
#JSX1import * as crypto from 'crypto'; 2import { PathLike, readFileSync } from 'fs'; 3 4const hash = (algorithm: string, encoding: crypto.BinaryToTextEncoding, input: PathLike) => { 5 return crypto.createHash(algorithm).update(readFileSync(input)).digest(encoding); 6}; 7 8export default hash; 9 10
Esta es una función TypeScript llamada hash
que genera un valor hash para un archivo dado. Toma tres parámetros:
algorithm
: el algoritmo hash a utilizar (por ejemplo «sha256», «md5», etc.)encoding
: la codificación a utilizar para el valor hash resultante (p.ej. «hex», «base64», etc.)input
: el archivo para el que se generará el hashLa función utiliza el módulo crypto
para crear un objeto hash, lo actualiza con el contenido del fichero de entrada y devuelve el valor hash en la codificación especificada.
Nombre | Descripción |
---|---|
🐦 ECDSA | (Elliptic Curve Digital Signature Algorithm) Utilizado para crear firmas digitales. |
🐦 ECDH | (Elliptic Curve Diffie-Hellman) Un método para intercambiar claves secretas. |
#PYTHON1from cryptography.hazmat.primitives.asymmetric import x25519 2from cryptography.hazmat.primitives.asymmetric.x25519 import X25519PrivateKey, X25519PublicKey 3from cryptography.hazmat.primitives import serialization, hashes 4from cryptography.hazmat.primitives.asymmetric import padding 5from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes 6from cryptography.hazmat.backends import default_backend 7import os 8import math 9 10 11def generate_key_pair(): 12 # Genera un par de claves ECDH. 13 private_key = X25519PrivateKey.generate() 14 public_key = private_key.public_key() 15 return private_key, public_key 16 17 18def derive_key(private_key, public_key): 19 # Obtención de una clave compartida mediante ECDH 20 shared_key = private_key.exchange(public_key) 21 return shared_key 22 23 24def fibonacci_sequence(n): 25 # Generar una sucesión de Fibonacci hasta el enésimo término. 26 sequence = [0, 1] 27 while len(sequence) < n: 28 sequence.append(sequence[-1] + sequence[-2]) 29 return sequence 30 31 32def xor_encrypt(data, key): 33 # XOR a los datos con la llave. 34 return bytes([b ^ key[i % len(key)] for i, b in enumerate(data)]) 35 36 37def encrypt(plaintext, public_key): 38 # Cifrar el texto plano utilizando la clave pública y una secuencia de Fibonacci. 39 # Genera una llave asimetrica de manera aletoeria 40 symmetric_key = os.urandom(32) 41 42 # Se Obtiene la clave compartida mediante ECDH 43 private_key, _ = generate_key_pair() # Genera una clave privada temporal 44 shared_key = derive_key(private_key, public_key) 45 46 # Genera una clave fibonacci basada en la longitud del texto plano 47 fib_sequence = fibonacci_sequence(len(plaintext)) 48 49 # Ajusta la longitud de la clave combinada para coincidir con el texto plano 50 combined_key = bytes( 51 [shared_key[i % len(shared_key)] ^ fib_sequence[i % len(fib_sequence)] for i in range(len(plaintext))]) 52 53 # Encripta el texto plano con la clave combinada 54 encrypted_text = xor_encrypt(plaintext.encode(), combined_key) 55 56 return encrypted_text, private_key # Retorna temporalmente la clave privada 57 58 59def decrypt(encrypted_text, private_key, public_key): 60 """Descifra el texto cifrado utilizando la clave privada y la clave pública.""" 61 # Se Obtiene la clave compartida mediante ECDH 62 shared_key = derive_key(private_key, public_key) 63 64 # Generar una secuencia de Fibonacci basada en la longitud del texto cifrado 65 fib_sequence = fibonacci_sequence(len(encrypted_text)) 66 67 # Ajusta la longitud de la clave combinada para que coincida con el texto cifrado 68 combined_key = bytes( 69 [shared_key[i % len(shared_key)] ^ fib_sequence[i % len(fib_sequence)] for i in range(len(encrypted_text))]) 70 71 # Descifra el texto cifrado con la clave combinada 72 decrypted_text = xor_encrypt(encrypted_text, combined_key) 73 74 return decrypted_text.decode(errors='ignore') # Ignora los errores durante la decodificación 75 76 77print("Enter a password to encrypt") 78 79passwd = input(": ") 80 81# Ejemplo de uso 82# Frase: -- 83plaintext = passwd 84private_key, public_key = generate_key_pair() 85encrypted_text, temp_private_key = encrypt(plaintext, public_key) 86print(f"Encrypted: {encrypted_text}") 87 88decrypted_text = decrypt(encrypted_text, temp_private_key, public_key) 89print(f"Decrypted: {decrypted_text}") 90 91
El código anterior fue escrito en Python usando tecnicas de calculo utilizando la criptografía de curva elíptica (concretamente, la curva X25519).
Instala las dependencias y asegurate de instalar la libreria cryptography correctamente.
Ejemplo: Ingresamos la palabra : Hello
X25519PrivateKey.generate()
.generate_key_pair()
para crear una clave privada y una clave pública.Si ejecutara el programa, podría ver un resultado similar a éste (los valores reales serán diferentes cada vez debido a la aleatoriedad):
b'\x1a\x2b\x3c\x4d\x5e\x6f\...'
b'\x9a\x8b\x7c\x6d\x5e\x4f\...'
Las claves pública y privada no se derivan de la entrada «Hola», sino que se generan de forma independiente. La entrada sólo se utiliza para los procesos de cifrado y descifrado después de que se hayan generado las claves.
Nombre | Descripción |
---|---|
🐦 QKD | (Quantum Key Distribution) Permite a dos partes generar una clave secreta compartida utilizando partículas cuánticas. Si un tercero intenta interceptar la clave, esto alterará el estado cuántico y será detectable. |
Esto esta aun en desarrollo, pero la idea principal de la criptografía cuántica promete revolucionar la seguridad informática al ofrecer métodos que son teóricamente invulnerables a ataques futuros basados en computadoras cuántica
#PYTHON1import numpy as np 2import random 3 4class QKD: 5 def __init__(self, n_bits): 6 self.n_bits = n_bits 7 self.alice_bits = [] 8 self.bob_bits = [] 9 self.bases_alice = [] 10 self.bases_bob = [] 11 self.shared_key = [] 12 13 def generate_bits_and_bases(self): 14 # Alice genera bits aleatorios y bases 15 for _ in range(self.n_bits): 16 self.alice_bits.append(random.randint(0, 1)) # Bit aleatorio (0 ó 1) 17 self.bases_alice.append(random.choice(['H', 'V'])) # Base aleatoria (horizontal o vertical) 18 19 def simulate_bob_measurement(self): 20 # Bob elige aleatoriamente bases para medir los bits de Alice 21 for _ in range(self.n_bits): 22 self.bases_bob.append(random.choice(['H', 'V'])) 23 # Simular la medición (si las bases coinciden, se lleva el bit) 24 if self.bases_alice[_] == self.bases_bob[_]: 25 self.bob_bits.append(self.alice_bits[_]) 26 else: 27 self.bob_bits.append(None) # Ningún bit si las bases no coinciden 28 29 def sift_key(self): 30 # Tamizar la clave en función de las bases coincidentes 31 for i in range(self.n_bits): 32 if self.bases_alice[i] == self.bases_bob[i]: 33 self.shared_key.append(self.alice_bits[i]) 34 35 def run_qkd_protocol(self): 36 self.generate_bits_and_bases() 37 self.simulate_bob_measurement() 38 self.sift_key() 39 40 return self.shared_key 41 42# Ejemplo de uso 43n_bits = 10 # Número de bits a intercambiar 44qkd_protocol = QKD(n_bits) 45secure_key = qkd_protocol.run_qkd_protocol() 46 47print("Shared secure key:", secure_key) 48
Esta clasificación refleja la diversidad y profundidad del campo de la criptografía, mostrando cómo sus distintas técnicas se aplican para proteger la información en variados contextos. Desde el cifrado de mensajes hasta la seguridad de las transacciones en línea y la autenticación de usuarios, la criptografía es fundamental para la seguridad en el mundo digital.
Mas adelante mostraré como se rompen estos cifrados y porque mmd5 es muy malo para usar. En otra entrada revisaremos como funciona el cifrado AES.