Cryptography là gì?
Cryptography là nghệ thuật bảo vệ thông tin bằng cách chuyển đổi thành dạng không đọc được (mã hóa) và chỉ có thể đọc lại bằng key đúng (giải mã).
Cài đặt
pip install cryptography
Hashing
Hashing là quá trình một chiều - không thể “giải mã” hash value.
import hashlib
# MD5 (không nên dùng cho security)
text = "Hello, PION!"
md5_hash = hashlib.md5(text.encode()).hexdigest()
print(f"MD5: {md5_hash}")
# SHA-256 (khuyến nghị)
sha256_hash = hashlib.sha256(text.encode()).hexdigest()
print(f"SHA256: {sha256_hash}")
# SHA-512
sha512_hash = hashlib.sha512(text.encode()).hexdigest()
print(f"SHA512: {sha512_hash}")
# Hash file
def hash_file(filepath: str, algorithm: str = "sha256") -> str:
"""Calculate hash of a file."""
hash_func = hashlib.new(algorithm)
with open(filepath, "rb") as f:
for chunk in iter(lambda: f.read(8192), b""):
hash_func.update(chunk)
return hash_func.hexdigest()
# Usage
file_hash = hash_file("document.pdf")
print(f"File hash: {file_hash}")
Password Hashing
Sử dụng bcrypt hoặc argon2 cho passwords:
import bcrypt
# Hash password
password = "my_secure_password"
salt = bcrypt.gensalt()
hashed = bcrypt.hashpw(password.encode(), salt)
print(f"Hashed: {hashed}")
# Verify password
def check_password(password: str, hashed: bytes) -> bool:
return bcrypt.checkpw(password.encode(), hashed)
# Usage
if check_password("my_secure_password", hashed):
print("Password correct!")
else:
print("Wrong password!")
Symmetric Encryption (Fernet)
Cùng key dùng để encrypt và decrypt:
from cryptography.fernet import Fernet
# Generate key
key = Fernet.generate_key()
print(f"Key: {key.decode()}")
# Save key to file
with open("secret.key", "wb") as f:
f.write(key)
# Load key
with open("secret.key", "rb") as f:
key = f.read()
# Create cipher
cipher = Fernet(key)
# Encrypt
message = "This is a secret message"
encrypted = cipher.encrypt(message.encode())
print(f"Encrypted: {encrypted}")
# Decrypt
decrypted = cipher.decrypt(encrypted)
print(f"Decrypted: {decrypted.decode()}")
File Encryption
from cryptography.fernet import Fernet
from pathlib import Path
def encrypt_file(filepath: str, key: bytes) -> str:
"""Encrypt a file."""
cipher = Fernet(key)
with open(filepath, "rb") as f:
data = f.read()
encrypted = cipher.encrypt(data)
encrypted_path = filepath + ".encrypted"
with open(encrypted_path, "wb") as f:
f.write(encrypted)
return encrypted_path
def decrypt_file(filepath: str, key: bytes) -> str:
"""Decrypt a file."""
cipher = Fernet(key)
with open(filepath, "rb") as f:
encrypted = f.read()
decrypted = cipher.decrypt(encrypted)
# Remove .encrypted extension
original_path = filepath.replace(".encrypted", "")
with open(original_path, "wb") as f:
f.write(decrypted)
return original_path
# Usage
key = Fernet.generate_key()
encrypt_file("secret.txt", key)
decrypt_file("secret.txt.encrypted", key)
AES Encryption
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
import os
def aes_encrypt(plaintext: bytes, key: bytes) -> tuple:
"""Encrypt using AES-256-CBC."""
# Generate random IV
iv = os.urandom(16)
# Create cipher
cipher = Cipher(
algorithms.AES(key),
modes.CBC(iv),
backend=default_backend()
)
# Pad plaintext to block size
padding_length = 16 - (len(plaintext) % 16)
padded = plaintext + bytes([padding_length] * padding_length)
# Encrypt
encryptor = cipher.encryptor()
ciphertext = encryptor.update(padded) + encryptor.finalize()
return iv, ciphertext
def aes_decrypt(iv: bytes, ciphertext: bytes, key: bytes) -> bytes:
"""Decrypt AES-256-CBC."""
cipher = Cipher(
algorithms.AES(key),
modes.CBC(iv),
backend=default_backend()
)
decryptor = cipher.decryptor()
padded = decryptor.update(ciphertext) + decryptor.finalize()
# Remove padding
padding_length = padded[-1]
plaintext = padded[:-padding_length]
return plaintext
# Usage
key = os.urandom(32) # 256-bit key
message = b"Secret message"
iv, encrypted = aes_encrypt(message, key)
decrypted = aes_decrypt(iv, encrypted, key)
print(decrypted.decode())
Asymmetric Encryption (RSA)
Dùng public key để encrypt, private key để decrypt:
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes, serialization
# Generate key pair
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
public_key = private_key.public_key()
# Save private key
with open("private_key.pem", "wb") as f:
f.write(private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.NoEncryption()
))
# Save public key
with open("public_key.pem", "wb") as f:
f.write(public_key.public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
))
# Encrypt với public key
message = b"Secret message"
ciphertext = public_key.encrypt(
message,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Decrypt với private key
plaintext = private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
print(plaintext.decode())
Digital Signatures
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
# Generate key pair
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
public_key = private_key.public_key()
# Sign message
message = b"This is an important document"
signature = private_key.sign(
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
# Verify signature
try:
public_key.verify(
signature,
message,
padding.PSS(
mgf=padding.MGF1(hashes.SHA256()),
salt_length=padding.PSS.MAX_LENGTH
),
hashes.SHA256()
)
print("Signature is valid!")
except:
print("Invalid signature!")
Ứng dụng: Simple Encryption Tool
#!/usr/bin/env python3
"""
Simple file encryption tool
"""
import argparse
from cryptography.fernet import Fernet
from pathlib import Path
def generate_key() -> bytes:
return Fernet.generate_key()
def encrypt_file(filepath: str, key: bytes):
cipher = Fernet(key)
with open(filepath, "rb") as f:
data = f.read()
encrypted = cipher.encrypt(data)
with open(filepath + ".enc", "wb") as f:
f.write(encrypted)
print(f"Encrypted: {filepath}.enc")
def decrypt_file(filepath: str, key: bytes):
cipher = Fernet(key)
with open(filepath, "rb") as f:
data = f.read()
decrypted = cipher.decrypt(data)
output = filepath.replace(".enc", "")
with open(output, "wb") as f:
f.write(decrypted)
print(f"Decrypted: {output}")
def main():
parser = argparse.ArgumentParser(description="File Encryption Tool")
parser.add_argument("action", choices=["generate", "encrypt", "decrypt"])
parser.add_argument("-f", "--file", help="File to encrypt/decrypt")
parser.add_argument("-k", "--key", help="Key file")
args = parser.parse_args()
if args.action == "generate":
key = generate_key()
with open("encryption.key", "wb") as f:
f.write(key)
print("Key saved to encryption.key")
elif args.action in ["encrypt", "decrypt"]:
with open(args.key, "rb") as f:
key = f.read()
if args.action == "encrypt":
encrypt_file(args.file, key)
else:
decrypt_file(args.file, key)
if __name__ == "__main__":
main()
Bước tiếp theo
Tiếp theo:
- Password Tools: Generators và crackers
- Packet Sniffing: Phân tích network traffic
⚠️ Security tip: Không bao giờ hardcode keys trong code. Sử dụng environment variables hoặc key management systems!