Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/Crypto/Cipher/_mode_ecb.py: 60%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

52 statements  

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)