pwhash.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. # Copyright 2013 Donald Stufft and individual contributors
  2. #
  3. # Licensed under the Apache License, Version 2.0 (the "License");
  4. # you may not use this file except in compliance with the License.
  5. # You may obtain a copy of the License at
  6. #
  7. # http://www.apache.org/licenses/LICENSE-2.0
  8. #
  9. # Unless required by applicable law or agreed to in writing, software
  10. # distributed under the License is distributed on an "AS IS" BASIS,
  11. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. # See the License for the specific language governing permissions and
  13. # limitations under the License.
  14. from __future__ import absolute_import
  15. from __future__ import division
  16. import nacl.bindings
  17. import nacl.encoding
  18. import nacl.exceptions as exc
  19. from nacl.exceptions import ensure
  20. _strbytes_plus_one = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRBYTES
  21. SCRYPT_SALTBYTES = nacl.bindings.crypto_pwhash_scryptsalsa208sha256_SALTBYTES
  22. SCRYPT_PWHASH_SIZE = _strbytes_plus_one - 1
  23. SCRYPT_OPSLIMIT_INTERACTIVE = \
  24. nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_INTERACTIVE
  25. SCRYPT_MEMLIMIT_INTERACTIVE = \
  26. nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_INTERACTIVE
  27. SCRYPT_OPSLIMIT_SENSITIVE = \
  28. nacl.bindings.crypto_pwhash_scryptsalsa208sha256_OPSLIMIT_SENSITIVE
  29. SCRYPT_MEMLIMIT_SENSITIVE = \
  30. nacl.bindings.crypto_pwhash_scryptsalsa208sha256_MEMLIMIT_SENSITIVE
  31. def kdf_scryptsalsa208sha256(size, password, salt,
  32. opslimit=SCRYPT_OPSLIMIT_SENSITIVE,
  33. memlimit=SCRYPT_MEMLIMIT_SENSITIVE,
  34. encoder=nacl.encoding.RawEncoder):
  35. """
  36. Makes a key defined from ``password`` and ``salt`` that is
  37. ``size`` bytes long
  38. the enclosing module provides the constants
  39. - :py:const:`.SCRYPT_OPSLIMIT_INTERACTIVE`
  40. - :py:const:`.SCRYPT_MEMLIMIT_INTERACTIVE`
  41. - :py:const:`.SCRYPT_OPSLIMIT_SENSITIVE`
  42. - :py:const:`.SCRYPT_MEMLIMIT_SENSITIVE`
  43. as a guidance for correct settings respectively for the
  44. interactive login and the long term key protecting sensitive data
  45. use cases.
  46. :param int size: int
  47. :param bytes password: bytes
  48. :param bytes salt: bytes
  49. :param int opslimit:
  50. :param int memlimit:
  51. :rtype: bytes
  52. """
  53. ensure(len(salt) == SCRYPT_SALTBYTES,
  54. "The salt must be exactly %s, not %s bytes long" % (
  55. SCRYPT_SALTBYTES,
  56. len(salt)
  57. ),
  58. raising=exc.ValueError
  59. )
  60. n_log2, r, p = nacl.bindings.nacl_bindings_pick_scrypt_params(opslimit,
  61. memlimit)
  62. maxmem = memlimit + (2 ** 16)
  63. return encoder.encode(
  64. nacl.bindings.crypto_pwhash_scryptsalsa208sha256_ll(
  65. password, salt, 2 ** n_log2, r, p, maxmem=maxmem, dklen=size)
  66. )
  67. def scryptsalsa208sha256_str(password,
  68. opslimit=SCRYPT_OPSLIMIT_INTERACTIVE,
  69. memlimit=SCRYPT_MEMLIMIT_INTERACTIVE):
  70. """
  71. Hashes a password with a random salt, returning an ascii string
  72. that has all the needed info to check against a future password
  73. The default settings for opslimit and memlimit are those deemed
  74. correct for the interactive user login case.
  75. :param bytes password:
  76. :param int opslimit:
  77. :param int memlimit:
  78. :rtype: bytes
  79. """
  80. return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_str(password,
  81. opslimit,
  82. memlimit)
  83. def verify_scryptsalsa208sha256(password_hash, password):
  84. """
  85. Takes the output of scryptsalsa208sha256 and compares it against
  86. a user provided password to see if they are the same
  87. :param password_hash: bytes
  88. :param password: bytes
  89. :rtype: boolean
  90. """
  91. ensure(len(password_hash) == SCRYPT_PWHASH_SIZE,
  92. "The password hash must be exactly %s bytes long" %
  93. nacl.bindings.crypto_pwhash_scryptsalsa208sha256_STRBYTES,
  94. raising=exc.ValueError)
  95. return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_str_verify(
  96. password_hash, password
  97. )