Cybersecurity Fundamentals (Part 3)
Β
π¨ WARNING π¨: This will be one of the longest and somewhat advanced entries, I recommend reading carefully and if you put anything seen here into practice, you should do so at your own risk. Difficulty Level: βββ
I recommend you go to the CheatSheet for a more dynamic and fun version of learning these terms. Click to find the Complete CheatSheet
Β
What is Cryptography? π
CRYPTOGRAPHY: It is the art of representing information through symbols and coding systems to transmit information securely and reliably. What is its use?: To encrypt confidential or private information to keep it safe from any type of attack and to comply with information security regulations (although this is not always infallible).
Examples in your daily life
- π When you log into your favorite social network with your password.
- π When you unlock your cell phone.
- π When you send a WhatsApp message to your partner.
- π When you hear a taxi driver talking to another in code, for example: 10-4, 7-40, etc.
Β
1. Symmetric Cryptography
- π« Features: In symmetric cryptography, the same key is used to encrypt and decrypt a message. This requires both parties to share the key securely before use. It is faster compared to asymmetric cryptography and is used to encrypt large volumes of data.
- π« Applications: It is commonly used for file encryption (for example, in cloud storage systems), in databases to protect sensitive data, and in virtual private networks (VPNs) to ensure data transmission, in short, large volumes of data.
Examples of Symmetric Cryptography
Name | Description |
---|---|
π¦ AES | (Advanced Encryption Standard) It is a widely used standard for its efficiency and security. Some software that uses it are Encrypto, GIE, PassPai |
π¦ DES | (Data Encryption Standard) It is an older algorithm that has been largely replaced by AES. |
π¦ Blowfish | It is a block cipher algorithm that is fast and efficient for variable-sized data, widely used in WooCommerce. |
Β
Symmetric Cryptography Code Example
#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
This TypeScript code snippet defines a function called cipher
that performs encryption using the Advanced Encryption Standard (AES) algorithm.
The function receives the following parameters:
password
: A string representing the password used to encrypt the data.salt
: A string representing the salt used in the encryption process.size
: A number representing the key size (128, 192, or 256).input
: APathLike
object representing the path to the file to be encrypted.output
: APathLike
object representing the path to the encrypted output file.
Inside the function, it creates a cipher using the createCipheriv
method of the crypto
module. It specifies the encryption algorithm as aes-{size}-cbc
, where {size}
is the value of the size
parameter. It also generates a key using the scryptSync
method, passing the password
, salt
, and size / 8
as arguments.
Next, the function uses the pipeline
method to read the contents of the input file, encrypt it using the cipher, and write the encrypted result to the output file. If an error occurs during the encryption process, it throws the 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
This decrypts the content of the previous code.
Β
2. Asymmetric or Public Key Cryptography
- π« Features: Also known as public key cryptography, it uses a pair of keys: a public one and a private one. The public key can be shared openly, while the private key is kept secret. This technique allows both encryption and digital signing of messages.
- π« Applications: It is essential for creating digital signatures, establishing secure sessions on the Internet (as in SSL/TLS for secure websites), and in encrypted email systems. This method is essential for establishing secure connections on the internet, such as in the HTTPS protocol.
Examples of Asymmetric Cryptography
Name | Description |
---|---|
π¦ RSA | (Rivest-Shamir-Adleman) It is one of the first asymmetric cryptography systems, used for encryption and digital signatures. |
π¦ DSA | (Digital Signature Algorithm) Used mainly for creating digital signatures. |
π¦ ECC | (Elliptic Curve Cryptography) It offers the same security as RSA but with shorter keys, which makes it more efficient. Some software that uses it are GIE. |
Β
Asymmetric Cryptography Code Example
#JSX1// Import necessary modules 2import * as crypto from "crypto"; 3import { PathLike, mkdirSync, writeFileSync } from "fs"; 4import { join } from "path"; 5 6// Function to generate an RSA or RSA-PSS key pair 7const keygen = ( 8 // Type of key to generate ("rsa" or "rsa-pss") 9 type: "rsa" | "rsa-pss", 10 // Encryption size for the private key (128, 192, or 256 bits) 11 size: 128 | 192 | 256, 12 // Passphrase to protect the private key 13 passphrase: string, 14 // Output format of the keys ("pem" or "der") 15 format: "pem" | "der", 16 // Modulus length for the key (2048, 3072, or 4096 bits) 17 modulusLength: 2048 | 3072 | 4096 18 // Define key generation options according to the type 19) => { 20 switch (type) { 21 case "rsa": { 22 // Options for RSA keys 23 const options: crypto.RSAKeyPairOptions< 24 crypto.KeyFormat, 25 crypto.KeyFormat 26 > = { 27 modulusLength, // Modulus length 28 publicKeyEncoding: { 29 type: "spki", // Standard format for public key 30 format, // Output format 31 }, 32 privateKeyEncoding: { 33 type: "pkcs8", // Standard format for private key 34 format, // Output format 35 cipher: `aes-${size}-cbc`, // Encryption algorithm for the private key 36 passphrase, // Passphrase 37 }, 38 }; 39 return crypto.generateKeyPairSync("rsa", options); // Generate the key pair 40 } 41 case "rsa-pss": { 42 // Options for RSA-PSS keys (similar to RSA but with PSS signature) 43 const options: crypto.RSAPSSKeyPairOptions< 44 crypto.KeyFormat, 45 crypto.KeyFormat 46 > = { 47 modulusLength, // Modulus length 48 publicKeyEncoding: { 49 type: "spki", // Standard format for public key 50 format, // Output format 51 }, 52 privateKeyEncoding: { 53 type: "pkcs8", // Standard format for private key 54 format, // Output format 55 cipher: `aes-${size}-cbc`, // Encryption algorithm for the private key 56 passphrase, // Passphrase 57 }, 58 }; 59 return crypto.generateKeyPairSync("rsa-pss", options); // Generate the key pair 60 } 61 } 62}; 63 64// Function to create a key pair and save them to files 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 // Generate the key pair using the keygen function 74 const { publicKey, privateKey } = keygen( 75 type, 76 size, 77 passphrase, 78 outFormat, 79 modulusLength 80 ); 81 // Create the output folder if it does not exist 82 mkdirSync(outDir, { recursive: true }); 83 // Save the public key to a file 84 writeFileSync(join(outDir, `public.${outFormat}`), publicKey.toString()); 85 // Save the private key to a file (encrypted with the passphrase) 86 writeFileSync(join(outDir, `private.${outFormat}`), privateKey.toString()); 87}; 88 89// Export the keypair function to use it in other modules 90export default keypair; 91 92
The above code is a TypeScript function called keygen
that generates an RSA or RSA-PSS key pair. It takes five parameters:
type
: the type of key to generate, either "rsa" or "rsa-pss".size
: the encryption size of the private key (128, 192, or 256 bits)- Passphrase: password to protect the private key.
format
: the output format of the keys ("pem" or "der")modulusLength
: the modulus length of the key (2048, 3072, or 4096 bits)
The function uses a switch
statement to determine which type of key to generate, and then creates an options object with the specified parameters. It then calls the crypto.generateKeyPairSync
function to generate the key pair, passing the options object.
In summary, this function generates an RSA or RSA-PSS key pair with customizable encryption size, password protection, output format, and modulus length.
Β
3. Cryptographic Hash
- π« Features: Cryptographic hashes are algorithms that take an input of any size and produce a fixed-size output, known as a hash. These are one-way, which means that the original message cannot be obtained from the hash. In addition, a small modification in the input produces a completely different hash.
- π« Applications: They are used to verify data integrity, in password authentication (storing the hash of the password instead of the password itself), and in blockchain technology to ensure the integrity of the blockchain.
Examples of Cryptographic Hash
Name | Description |
---|---|
π¦ SHA-256 | (Secure Hash Algorithm 256 bits) Part of the SHA-2 family, widely used in applications such as Bitcoin. |
π¦ MD5 | (Message-Digest Algorithm 5) Although it is fast, it is no longer recommended due to vulnerabilities found. |
π¦ Whirlpool | A hash algorithm that produces a 512-bit hash. |
Β
Cryptographic Hash Code Example
#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
This is a TypeScript function called hash
that generates a hash value for a given file. It takes three parameters:
algorithm
: the hash algorithm to use (e.g. "sha256", "md5", etc.)encoding
: the encoding to use for the resulting hash value (e.g. "hex", "base64", etc.)input
: the file for which the hash will be generated
The function uses the crypto
module to create a hash object, updates it with the contents of the input file, and returns the hash value in the specified encoding.
Β
4. Elliptic Curve Cryptography
- π« Features: Based on the arithmetic of elliptic curves over finite fields, it offers a high level of security with shorter keys compared to traditional asymmetric cryptography. This translates into faster operations and lower resource usage.
- π« Applications: It is widely used in mobile applications and devices with limited resources. It is also essential in the creation of cryptocurrencies, such as Bitcoin and Ethereum, to secure transactions and manage private keys.
Examples of Elliptic Curve
Name | Description |
---|---|
π¦ ECDSA | (Elliptic Curve Digital Signature Algorithm) Used to create digital signatures. |
π¦ ECDH | (Elliptic Curve Diffie-Hellman) A method for exchanging secret keys. |
Β
Elliptic Curve Code Example
#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 # Generates an ECDH key pair. 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 # Obtaining a shared key through ECDH 20 shared_key = private_key.exchange(public_key) 21 return shared_key 22 23 24def fibonacci_sequence(n): 25 # Generate a Fibonacci sequence up to the nth term. 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 the data with the key. 34 return bytes([b ^ key[i % len(key)] for i, b in enumerate(data)]) 35 36 37def encrypt(plaintext, public_key): 38 # Encrypt the plaintext using the public key and a Fibonacci sequence. 39 # Generates an asymmetric key randomly 40 symmetric_key = os.urandom(32) 41 42 # The shared key is obtained through ECDH 43 private_key, _ = generate_key_pair() # Generates a temporary private key 44 shared_key = derive_key(private_key, public_key) 45 46 # Generates a fibonacci key based on the length of the plaintext 47 fib_sequence = fibonacci_sequence(len(plaintext)) 48 49 # Adjusts the length of the combined key to match the plaintext 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 # Encrypts the plaintext with the combined key 54 encrypted_text = xor_encrypt(plaintext.encode(), combined_key) 55 56 return encrypted_text, private_key # Temporarily returns the private key 57 58 59def decrypt(encrypted_text, private_key, public_key): 60 """Decrypts the ciphertext using the private key and the public key.""" 61 # The shared key is obtained through ECDH 62 shared_key = derive_key(private_key, public_key) 63 64 # Generate a Fibonacci sequence based on the length of the ciphertext 65 fib_sequence = fibonacci_sequence(len(encrypted_text)) 66 67 # Adjusts the length of the combined key to match the ciphertext 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 # Decrypts the ciphertext with the combined key 72 decrypted_text = xor_encrypt(encrypted_text, combined_key) 73 74 return decrypted_text.decode(errors='ignore') # Ignores errors during decoding 75 76 77print("Enter a password to encrypt") 78 79passwd = input(": ") 80 81# Example of use 82# Phrase: -- 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
The above code was written in Python using calculation techniques using elliptic curve cryptography (specifically, the X25519 curve).
Install the dependencies and make sure to install the cryptography library correctly.
Example: We enter the word: Hello
Key generation process
- Private key: It is a randomly generated value that is kept secret. It is generated using the
X25519PrivateKey.generate()
method. - Public key: It is derived from the private key and can be shared openly. It is calculated as part of the key pair generation process.
Key generation example
- Run the
generate_key_pair()
function to create a private key and a public key. - The private key is a binary value that is not intended to be shared.
- The public key is derived from the private key and can be shared with others.
Example of output
If you were to run the program, you might see a result similar to this (the actual values will be different each time due to randomness):
- Private Key:
b'\x1a\x2b\x3c\x4d\x5e\x6f\...'
- Public Key:
b'\x9a\x8b\x7c\x6d\x5e\x4f\...'
Important note
The public and private keys are not derived from the "Hello" input, but are generated independently. The input is only used for the encryption and decryption processes after the keys have been generated.
Β
5. Quantum Cryptography
- π« Features: It takes advantage of the principles of quantum mechanics, such as quantum entanglement and uncertainty, to create communication systems that cannot be intercepted without being detected. It offers theoretically unconditional security.
- π« Applications: Although it is still in the early stages of development and implementation, it has the potential to revolutionize security in sensitive communications and in protection against the threats of quantum computing to traditional cryptography.
Examples of Quantum Cryptography
Name | Description |
---|---|
π¦ QKD | (Quantum Key Distribution) It allows two parties to generate a shared secret key using quantum particles. If a third party tries to intercept the key, this will alter the quantum state and will be detectable. |
This is still under development, but the main idea of quantum cryptography promises to revolutionize computer security by offering methods that are theoretically invulnerable to future attacks based on quantum computers
Quantum Cryptography Code Example
#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 generates random bits and bases 15 for _ in range(self.n_bits): 16 self.alice_bits.append(random.randint(0, 1)) # Random bit (0 or 1) 17 self.bases_alice.append(random.choice(['H', 'V'])) # Random basis (horizontal or vertical) 18 19 def simulate_bob_measurement(self): 20 # Bob randomly chooses bases to measure Alice's bits 21 for _ in range(self.n_bits): 22 self.bases_bob.append(random.choice(['H', 'V'])) 23 # Simulate the measurement (if the bases match, he gets the 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) # No bit if the bases do not match 28 29 def sift_key(self): 30 # Sift the key based on the matching bases 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# Example of use 43n_bits = 10 # Number of bits to exchange 44qkd_protocol = QKD(n_bits) 45secure_key = qkd_protocol.run_qkd_protocol() 46 47print("Shared secure key:", secure_key) 48
This classification reflects the diversity and depth of the field of cryptography, showing how its different techniques are applied to protect information in various contexts. From message encryption to the security of online transactions and user authentication, cryptography is essential for security in the digital world.
Β
Later I will show how these encryptions are broken and why md5 is very bad to use. In another entry we will review how AES encryption works.
Β
- π Access to the --> Blog
Thanks for reading
Β
Sources
- π KoΒ±cielny, C. (2005). AES with the increased confidentiality. Quasigroups and Related Systems, 13, 265-268.
- π Escobar Benet, M. (2015). Public and private key cryptography. RSA.
- π Dasso, A. (2017). RSA key length vs. computational power. In XIX Workshop of Researchers in Computer Science WICC 2017, ITBA, Buenos Aires