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"""
24Electronic Code Book (ECB) mode.
25"""
26
27__all__ = [ 'EcbMode' ]
28
29from Crypto.Util._raw_api import (load_pycryptodome_raw_lib,
30 VoidPointer, create_string_buffer,
31 get_raw_buffer, SmartPointer,
32 c_size_t, c_uint8_ptr,
33 is_writeable_buffer)
34
35raw_ecb_lib = load_pycryptodome_raw_lib("Crypto.Cipher._raw_ecb", """
36 int ECB_start_operation(void *cipher,
37 void **pResult);
38 int ECB_encrypt(void *ecbState,
39 const uint8_t *in,
40 uint8_t *out,
41 size_t data_len);
42 int ECB_decrypt(void *ecbState,
43 const uint8_t *in,
44 uint8_t *out,
45 size_t data_len);
46 int ECB_stop_operation(void *state);
47 """
48 )
49
50
51class EcbMode(object):
52 """*Electronic Code Book (ECB)*.
53
54 This is the simplest encryption mode. Each of the plaintext blocks
55 is directly encrypted into a ciphertext block, independently of
56 any other block.
57
58 This mode is dangerous because it exposes frequency of symbols
59 in your plaintext. Other modes (e.g. *CBC*) should be used instead.
60
61 See `NIST SP800-38A`_ , Section 6.1.
62
63 .. _`NIST SP800-38A` : http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
64
65 :undocumented: __init__
66 """
67
68 def __init__(self, block_cipher):
69 """Create a new block cipher, configured in ECB mode.
70
71 :Parameters:
72 block_cipher : C pointer
73 A smart pointer to the low-level block cipher instance.
74 """
75 self.block_size = block_cipher.block_size
76
77 self._state = VoidPointer()
78 result = raw_ecb_lib.ECB_start_operation(block_cipher.get(),
79 self._state.address_of())
80 if result:
81 raise ValueError("Error %d while instantiating the ECB mode"
82 % result)
83
84 # Ensure that object disposal of this Python object will (eventually)
85 # free the memory allocated by the raw library for the cipher
86 # mode
87 self._state = SmartPointer(self._state.get(),
88 raw_ecb_lib.ECB_stop_operation)
89
90 # Memory allocated for the underlying block cipher is now owned
91 # by the cipher mode
92 block_cipher.release()
93
94 def encrypt(self, plaintext, output=None):
95 """Encrypt data with the key set at initialization.
96
97 The data to encrypt can be broken up in two or
98 more pieces and `encrypt` can be called multiple times.
99
100 That is, the statement:
101
102 >>> c.encrypt(a) + c.encrypt(b)
103
104 is equivalent to:
105
106 >>> c.encrypt(a+b)
107
108 This function does not add any padding to the plaintext.
109
110 :Parameters:
111 plaintext : bytes/bytearray/memoryview
112 The piece of data to encrypt.
113 The length must be multiple of the cipher block length.
114 :Keywords:
115 output : bytearray/memoryview
116 The location where the ciphertext must be written to.
117 If ``None``, the ciphertext is returned.
118 :Return:
119 If ``output`` is ``None``, the ciphertext is returned as ``bytes``.
120 Otherwise, ``None``.
121 """
122
123 if output is None:
124 ciphertext = create_string_buffer(len(plaintext))
125 else:
126 ciphertext = output
127
128 if not is_writeable_buffer(output):
129 raise TypeError("output must be a bytearray or a writeable memoryview")
130
131 if len(plaintext) != len(output):
132 raise ValueError("output must have the same length as the input"
133 " (%d bytes)" % len(plaintext))
134
135 result = raw_ecb_lib.ECB_encrypt(self._state.get(),
136 c_uint8_ptr(plaintext),
137 c_uint8_ptr(ciphertext),
138 c_size_t(len(plaintext)))
139 if result:
140 if result == 3:
141 raise ValueError("Data must be aligned to block boundary in ECB mode")
142 raise ValueError("Error %d while encrypting in ECB mode" % result)
143
144 if output is None:
145 return get_raw_buffer(ciphertext)
146 else:
147 return None
148
149 def decrypt(self, ciphertext, output=None):
150 """Decrypt data with the key set at initialization.
151
152 The data to decrypt can be broken up in two or
153 more pieces and `decrypt` can be called multiple times.
154
155 That is, the statement:
156
157 >>> c.decrypt(a) + c.decrypt(b)
158
159 is equivalent to:
160
161 >>> c.decrypt(a+b)
162
163 This function does not remove any padding from the plaintext.
164
165 :Parameters:
166 ciphertext : bytes/bytearray/memoryview
167 The piece of data to decrypt.
168 The length must be multiple of the cipher block length.
169 :Keywords:
170 output : bytearray/memoryview
171 The location where the plaintext must be written to.
172 If ``None``, the plaintext is returned.
173 :Return:
174 If ``output`` is ``None``, the plaintext is returned as ``bytes``.
175 Otherwise, ``None``.
176 """
177
178 if output is None:
179 plaintext = create_string_buffer(len(ciphertext))
180 else:
181 plaintext = output
182
183 if not is_writeable_buffer(output):
184 raise TypeError("output must be a bytearray or a writeable memoryview")
185
186 if len(ciphertext) != len(output):
187 raise ValueError("output must have the same length as the input"
188 " (%d bytes)" % len(plaintext))
189
190 result = raw_ecb_lib.ECB_decrypt(self._state.get(),
191 c_uint8_ptr(ciphertext),
192 c_uint8_ptr(plaintext),
193 c_size_t(len(ciphertext)))
194 if result:
195 if result == 3:
196 raise ValueError("Data must be aligned to block boundary in ECB mode")
197 raise ValueError("Error %d while decrypting in ECB mode" % result)
198
199 if output is None:
200 return get_raw_buffer(plaintext)
201 else:
202 return None
203
204
205def _create_ecb_cipher(factory, **kwargs):
206 """Instantiate a cipher object that performs ECB encryption/decryption.
207
208 :Parameters:
209 factory : module
210 The underlying block cipher, a module from ``Crypto.Cipher``.
211
212 All keywords are passed to the underlying block cipher.
213 See the relevant documentation for details (at least ``key`` will need
214 to be present"""
215
216 cipher_state = factory._create_base_cipher(kwargs)
217 cipher_state.block_size = factory.block_size
218 if kwargs:
219 raise TypeError("Unknown parameters for ECB: %s" % str(kwargs))
220 return EcbMode(cipher_state)