satupeta-main/app/utils/encryption.py

67 lines
1.8 KiB
Python
Raw Normal View History

2026-01-27 02:11:58 +00:00
import base64
import json
import os
from typing import Dict
from cryptography.fernet import Fernet
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes
from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC
from app.core.config import settings
class CredentialEncryption:
"""
Kelas untuk mengenkripsi dan mendekripsi data kredensial.
Menggunakan Fernet (implementasi AES-128-CBC) dengan salt dan PBKDF2
untuk meningkatkan keamanan.
"""
def __init__(self):
self.master_key = settings.SECRET_KEY
def _derive_key(self, salt):
master_key_bytes = self.master_key.encode()
kdf = PBKDF2HMAC(algorithm=hashes.SHA256(), length=32, salt=salt, iterations=100000, backend=default_backend())
key = base64.urlsafe_b64encode(kdf.derive(master_key_bytes))
return key
def encrypt(self, data):
iv = os.urandom(16)
iv_b64 = base64.b64encode(iv).decode("utf-8")
key = self._derive_key(iv)
cipher = Fernet(key)
data_json = json.dumps(data)
encrypted_data = cipher.encrypt(data_json.encode("utf-8"))
encrypted_b64 = base64.b64encode(encrypted_data).decode("utf-8")
return encrypted_b64, iv_b64
def decrypt(self, encrypted_data, iv) -> Dict:
try:
encrypted_bytes = base64.b64decode(encrypted_data)
iv_bytes = base64.b64decode(iv)
key = self._derive_key(iv_bytes)
cipher = Fernet(key)
decrypted_data = cipher.decrypt(encrypted_bytes)
decrypted_str = decrypted_data.decode("utf-8")
data = json.loads(decrypted_str)
return data
except Exception as e:
raise e
# Inisialisasi singleton instance
credential_encryption = CredentialEncryption()