pbkdf2.py 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. # This file is dual licensed under the terms of the Apache License, Version
  2. # 2.0, and the BSD License. See the LICENSE file in the root of this repository
  3. # for complete details.
  4. import typing
  5. from cryptography import utils
  6. from cryptography.exceptions import (
  7. AlreadyFinalized,
  8. InvalidKey,
  9. UnsupportedAlgorithm,
  10. _Reasons,
  11. )
  12. from cryptography.hazmat.primitives import constant_time, hashes
  13. from cryptography.hazmat.primitives.kdf import KeyDerivationFunction
  14. class PBKDF2HMAC(KeyDerivationFunction):
  15. def __init__(
  16. self,
  17. algorithm: hashes.HashAlgorithm,
  18. length: int,
  19. salt: bytes,
  20. iterations: int,
  21. backend: typing.Any = None,
  22. ):
  23. from cryptography.hazmat.backends.openssl.backend import (
  24. backend as ossl,
  25. )
  26. if not ossl.pbkdf2_hmac_supported(algorithm):
  27. raise UnsupportedAlgorithm(
  28. "{} is not supported for PBKDF2 by this backend.".format(
  29. algorithm.name
  30. ),
  31. _Reasons.UNSUPPORTED_HASH,
  32. )
  33. self._used = False
  34. self._algorithm = algorithm
  35. self._length = length
  36. utils._check_bytes("salt", salt)
  37. self._salt = salt
  38. self._iterations = iterations
  39. def derive(self, key_material: bytes) -> bytes:
  40. if self._used:
  41. raise AlreadyFinalized("PBKDF2 instances can only be used once.")
  42. self._used = True
  43. utils._check_byteslike("key_material", key_material)
  44. from cryptography.hazmat.backends.openssl.backend import backend
  45. return backend.derive_pbkdf2_hmac(
  46. self._algorithm,
  47. self._length,
  48. self._salt,
  49. self._iterations,
  50. key_material,
  51. )
  52. def verify(self, key_material: bytes, expected_key: bytes) -> None:
  53. derived_key = self.derive(key_material)
  54. if not constant_time.bytes_eq(derived_key, expected_key):
  55. raise InvalidKey("Keys do not match.")