Kellyss commited on
Commit
456f2be
verified
1 Parent(s): 0ddbf29

Create substitution_cipher.py

Browse files
Files changed (1) hide show
  1. substitution_cipher.py +81 -0
substitution_cipher.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python3
2
+ """
3
+ Cifrado de sustituci贸n estilo AES (solo confusi贸n/ofuscaci贸n).
4
+ Autor: Denisse Aguilar (ejemplo para maestr铆a en Criptograf铆a)
5
+ ------------------------------------------------------------------
6
+ Descripci贸n:
7
+ - Genera una S-box (sustituci贸n 1 a 1 de bytes) derivada de una clave.
8
+ - Cifra y descifra texto usando solo sustituci贸n (sin difusi贸n).
9
+ - Basado en la idea del paso SubBytes del AES.
10
+ ------------------------------------------------------------------
11
+ Uso (en terminal o Hugging Face):
12
+ >>> from substitution_cipher import encrypt, decrypt
13
+ >>> texto_cifrado = encrypt("Hola mundo", "miClave")
14
+ >>> decrypt(texto_cifrado, "miClave")
15
+ """
16
+
17
+ import hashlib
18
+ import base64
19
+ import random
20
+
21
+ # ==============================================================
22
+ # 馃攼 Generaci贸n de S-box e inversa
23
+ # ==============================================================
24
+
25
+ def generate_sbox_from_key(key: str):
26
+ """
27
+ Genera una tabla de sustituci贸n (S-box) de 256 valores 煤nicos basada en la clave.
28
+ """
29
+ # Deriva una semilla num茅rica de la clave usando SHA-256
30
+ key_hash = hashlib.sha256(key.encode("utf-8")).digest()
31
+ seed = int.from_bytes(key_hash, "big")
32
+
33
+ # Usa PRNG determinista (semilla derivada)
34
+ rng = random.Random(seed)
35
+
36
+ sbox = list(range(256))
37
+ rng.shuffle(sbox) # Permutaci贸n aleatoria 0..255
38
+ inv_sbox = [0] * 256
39
+ for i, v in enumerate(sbox):
40
+ inv_sbox[v] = i
41
+ return sbox, inv_sbox
42
+
43
+ # ==============================================================
44
+ # 馃攣 Funciones de cifrado y descifrado
45
+ # ==============================================================
46
+
47
+ def encrypt(plaintext: str, password: str) -> str:
48
+ """
49
+ Cifra un texto (string) usando sustituci贸n de bytes.
50
+ Devuelve el resultado en base64.
51
+ """
52
+ sbox, _ = generate_sbox_from_key(password)
53
+ data = plaintext.encode("utf-8")
54
+ encrypted_bytes = bytes([sbox[b] for b in data])
55
+ return base64.b64encode(encrypted_bytes).decode("utf-8")
56
+
57
+ def decrypt(ciphertext_b64: str, password: str) -> str:
58
+ """
59
+ Descifra un texto cifrado en base64 usando la misma clave.
60
+ """
61
+ _, inv_sbox = generate_sbox_from_key(password)
62
+ encrypted_bytes = base64.b64decode(ciphertext_b64)
63
+ decrypted_bytes = bytes([inv_sbox[b] for b in encrypted_bytes])
64
+ return decrypted_bytes.decode("utf-8", errors="ignore")
65
+
66
+ # ==============================================================
67
+ # 馃И Ejemplo de uso
68
+ # ==============================================================
69
+
70
+ if __name__ == "__main__":
71
+ import argparse
72
+ parser = argparse.ArgumentParser(description="Cifrado por sustituci贸n (solo confusi贸n).")
73
+ parser.add_argument("mode", choices=["encrypt", "decrypt"], help="Modo: encrypt o decrypt")
74
+ parser.add_argument("text", help="Texto a cifrar o descifrar")
75
+ parser.add_argument("--key", required=True, help="Clave secreta")
76
+ args = parser.parse_args()
77
+
78
+ if args.mode == "encrypt":
79
+ print(encrypt(args.text, args.key))
80
+ else:
81
+ print(decrypt(args.text, args.key))