_mode_ecb.py 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. # -*- coding: utf-8 -*-
  2. #
  3. # Cipher/mode_ecb.py : ECB mode
  4. #
  5. # ===================================================================
  6. # The contents of this file are dedicated to the public domain. To
  7. # the extent that dedication to the public domain is not available,
  8. # everyone is granted a worldwide, perpetual, royalty-free,
  9. # non-exclusive license to exercise all rights associated with the
  10. # contents of this file for any purpose whatsoever.
  11. # No rights are reserved.
  12. #
  13. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  14. # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  15. # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  16. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  17. # BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  18. # ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  19. # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  20. # SOFTWARE.
  21. # ===================================================================
  22. """
  23. Electronic Code Book (ECB) mode.
  24. """
  25. __all__ = [ 'EcbMode' ]
  26. from Cryptodome.Util._raw_api import (load_pycryptodome_raw_lib,
  27. VoidPointer, create_string_buffer,
  28. get_raw_buffer, SmartPointer,
  29. c_size_t, c_uint8_ptr,
  30. is_writeable_buffer)
  31. raw_ecb_lib = load_pycryptodome_raw_lib("Cryptodome.Cipher._raw_ecb", """
  32. int ECB_start_operation(void *cipher,
  33. void **pResult);
  34. int ECB_encrypt(void *ecbState,
  35. const uint8_t *in,
  36. uint8_t *out,
  37. size_t data_len);
  38. int ECB_decrypt(void *ecbState,
  39. const uint8_t *in,
  40. uint8_t *out,
  41. size_t data_len);
  42. int ECB_stop_operation(void *state);
  43. """
  44. )
  45. class EcbMode(object):
  46. """*Electronic Code Book (ECB)*.
  47. This is the simplest encryption mode. Each of the plaintext blocks
  48. is directly encrypted into a ciphertext block, independently of
  49. any other block.
  50. This mode is dangerous because it exposes frequency of symbols
  51. in your plaintext. Other modes (e.g. *CBC*) should be used instead.
  52. See `NIST SP800-38A`_ , Section 6.1.
  53. .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
  54. :undocumented: __init__
  55. """
  56. def __init__(self, block_cipher):
  57. """Create a new block cipher, configured in ECB mode.
  58. :Parameters:
  59. block_cipher : C pointer
  60. A smart pointer to the low-level block cipher instance.
  61. """
  62. self.block_size = block_cipher.block_size
  63. self._state = VoidPointer()
  64. result = raw_ecb_lib.ECB_start_operation(block_cipher.get(),
  65. self._state.address_of())
  66. if result:
  67. raise ValueError("Error %d while instantiating the ECB mode"
  68. % result)
  69. # Ensure that object disposal of this Python object will (eventually)
  70. # free the memory allocated by the raw library for the cipher
  71. # mode
  72. self._state = SmartPointer(self._state.get(),
  73. raw_ecb_lib.ECB_stop_operation)
  74. # Memory allocated for the underlying block cipher is now owned
  75. # by the cipher mode
  76. block_cipher.release()
  77. def encrypt(self, plaintext, output=None):
  78. """Encrypt data with the key set at initialization.
  79. The data to encrypt can be broken up in two or
  80. more pieces and `encrypt` can be called multiple times.
  81. That is, the statement:
  82. >>> c.encrypt(a) + c.encrypt(b)
  83. is equivalent to:
  84. >>> c.encrypt(a+b)
  85. This function does not add any padding to the plaintext.
  86. :Parameters:
  87. plaintext : bytes/bytearray/memoryview
  88. The piece of data to encrypt.
  89. The length must be multiple of the cipher block length.
  90. :Keywords:
  91. output : bytearray/memoryview
  92. The location where the ciphertext must be written to.
  93. If ``None``, the ciphertext is returned.
  94. :Return:
  95. If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
  96. Otherwise, ``None``.
  97. """
  98. if output is None:
  99. ciphertext = create_string_buffer(len(plaintext))
  100. else:
  101. ciphertext = output
  102. if not is_writeable_buffer(output):
  103. raise TypeError("output must be a bytearray or a writeable memoryview")
  104. if len(plaintext) != len(output):
  105. raise ValueError("output must have the same length as the input"
  106. " (%d bytes)" % len(plaintext))
  107. result = raw_ecb_lib.ECB_encrypt(self._state.get(),
  108. c_uint8_ptr(plaintext),
  109. c_uint8_ptr(ciphertext),
  110. c_size_t(len(plaintext)))
  111. if result:
  112. if result == 3:
  113. raise ValueError("Data must be aligned to block boundary in ECB mode")
  114. raise ValueError("Error %d while encrypting in ECB mode" % result)
  115. if output is None:
  116. return get_raw_buffer(ciphertext)
  117. else:
  118. return None
  119. def decrypt(self, ciphertext, output=None):
  120. """Decrypt data with the key set at initialization.
  121. The data to decrypt can be broken up in two or
  122. more pieces and `decrypt` can be called multiple times.
  123. That is, the statement:
  124. >>> c.decrypt(a) + c.decrypt(b)
  125. is equivalent to:
  126. >>> c.decrypt(a+b)
  127. This function does not remove any padding from the plaintext.
  128. :Parameters:
  129. ciphertext : bytes/bytearray/memoryview
  130. The piece of data to decrypt.
  131. The length must be multiple of the cipher block length.
  132. :Keywords:
  133. output : bytearray/memoryview
  134. The location where the plaintext must be written to.
  135. If ``None``, the plaintext is returned.
  136. :Return:
  137. If ``output`` is ``None``, the plaintext is returned as ``bytes``.
  138. Otherwise, ``None``.
  139. """
  140. if output is None:
  141. plaintext = create_string_buffer(len(ciphertext))
  142. else:
  143. plaintext = output
  144. if not is_writeable_buffer(output):
  145. raise TypeError("output must be a bytearray or a writeable memoryview")
  146. if len(ciphertext) != len(output):
  147. raise ValueError("output must have the same length as the input"
  148. " (%d bytes)" % len(plaintext))
  149. result = raw_ecb_lib.ECB_decrypt(self._state.get(),
  150. c_uint8_ptr(ciphertext),
  151. c_uint8_ptr(plaintext),
  152. c_size_t(len(ciphertext)))
  153. if result:
  154. if result == 3:
  155. raise ValueError("Data must be aligned to block boundary in ECB mode")
  156. raise ValueError("Error %d while decrypting in ECB mode" % result)
  157. if output is None:
  158. return get_raw_buffer(plaintext)
  159. else:
  160. return None
  161. def _create_ecb_cipher(factory, **kwargs):
  162. """Instantiate a cipher object that performs ECB encryption/decryption.
  163. :Parameters:
  164. factory : module
  165. The underlying block cipher, a module from ``Cryptodome.Cipher``.
  166. All keywords are passed to the underlying block cipher.
  167. See the relevant documentation for details (at least ``key`` will need
  168. to be present"""
  169. cipher_state = factory._create_base_cipher(kwargs)
  170. cipher_state.block_size = factory.block_size
  171. if kwargs:
  172. raise TypeError("Unknown parameters for ECB: %s" % str(kwargs))
  173. return EcbMode(cipher_state)