hashlib.py 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. # Copyright 2016-2019 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. import binascii
  15. from typing import NoReturn
  16. import nacl.bindings
  17. from nacl.utils import bytes_as_string
  18. BYTES = nacl.bindings.crypto_generichash_BYTES
  19. BYTES_MIN = nacl.bindings.crypto_generichash_BYTES_MIN
  20. BYTES_MAX = nacl.bindings.crypto_generichash_BYTES_MAX
  21. KEYBYTES = nacl.bindings.crypto_generichash_KEYBYTES
  22. KEYBYTES_MIN = nacl.bindings.crypto_generichash_KEYBYTES_MIN
  23. KEYBYTES_MAX = nacl.bindings.crypto_generichash_KEYBYTES_MAX
  24. SALTBYTES = nacl.bindings.crypto_generichash_SALTBYTES
  25. PERSONALBYTES = nacl.bindings.crypto_generichash_PERSONALBYTES
  26. SCRYPT_AVAILABLE = nacl.bindings.has_crypto_pwhash_scryptsalsa208sha256
  27. _b2b_init = nacl.bindings.crypto_generichash_blake2b_init
  28. _b2b_final = nacl.bindings.crypto_generichash_blake2b_final
  29. _b2b_update = nacl.bindings.crypto_generichash_blake2b_update
  30. class blake2b:
  31. """
  32. :py:mod:`hashlib` API compatible blake2b algorithm implementation
  33. """
  34. MAX_DIGEST_SIZE = BYTES
  35. MAX_KEY_SIZE = KEYBYTES_MAX
  36. PERSON_SIZE = PERSONALBYTES
  37. SALT_SIZE = SALTBYTES
  38. def __init__(
  39. self,
  40. data: bytes = b"",
  41. digest_size: int = BYTES,
  42. key: bytes = b"",
  43. salt: bytes = b"",
  44. person: bytes = b"",
  45. ):
  46. """
  47. :py:class:`.blake2b` algorithm initializer
  48. :param data:
  49. :type data: bytes
  50. :param int digest_size: the requested digest size; must be
  51. at most :py:attr:`.MAX_DIGEST_SIZE`;
  52. the default digest size is :py:data:`.BYTES`
  53. :param key: the key to be set for keyed MAC/PRF usage; if set,
  54. the key must be at most :py:data:`.KEYBYTES_MAX` long
  55. :type key: bytes
  56. :param salt: a initialization salt at most
  57. :py:attr:`.SALT_SIZE` long; it will be zero-padded
  58. if needed
  59. :type salt: bytes
  60. :param person: a personalization string at most
  61. :py:attr:`.PERSONAL_SIZE` long; it will be zero-padded
  62. if needed
  63. :type person: bytes
  64. """
  65. self._state = _b2b_init(
  66. key=key, salt=salt, person=person, digest_size=digest_size
  67. )
  68. self._digest_size = digest_size
  69. if data:
  70. self.update(data)
  71. @property
  72. def digest_size(self) -> int:
  73. return self._digest_size
  74. @property
  75. def block_size(self) -> int:
  76. return 128
  77. @property
  78. def name(self) -> str:
  79. return "blake2b"
  80. def update(self, data: bytes) -> None:
  81. _b2b_update(self._state, data)
  82. def digest(self) -> bytes:
  83. _st = self._state.copy()
  84. return _b2b_final(_st)
  85. def hexdigest(self) -> str:
  86. return bytes_as_string(binascii.hexlify(self.digest()))
  87. def copy(self) -> "blake2b":
  88. _cp = type(self)(digest_size=self.digest_size)
  89. _st = self._state.copy()
  90. _cp._state = _st
  91. return _cp
  92. def __reduce__(self) -> NoReturn:
  93. """
  94. Raise the same exception as hashlib's blake implementation
  95. on copy.copy()
  96. """
  97. raise TypeError(
  98. "can't pickle {} objects".format(self.__class__.__name__)
  99. )
  100. def scrypt(
  101. password: bytes,
  102. salt: bytes = b"",
  103. n: int = 2 ** 20,
  104. r: int = 8,
  105. p: int = 1,
  106. maxmem: int = 2 ** 25,
  107. dklen: int = 64,
  108. ) -> bytes:
  109. """
  110. Derive a cryptographic key using the scrypt KDF.
  111. :raises nacl.exceptions.UnavailableError: If called when using a
  112. minimal build of libsodium.
  113. Implements the same signature as the ``hashlib.scrypt`` implemented
  114. in cpython version 3.6
  115. """
  116. return nacl.bindings.crypto_pwhash_scryptsalsa208sha256_ll(
  117. password, salt, n, r, p, maxmem=maxmem, dklen=dklen
  118. )