您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 

201 行
5.5 KiB

  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. from __future__ import absolute_import, division, print_function
  5. import abc
  6. import six
  7. from cryptography import utils
  8. from cryptography.exceptions import AlreadyFinalized
  9. from cryptography.hazmat.bindings._padding import lib
  10. @six.add_metaclass(abc.ABCMeta)
  11. class PaddingContext(object):
  12. @abc.abstractmethod
  13. def update(self, data):
  14. """
  15. Pads the provided bytes and returns any available data as bytes.
  16. """
  17. @abc.abstractmethod
  18. def finalize(self):
  19. """
  20. Finalize the padding, returns bytes.
  21. """
  22. def _byte_padding_check(block_size):
  23. if not (0 <= block_size <= 2040):
  24. raise ValueError("block_size must be in range(0, 2041).")
  25. if block_size % 8 != 0:
  26. raise ValueError("block_size must be a multiple of 8.")
  27. def _byte_padding_update(buffer_, data, block_size):
  28. if buffer_ is None:
  29. raise AlreadyFinalized("Context was already finalized.")
  30. utils._check_bytes("data", data)
  31. buffer_ += data
  32. finished_blocks = len(buffer_) // (block_size // 8)
  33. result = buffer_[:finished_blocks * (block_size // 8)]
  34. buffer_ = buffer_[finished_blocks * (block_size // 8):]
  35. return buffer_, result
  36. def _byte_padding_pad(buffer_, block_size, paddingfn):
  37. if buffer_ is None:
  38. raise AlreadyFinalized("Context was already finalized.")
  39. pad_size = block_size // 8 - len(buffer_)
  40. return buffer_ + paddingfn(pad_size)
  41. def _byte_unpadding_update(buffer_, data, block_size):
  42. if buffer_ is None:
  43. raise AlreadyFinalized("Context was already finalized.")
  44. utils._check_bytes("data", data)
  45. buffer_ += data
  46. finished_blocks = max(len(buffer_) // (block_size // 8) - 1, 0)
  47. result = buffer_[:finished_blocks * (block_size // 8)]
  48. buffer_ = buffer_[finished_blocks * (block_size // 8):]
  49. return buffer_, result
  50. def _byte_unpadding_check(buffer_, block_size, checkfn):
  51. if buffer_ is None:
  52. raise AlreadyFinalized("Context was already finalized.")
  53. if len(buffer_) != block_size // 8:
  54. raise ValueError("Invalid padding bytes.")
  55. valid = checkfn(buffer_, block_size // 8)
  56. if not valid:
  57. raise ValueError("Invalid padding bytes.")
  58. pad_size = six.indexbytes(buffer_, -1)
  59. return buffer_[:-pad_size]
  60. class PKCS7(object):
  61. def __init__(self, block_size):
  62. _byte_padding_check(block_size)
  63. self.block_size = block_size
  64. def padder(self):
  65. return _PKCS7PaddingContext(self.block_size)
  66. def unpadder(self):
  67. return _PKCS7UnpaddingContext(self.block_size)
  68. @utils.register_interface(PaddingContext)
  69. class _PKCS7PaddingContext(object):
  70. def __init__(self, block_size):
  71. self.block_size = block_size
  72. # TODO: more copies than necessary, we should use zero-buffer (#193)
  73. self._buffer = b""
  74. def update(self, data):
  75. self._buffer, result = _byte_padding_update(
  76. self._buffer, data, self.block_size)
  77. return result
  78. def _padding(self, size):
  79. return six.int2byte(size) * size
  80. def finalize(self):
  81. result = _byte_padding_pad(
  82. self._buffer, self.block_size, self._padding)
  83. self._buffer = None
  84. return result
  85. @utils.register_interface(PaddingContext)
  86. class _PKCS7UnpaddingContext(object):
  87. def __init__(self, block_size):
  88. self.block_size = block_size
  89. # TODO: more copies than necessary, we should use zero-buffer (#193)
  90. self._buffer = b""
  91. def update(self, data):
  92. self._buffer, result = _byte_unpadding_update(
  93. self._buffer, data, self.block_size)
  94. return result
  95. def finalize(self):
  96. result = _byte_unpadding_check(
  97. self._buffer, self.block_size,
  98. lib.Cryptography_check_pkcs7_padding)
  99. self._buffer = None
  100. return result
  101. class ANSIX923(object):
  102. def __init__(self, block_size):
  103. _byte_padding_check(block_size)
  104. self.block_size = block_size
  105. def padder(self):
  106. return _ANSIX923PaddingContext(self.block_size)
  107. def unpadder(self):
  108. return _ANSIX923UnpaddingContext(self.block_size)
  109. @utils.register_interface(PaddingContext)
  110. class _ANSIX923PaddingContext(object):
  111. def __init__(self, block_size):
  112. self.block_size = block_size
  113. # TODO: more copies than necessary, we should use zero-buffer (#193)
  114. self._buffer = b""
  115. def update(self, data):
  116. self._buffer, result = _byte_padding_update(
  117. self._buffer, data, self.block_size)
  118. return result
  119. def _padding(self, size):
  120. return six.int2byte(0) * (size - 1) + six.int2byte(size)
  121. def finalize(self):
  122. result = _byte_padding_pad(
  123. self._buffer, self.block_size, self._padding)
  124. self._buffer = None
  125. return result
  126. @utils.register_interface(PaddingContext)
  127. class _ANSIX923UnpaddingContext(object):
  128. def __init__(self, block_size):
  129. self.block_size = block_size
  130. # TODO: more copies than necessary, we should use zero-buffer (#193)
  131. self._buffer = b""
  132. def update(self, data):
  133. self._buffer, result = _byte_unpadding_update(
  134. self._buffer, data, self.block_size)
  135. return result
  136. def finalize(self):
  137. result = _byte_unpadding_check(
  138. self._buffer, self.block_size,
  139. lib.Cryptography_check_ansix923_padding)
  140. self._buffer = None
  141. return result