bcrypt.py 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748
  1. import secrets
  2. import string
  3. from core.base import CryptoConfig, CryptoProvider
  4. class BCryptConfig(CryptoConfig):
  5. provider: str = "bcrypt"
  6. salt_rounds: int = 12
  7. def validate_config(self) -> None: # type: ignore
  8. super().validate_config()
  9. if self.salt_rounds < 4 or self.salt_rounds > 31:
  10. raise ValueError("salt_rounds must be between 4 and 31")
  11. class BCryptProvider(CryptoProvider):
  12. def __init__(self, config: BCryptConfig):
  13. try:
  14. import bcrypt
  15. self.bcrypt = bcrypt
  16. except ImportError:
  17. raise ImportError("bcrypt must be installed to use BCryptProvider")
  18. if not isinstance(config, BCryptConfig):
  19. raise ValueError(
  20. "BCryptProvider must be initialized with a BCryptConfig"
  21. )
  22. super().__init__(config)
  23. self.config: BCryptConfig = config
  24. def get_password_hash(self, password: str) -> str:
  25. return self.bcrypt.hashpw(
  26. password.encode("utf-8"),
  27. self.bcrypt.gensalt(rounds=self.config.salt_rounds),
  28. ).decode("utf-8")
  29. def verify_password(
  30. self, plain_password: str, hashed_password: str
  31. ) -> bool:
  32. return self.bcrypt.checkpw(
  33. plain_password.encode("utf-8"), hashed_password.encode("utf-8")
  34. )
  35. def generate_verification_code(self, length: int = 32) -> str:
  36. alphabet = string.ascii_letters + string.digits
  37. return "".join(secrets.choice(alphabet) for _ in range(length))