- Deskripsi
- Fitur
- Requirements
- Instalasi
- Cara Penggunaan
- Penjelasan Algoritma
- Contoh Penggunaan
- Keamanan
- Troubleshooting
CryptoMultifungsi adalah aplikasi Python berbasis CLI (Command Line Interface) yang menyediakan implementasi berbagai algoritma kriptografi modern. Program ini dirancang untuk kebutuhan enkripsi data, hashing password, dan verifikasi integritas data dengan antarmuka yang user-friendly.
Aplikasi ini menggunakan library cryptography yang teruji dan bcrypt untuk password hashing, memastikan implementasi yang aman dan sesuai standar industri.
| Fitur | Tipe | Keterangan |
|---|---|---|
| Fernet | Enkripsi Simetris | Enkripsi symmetric key dengan format yang aman |
| RSA | Enkripsi Asimetris | Public-key cryptography dengan key size 2048-bit |
| SHA-256 | Hash Function | Menghasilkan message digest 256-bit |
| HMAC | Message Authentication | Verifikasi integritas dan autentikasi pesan |
| bcrypt | Password Hash | Hashing password dengan salt untuk keamanan maksimal |
- Python 3.7+
- Library:
cryptography>= 41.0.0bcrypt>= 4.0.0
git clone https://github.com/ALIF101XL/CryptoToolkit.git
cd CryptoToolkit && chmod 755 *.pypip install -r requirements.txtAtau manual install:
pip install cryptography bcryptpython crypto_multifungsi.pyJika berhasil, akan muncul menu utama program.
python crypto_multifungsi.py=== CRYPTO MULTIFUNGSI ===
1. Fernet (Simetris)
2. RSA (Asimetris)
3. SHA-256 Hash
4. HMAC
5. Password Hash (bcrypt)
6. Keluar
Pilih menu (1-6):
Pilih menu: 1
--- FERNET ---
1. Generate Key
2. Enkripsi
3. Deskripsi
Pilih: 1
Langkah:
- Generate Key → Simpan key dengan aman
- Gunakan key tersebut untuk enkripsi
- Gunakan key yang sama untuk dekripsi
Pilih menu: 2
--- RSA ---
1. Generate Key Pair
2. Enkripsi
3. Deskripsi
Pilih: 1
Langkah:
- Generate Key Pair (private & public key)
- Gunakan public key untuk enkripsi
- Gunakan private key untuk dekripsi
Pilih menu: 3
--- SHA-256 ---
Masukkan pesan: hello world
Hash SHA-256: a948904f2f0f479b8f8197694b30184b0d2ed1c1cd2a1ec0fb85d299a192145447
Pilih menu: 4
--- HMAC ---
Masukkan pesan: hello world
Masukkan kunci HMAC: secret_key
HMAC: 8b1a9953c4611296aed9e1fe...
Pilih menu: 5
--- PASSWORD HASH ---
1. Hash Password
2. Verifikasi Password
Pilih: 1
Masukkan password: MySecurePass123!
Hashed password: b'$2b$12$...'
Definisi: Enkripsi simetris yang menggunakan kunci yang sama untuk enkripsi dan dekripsi.
Karakteristik:
- Key Size: 256-bit
- Algoritma Dasar: AES-128 dalam mode CBC
- Timestamp: Includes timestamp dalam ciphertext (proteksi replay attack)
- Kecepatan: Sangat cepat
- Use Case: Enkripsi file, database, cookies
Keuntungan: ✅ Cepat dan efisien ✅ Built-in integrity checking ✅ Format standar dan aman
Kelemahan: ❌ Key harus dijaga rahasia ❌ Sulit untuk key distribution
Contoh Implementasi:
from cryptography.fernet import Fernet
# Generate key
key = Fernet.generate_key()
cipher = Fernet(key)
# Encrypt
ciphertext = cipher.encrypt(b"secret message")
# Decrypt
plaintext = cipher.decrypt(ciphertext)Definisi: Enkripsi public-key cryptography dengan dua kunci berbeda (public & private).
Karakteristik:
- Key Size: 2048-bit (industry standard)
- Public Exponent: 65537 (standard)
- Padding: OAEP (Optimal Asymmetric Encryption Padding)
- Hash Algorithm: SHA-256
- Kecepatan: Lebih lambat dari simetris
- Use Case: Digital signature, key distribution, secure communication
Keuntungan: ✅ Public key dapat dibagikan ✅ Tidak perlu pre-shared secret ✅ Cocok untuk multiple recipients
Kelemahan: ❌ Lebih lambat ❌ Key size lebih besar ❌ Hanya cocok untuk data kecil (<245 bytes untuk RSA-2048)
Contoh Implementasi:
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
# Generate keys
private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=2048
)
public_key = private_key.public_key()
# Encrypt dengan public key
ciphertext = public_key.encrypt(
b"secret",
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
# Decrypt dengan private key
plaintext = private_key.decrypt(ciphertext, padding.OAEP(...))Definisi: One-way hash function yang menghasilkan fixed-size output (256-bit).
Karakteristik:
- Output Size: 256-bit (64 karakter hex)
- One-Way: Tidak dapat di-reverse
- Collision Resistant: Sangat sulit menemukan 2 input dengan hash sama
- Deterministic: Input sama selalu menghasilkan output sama
- Sensitivity: Kecil perubahan input = besar perubahan output (avalanche effect)
Use Case:
- File integrity verification
- Digital signature
- Blockchain (Bitcoin)
- Password storage (jika dikombinasi dengan salt)
Tidak Cocok Untuk: ❌ Password hashing (gunakan bcrypt/argon2) ❌ Reverse engineering (bukan encryption)
Contoh:
Input: "hello"
Output: 2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824
Input: "hello1"
Output: ce06092fb48d9ffac7d1a376e404b26b7575bcc11ee05a4615feda8f553cc8e4
Definisi: Kombinasi hash function dengan secret key untuk verifikasi integritas dan autentikasi.
Karakteristik:
- Secret Key: Diperlukan untuk generate dan verify HMAC
- Algorithm: SHA-256
- Verifikasi: Sender & receiver harus tahu key yang sama
- Use Case: API authentication, message verification, session tokens
Keuntungan: ✅ Proteksi terhadap tampering ✅ Autentikasi pesan ✅ Lebih aman dari plain hash
Contoh Alur:
Pengirim:
message = "transaction data"
key = "secret_key"
hmac = HMAC(message, key)
kirim: message + hmac
Penerima:
terima: message + hmac
hitung: expected_hmac = HMAC(message, key)
if received_hmac == expected_hmac:
✅ Pesan authentic & tidak diubah
else:
❌ Pesan dipalsukan atau diubah
Definisi: Algorithm khusus password hashing dengan built-in salt dan adaptive cost factor.
Karakteristik:
- Salt: Generated otomatis & random setiap hash
- Work Factor: Dapat ditingkatkan seiring waktu
- Algorithm: Blowfish cipher derivative
- Output Format:
$2b$cost$salt$hash - Resistant: Brute force, rainbow table, GPU attack
Contoh bcrypt Hash:
$2b$12$R9h7cIPz0gi.URNNX3kh2OPST9EYWckgx3/bdGHC7TN6xJnvUx2WG
│ │ │ │ │
│ │ │ └─ Salt (22 chars) └─ Hash (31 chars)
│ │ └─ Cost Factor (12 = 2^12 iterations)
│ └─ Format (2b = bcrypt)
└─ Identifier ($2b$)
Keuntungan: ✅ Built-in salt protection ✅ Adaptif terhadap hardware improvement ✅ Khusus dirancang untuk password ✅ Tahan terhadap GPU/FPGA attacks
Kelemahan: ❌ Lebih lambat (by design) ❌ Limit input hingga 72 bytes
Cost Factor:
- Cost 10: ~10ms
- Cost 12: ~250ms (recommended)
- Cost 14: ~6.5 seconds
crypto = CryptoMultifungsi()
# 1. Generate key
key = crypto.generate_fernet_key()
print(f"Simpan key ini: {key.decode()}")
# 2. Encrypt file content
dengan open('sensitive_data.txt', 'r') as f:
data = f.read()
encrypted = crypto.encrypt_fernet(data)
# 3. Simpan encrypted file
dengan open('sensitive_data.enc', 'wb') as f:
f.write(encrypted)
# 4. Nanti, untuk decrypt
dengan open('sensitive_data.enc', 'rb') as f:
encrypted_data = f.read()
decrypted = crypto.decrypt_fernet(encrypted_data)
print(decrypted)crypto = CryptoMultifungsi()
# Alice generates key pair
alice_private, alice_public = crypto.generate_rsa_keys()
# Bob dapat public key Alice
bob_ciphertext = crypto.encrypt_rsa("Pesan rahasia untuk Alice")
# Alice decrypt dengan private key-nya
alice_message = crypto.decrypt_rsa(bob_ciphertext)
print(alice_message) # "Pesan rahasia untuk Alice"crypto = CryptoMultifungsi()
# Registration - hash password
password = "MySecurePassword123!"
hashed_pwd = crypto.hash_password(password)
# Simpan hashed_pwd di database
# Login - verify password
input_pwd = "MySecurePassword123!"
jika crypto.verify_password(input_pwd, hashed_pwd):
print("✅ Login berhasil")
else:
print("❌ Password salah")crypto = CryptoMultifungsi()
# Server generate HMAC untuk API request
api_secret = "api_secret_key_12345"
request_data = '{"user_id": 123, "action": "transfer", "amount": 5000}'
hmac_signature = crypto.create_hmac(request_data, api_secret)
# Client verifikasi
received_hmac = "8b1a9953c4611296aed9e1fe..."
expected_hmac = crypto.create_hmac(request_data, api_secret)
jika received_hmac == expected_hmac:
print("✅ Request verified & authentic")crypto = CryptoMultifungsi()
# 1. Pengirim mengirim file + hash
dengan open('document.pdf', 'rb') as f:
file_data = f.read()
file_hash = crypto.hash_sha256(file_data.decode('latin1'))
print(f"SHA-256: {file_hash}")
# 2. Penerima verify
received_hash = "abc123def456..."
dengan open('document.pdf', 'rb') as f:
received_file = f.read()
computed_hash = crypto.hash_sha256(received_file.decode('latin1'))
jika computed_hash == received_hash:
print("✅ File tidak berubah")
else:
print("❌ File telah dimodifikasi!")# ❌ JANGAN - hardcode key
SECRET_KEY = "my_secret_key_12345"
# ✅ LAKUKAN - load dari environment variable
SECRET_KEY = os.getenv('FERNET_KEY')
# ✅ LAKUKAN - simpan di file terpisah dengan restricted permission
with open('/etc/app/keys.conf', 'r') as f:
SECRET_KEY = f.read()# ❌ JANGAN - gunakan plain SHA256 untuk password
hashed = hashlib.sha256(password.encode()).hexdigest()
# ✅ LAKUKAN - gunakan bcrypt
hashed = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))# ✅ Simpan private key dengan encryption & strict permission
from cryptography.hazmat.primitives import serialization
pem = private_key.private_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PrivateFormat.PKCS8,
encryption_algorithm=serialization.BestAvailableEncryption(b"passphrase")
)
# File permission: 600 (user only)
os.chmod('private_key.pem', 0o600)# ✅ Validate input sebelum encrypt
def encrypt_safe(self, plaintext):
if not isinstance(plaintext, str):
raise TypeError("Input harus string")
if len(plaintext) > 10000:
raise ValueError("Input terlalu panjang")
return self.encrypt_fernet(plaintext)# ✅ Gunakan constant-time comparison
import hmac
# ❌ JANGAN
if received_hmac == computed_hmac:
pass
# ✅ LAKUKAN
if hmac.compare_digest(received_hmac, computed_hmac):
print("Valid")| Metode | Kegunaan | Keamanan | Kecepatan |
|---|---|---|---|
| Fernet | Enkripsi data at-rest | Sangat Aman | Cepat ⭐⭐⭐⭐ |
| RSA | Key distribution, signature | Sangat Aman | Lambat ⭐⭐ |
| SHA-256 | Integrity check | Aman (bukan password) | Cepat ⭐⭐⭐⭐⭐ |
| HMAC | Message authentication | Sangat Aman | Cepat ⭐⭐⭐⭐ |
| bcrypt | Password hashing | Sangat Aman | Lambat ⭐⭐ |
Solusi:
pip install --upgrade cryptography bcryptPenyebab: Mencoba decrypt tanpa generate key terlebih dahulu
Solusi:
crypto = CryptoMultifungsi()
# 1. Generate key dulu
crypto.generate_fernet_key()
# 2. Baru encrypt/decrypt
ciphertext = crypto.encrypt_fernet("data")Penyebab: Mencoba decrypt RSA tanpa generate key pair
Solusi:
crypto = CryptoMultifungsi()
# 1. Generate RSA key pair
crypto.generate_rsa_keys()
# 2. Baru encrypt/decrypt
ciphertext = crypto.encrypt_rsa("data")Penyebab: Format input ciphertext salah
Solusi:
- Gunakan
repr()untuk display ciphertext dengan format benar - Copy output dengan format
b'...'untuk input decrypt
# Generate ciphertext
ciphertext = crypto.encrypt_rsa("test")
print(repr(ciphertext)) # Output: b'\x00\x01\x02...'
# Input ke program: b'\x00\x01\x02...'Penyebab: Format input hash salah
Solusi:
# Program akan print hash dalam format: b'$2b$12$...'
# Input ke program: b'$2b$12$...'Keterangan: Ini normal. bcrypt output selalu 60 karakter termasuk salt dan cost factor.
$2b$12$R9h7cIPz0gi.URNNX3kh2OPST9EYWckgx3/bdGHC7TN6xJnvUx2WG
└─────────────────────────────────────────────────────────────┘
60 characters
- cryptography.io Documentation
- bcrypt Documentation
- OWASP Cryptographic Cheat Sheet
- SHA-2 NIST Standard
- RSA Specification
Project ini tersedia untuk keperluan edukatif dan personal. Gunakan dengan bertanggung jawab.
-
Pahami konsep sebelum implementasi
- Baca tentang symmetric vs asymmetric encryption
- Pahami perbedaan hashing vs encryption
-
Eksperimen dengan data kecil dulu
- Test dengan string pendek
- Naikkan complexity secara bertahap
-
Jaga keamanan key
- Jangan commit key ke git
- Gunakan environment variable
- Rotate key secara berkala
-
Monitor performa
- RSA lebih lambat dari Fernet
- bcrypt intentionally slow untuk security
- Pilih sesuai kebutuhan
-
Stay updated
- Update library cryptography & bcrypt
- Ikuti security advisories
- Research algoritma baru
Last Updated: June 2026 Status: Active Development
import hashlib
import hmac
import os
import sys
from cryptography.fernet import Fernet
from cryptography.hazmat.primitives.asymmetric import rsa, padding
from cryptography.hazmat.primitives import hashes
import bcrypt
class CryptoMultifungsi:
def __init__(self):
self.fernet_key = None
self.rsa_private_key = None
self.rsa_public_key = None
def generate_fernet_key(self):
self.fernet_key = Fernet.generate_key()
return self.fernet_key
def encrypt_fernet(self, plaintext):
if not self.fernet_key:
self.generate_fernet_key()
cipher = Fernet(self.fernet_key)
return cipher.encrypt(plaintext.encode())
def decrypt_fernet(self, ciphertext):
if not self.fernet_key:
print("Key belum di-generate, tolol!")
return None
cipher = Fernet(self.fernet_key)
return cipher.decrypt(ciphertext).decode()
def generate_rsa_keys(self):
self.rsa_private_key = rsa.generate_private_key(
public_exponent=65537,
key_size=4096
)
self.rsa_public_key = self.rsa_private_key.public_key()
return self.rsa_private_key, self.rsa_public_key
def encrypt_rsa(self, plaintext):
if not self.rsa_public_key:
self.generate_rsa_keys()
return self.rsa_public_key.encrypt(
plaintext.encode(),
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
)
def decrypt_rsa(self, ciphertext):
if not self.rsa_private_key:
print("Private key belum ada, goblok!")
return None
return self.rsa_private_key.decrypt(
ciphertext,
padding.OAEP(
mgf=padding.MGF1(algorithm=hashes.SHA256()),
algorithm=hashes.SHA256(),
label=None
)
).decode()
def hash_sha256(self, message):
return hashlib.sha256(message.encode()).hexdigest()
def create_hmac(self, message, key):
return hmac.new(key.encode(), message.encode(), hashlib.sha256).hexdigest()
def hash_password(self, password):
return bcrypt.hashpw(password.encode(), bcrypt.gensalt())
def verify_password(self, password, hashed):
return bcrypt.checkpw(password.encode(), hashed)
def main():
crypto = CryptoMultifungsi()
while True:
print("\n=== CRYPTO MULTIFUNGSI ===")
print("1. Fernet (Simetris)")
print("2. RSA (Asimetris)")
print("3. SHA-256 Hash")
print("4. HMAC")
print("5. Password Hash (bcrypt)")
print("6. Keluar")
pilihan = input("Pilih menu (1-6): ")
if pilihan == "1":
print("\n--- FERNET ---")
print("1. Generate Key")
print("2. Enkripsi")
print("3. Deskripsi")
sub_pilihan = input("Pilih: ")
if sub_pilihan == "1":
key = crypto.generate_fernet_key()
print(f"Key: {key.decode()}")
elif sub_pilihan == "2":
plaintext = input("Masukkan teks: ")
hasil = crypto.encrypt_fernet(plaintext)
print(f"Hasil enkripsi: {hasil.decode()}")
elif sub_pilihan == "3":
ciphertext = input("Masukkan teks terenkripsi: ")
hasil = crypto.decrypt_fernet(ciphertext)
if hasil:
print(f"Hasil deskripsi: {hasil}")
elif pilihan == "2":
print("\n--- RSA ---")
print("1. Generate Key Pair")
print("2. Enkripsi")
print("3. Deskripsi")
sub_pilihan = input("Pilih: ")
if sub_pilihan == "1":
crypto.generate_rsa_keys()
print("Key pair berhasil di-generate!")
elif sub_pilihan == "2":
plaintext = input("Masukkan teks: ")
hasil = crypto.encrypt_rsa(plaintext)
print(f"Hasil enkripsi: {hasil}")
elif sub_pilihan == "3":
ciphertext = input("Masukkan ciphertext (bytes): ")
# Convert string input to bytes
try:
ciphertext_bytes = eval(ciphertext)
hasil = crypto.decrypt_rsa(ciphertext_bytes)
print(f"Hasil deskripsi: {hasil}")
except:
print("Input tidak valid, goblok!")
elif pilihan == "3":
print("\n--- SHA-256 ---")
message = input("Masukkan pesan: ")
hash_result = crypto.hash_sha256(message)
print(f"Hash SHA-256: {hash_result}")
elif pilihan == "4":
print("\n--- HMAC ---")
message = input("Masukkan pesan: ")
key = input("Masukkan kunci HMAC: ")
hmac_result = crypto.create_hmac(message, key)
print(f"HMAC: {hmac_result}")
elif pilihan == "5":
print("\n--- PASSWORD HASH ---")
print("1. Hash Password")
print("2. Verifikasi Password")
sub_pilihan = input("Pilih: ")
if sub_pilihan == "1":
password = input("Masukkan password: ")
hashed = crypto.hash_password(password)
print(f"Hashed password: {hashed}")
elif sub_pilihan == "2":
password = input("Masukkan password: ")
hashed = input("Masukkan hash (bytes): ")
try:
hashed_bytes = eval(hashed)
if crypto.verify_password(password, hashed_bytes):
print("Password cocok!")
else:
print("Password salah!")
except:
print("Input hash tidak valid!")
elif pilihan == "6":
print("Keluar dari program. Jangan lupa belajar lebih banyak, bangsat!")
sys.exit()
else:
print("Pilihan tidak valid, tolol!")
if __name__ == "__main__":
main()