You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

194 lines
6.7 KiB

  1. """passlib.pbkdf2 - PBKDF2 support
  2. this module is getting increasingly poorly named.
  3. maybe rename to "kdf" since it's getting more key derivation functions added.
  4. """
  5. #=============================================================================
  6. # imports
  7. #=============================================================================
  8. from __future__ import division
  9. # core
  10. import logging; log = logging.getLogger(__name__)
  11. # site
  12. # pkg
  13. from passlib.exc import ExpectedTypeError
  14. from passlib.utils.decor import deprecated_function
  15. from passlib.utils.compat import native_string_types
  16. from passlib.crypto.digest import norm_hash_name, lookup_hash, pbkdf1 as _pbkdf1, pbkdf2_hmac, compile_hmac
  17. # local
  18. __all__ = [
  19. # hash utils
  20. "norm_hash_name",
  21. # prf utils
  22. "get_prf",
  23. # kdfs
  24. "pbkdf1",
  25. "pbkdf2",
  26. ]
  27. #=============================================================================
  28. # issue deprecation warning for module
  29. #=============================================================================
  30. from warnings import warn
  31. warn("the module 'passlib.utils.pbkdf2' is deprecated as of Passlib 1.7, "
  32. "and will be removed in Passlib 2.0, please use 'passlib.crypto' instead",
  33. DeprecationWarning)
  34. #=============================================================================
  35. # hash helpers
  36. #=============================================================================
  37. norm_hash_name = deprecated_function(deprecated="1.7", removed="1.8", func_module=__name__,
  38. replacement="passlib.crypto.digest.norm_hash_name")(norm_hash_name)
  39. #=============================================================================
  40. # prf lookup
  41. #=============================================================================
  42. #: cache mapping prf name/func -> (func, digest_size)
  43. _prf_cache = {}
  44. #: list of accepted prefixes
  45. _HMAC_PREFIXES = ("hmac_", "hmac-")
  46. def get_prf(name):
  47. """Lookup pseudo-random family (PRF) by name.
  48. :arg name:
  49. This must be the name of a recognized prf.
  50. Currently this only recognizes names with the format
  51. :samp:`hmac-{digest}`, where :samp:`{digest}`
  52. is the name of a hash function such as
  53. ``md5``, ``sha256``, etc.
  54. todo: restore text about callables.
  55. :raises ValueError: if the name is not known
  56. :raises TypeError: if the name is not a callable or string
  57. :returns:
  58. a tuple of :samp:`({prf_func}, {digest_size})`, where:
  59. * :samp:`{prf_func}` is a function implementing
  60. the specified PRF, and has the signature
  61. ``prf_func(secret, message) -> digest``.
  62. * :samp:`{digest_size}` is an integer indicating
  63. the number of bytes the function returns.
  64. Usage example::
  65. >>> from passlib.utils.pbkdf2 import get_prf
  66. >>> hmac_sha256, dsize = get_prf("hmac-sha256")
  67. >>> hmac_sha256
  68. <function hmac_sha256 at 0x1e37c80>
  69. >>> dsize
  70. 32
  71. >>> digest = hmac_sha256('password', 'message')
  72. .. deprecated:: 1.7
  73. This function is deprecated, and will be removed in Passlib 2.0.
  74. This only related replacement is :func:`passlib.crypto.digest.compile_hmac`.
  75. """
  76. global _prf_cache
  77. if name in _prf_cache:
  78. return _prf_cache[name]
  79. if isinstance(name, native_string_types):
  80. if not name.startswith(_HMAC_PREFIXES):
  81. raise ValueError("unknown prf algorithm: %r" % (name,))
  82. digest = lookup_hash(name[5:]).name
  83. def hmac(key, msg):
  84. return compile_hmac(digest, key)(msg)
  85. record = (hmac, hmac.digest_info.digest_size)
  86. elif callable(name):
  87. # assume it's a callable, use it directly
  88. digest_size = len(name(b'x', b'y'))
  89. record = (name, digest_size)
  90. else:
  91. raise ExpectedTypeError(name, "str or callable", "prf name")
  92. _prf_cache[name] = record
  93. return record
  94. #=============================================================================
  95. # pbkdf1 support
  96. #=============================================================================
  97. def pbkdf1(secret, salt, rounds, keylen=None, hash="sha1"):
  98. """pkcs#5 password-based key derivation v1.5
  99. :arg secret: passphrase to use to generate key
  100. :arg salt: salt string to use when generating key
  101. :param rounds: number of rounds to use to generate key
  102. :arg keylen: number of bytes to generate (if ``None``, uses digest's native size)
  103. :param hash:
  104. hash function to use. must be name of a hash recognized by hashlib.
  105. :returns:
  106. raw bytes of generated key
  107. .. note::
  108. This algorithm has been deprecated, new code should use PBKDF2.
  109. Among other limitations, ``keylen`` cannot be larger
  110. than the digest size of the specified hash.
  111. .. deprecated:: 1.7
  112. This has been relocated to :func:`passlib.crypto.digest.pbkdf1`,
  113. and this version will be removed in Passlib 2.0.
  114. *Note the call signature has changed.*
  115. """
  116. return _pbkdf1(hash, secret, salt, rounds, keylen)
  117. #=============================================================================
  118. # pbkdf2
  119. #=============================================================================
  120. def pbkdf2(secret, salt, rounds, keylen=None, prf="hmac-sha1"):
  121. """pkcs#5 password-based key derivation v2.0
  122. :arg secret:
  123. passphrase to use to generate key
  124. :arg salt:
  125. salt string to use when generating key
  126. :param rounds:
  127. number of rounds to use to generate key
  128. :arg keylen:
  129. number of bytes to generate.
  130. if set to ``None``, will use digest size of selected prf.
  131. :param prf:
  132. psuedo-random family to use for key strengthening.
  133. this must be a string starting with ``"hmac-"``, followed by the name of a known digest.
  134. this defaults to ``"hmac-sha1"`` (the only prf explicitly listed in
  135. the PBKDF2 specification)
  136. .. rst-class:: warning
  137. .. versionchanged 1.7:
  138. This argument no longer supports arbitrary PRF callables --
  139. These were rarely / never used, and created too many unwanted codepaths.
  140. :returns:
  141. raw bytes of generated key
  142. .. deprecated:: 1.7
  143. This has been deprecated in favor of :func:`passlib.crypto.digest.pbkdf2_hmac`,
  144. and will be removed in Passlib 2.0. *Note the call signature has changed.*
  145. """
  146. if callable(prf) or (isinstance(prf, native_string_types) and not prf.startswith(_HMAC_PREFIXES)):
  147. raise NotImplementedError("non-HMAC prfs are not supported as of Passlib 1.7")
  148. digest = prf[5:]
  149. return pbkdf2_hmac(digest, secret, salt, rounds, keylen)
  150. #=============================================================================
  151. # eof
  152. #=============================================================================