InPanel 1.2.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (198) hide show
  1. inpanel/__init__.py +29 -0
  2. inpanel/acme.py +289 -0
  3. inpanel/aliyuncs.py +269 -0
  4. inpanel/app.py +514 -0
  5. inpanel/apt.py +223 -0
  6. inpanel/base.py +200 -0
  7. inpanel/config.py +139 -0
  8. inpanel/data/config.ini +29 -0
  9. inpanel/data/history +5 -0
  10. inpanel/data/runlogs.ini +12 -0
  11. inpanel/data/update_info.ini +4 -0
  12. inpanel/dnf.py +225 -0
  13. inpanel/lib/__init__.py +9 -0
  14. inpanel/lib/async_process.py +98 -0
  15. inpanel/lib/filelock.py +82 -0
  16. inpanel/lib/magic.py +233 -0
  17. inpanel/lib/pxssh.py +310 -0
  18. inpanel/lib/pyDes.py +867 -0
  19. inpanel/mod/__init__.py +0 -0
  20. inpanel/mod/apt.py +316 -0
  21. inpanel/mod/certificate.py +268 -0
  22. inpanel/mod/config.py +372 -0
  23. inpanel/mod/cron.py +315 -0
  24. inpanel/mod/disk.py +322 -0
  25. inpanel/mod/dnf.py +239 -0
  26. inpanel/mod/file.py +722 -0
  27. inpanel/mod/firewall.py +199 -0
  28. inpanel/mod/firewall_base.py +137 -0
  29. inpanel/mod/firewall_firewalld.py +170 -0
  30. inpanel/mod/firewall_iptables.py +176 -0
  31. inpanel/mod/firewall_macos.py +213 -0
  32. inpanel/mod/firewall_ufw.py +128 -0
  33. inpanel/mod/ftp.py +231 -0
  34. inpanel/mod/httpd.py +1205 -0
  35. inpanel/mod/lighttpd.py +26 -0
  36. inpanel/mod/login.py +98 -0
  37. inpanel/mod/mysql.py +577 -0
  38. inpanel/mod/named.py +26 -0
  39. inpanel/mod/nginx.py +2327 -0
  40. inpanel/mod/package.py +33 -0
  41. inpanel/mod/package_apt.py +62 -0
  42. inpanel/mod/package_base.py +77 -0
  43. inpanel/mod/package_dnf.py +62 -0
  44. inpanel/mod/package_map.py +366 -0
  45. inpanel/mod/package_yum.py +64 -0
  46. inpanel/mod/php.py +289 -0
  47. inpanel/mod/process.py +291 -0
  48. inpanel/mod/proftpd.py +26 -0
  49. inpanel/mod/pureftpd.py +26 -0
  50. inpanel/mod/query.py +108 -0
  51. inpanel/mod/server.py +1319 -0
  52. inpanel/mod/service.py +262 -0
  53. inpanel/mod/setting.py +228 -0
  54. inpanel/mod/shell.py +78 -0
  55. inpanel/mod/ssh.py +280 -0
  56. inpanel/mod/system.py +220 -0
  57. inpanel/mod/task.py +1337 -0
  58. inpanel/mod/ufw.py +14 -0
  59. inpanel/mod/user.py +306 -0
  60. inpanel/mod/vsftpd.py +67 -0
  61. inpanel/mod/yum.py +243 -0
  62. inpanel/plugins/__init__.py +10 -0
  63. inpanel/plugins/__pycache__/__init__.cpython-313.pyc +0 -0
  64. inpanel/plugins/acme/static/index.html +10 -0
  65. inpanel/plugins/acme/static/index.js +13 -0
  66. inpanel/plugins/shadowsocks-libev/__pycache__/info.cpython-313.pyc +0 -0
  67. inpanel/plugins/shadowsocks-libev/info.py +73 -0
  68. inpanel/plugins/shadowsocks-libev/static/index.html +70 -0
  69. inpanel/plugins/shadowsocks-libev/static/index.js +18 -0
  70. inpanel/public/css/global.css +138 -0
  71. inpanel/public/favicon.ico +0 -0
  72. inpanel/public/images/alipay.jpg +0 -0
  73. inpanel/public/images/loading.gif +0 -0
  74. inpanel/public/images/weixin.jpg +0 -0
  75. inpanel/public/index.html +94 -0
  76. inpanel/public/js/controllers/controllers.js +566 -0
  77. inpanel/public/js/controllers/database.js +590 -0
  78. inpanel/public/js/controllers/ecs.js +624 -0
  79. inpanel/public/js/controllers/file.js +940 -0
  80. inpanel/public/js/controllers/plugins.js +105 -0
  81. inpanel/public/js/controllers/service.js +1460 -0
  82. inpanel/public/js/controllers/site.js +1241 -0
  83. inpanel/public/js/controllers/utils.js +2319 -0
  84. inpanel/public/js/core.js +221 -0
  85. inpanel/public/js/directives.js +784 -0
  86. inpanel/public/js/filters.js +395 -0
  87. inpanel/public/js/services.js +257 -0
  88. inpanel/public/lib/angular/1.0.2/angular-resource.min.js +10 -0
  89. inpanel/public/lib/angular/1.0.2/angular.min.js +158 -0
  90. inpanel/public/lib/bootstrap/css/bootstrap-theme.css +587 -0
  91. inpanel/public/lib/bootstrap/css/bootstrap-theme.css.map +1 -0
  92. inpanel/public/lib/bootstrap/css/bootstrap-theme.min.css +6 -0
  93. inpanel/public/lib/bootstrap/css/bootstrap-theme.min.css.map +1 -0
  94. inpanel/public/lib/bootstrap/css/bootstrap.css +6757 -0
  95. inpanel/public/lib/bootstrap/css/bootstrap.css.map +1 -0
  96. inpanel/public/lib/bootstrap/css/bootstrap.min.css +6 -0
  97. inpanel/public/lib/bootstrap/css/bootstrap.min.css.map +1 -0
  98. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.eot +0 -0
  99. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.svg +288 -0
  100. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.ttf +0 -0
  101. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff +0 -0
  102. inpanel/public/lib/bootstrap/fonts/glyphicons-halflings-regular.woff2 +0 -0
  103. inpanel/public/lib/bootstrap/img/glyphicons-halflings-white.png +0 -0
  104. inpanel/public/lib/bootstrap/img/glyphicons-halflings.png +0 -0
  105. inpanel/public/lib/bootstrap/js/bootstrap.js +2377 -0
  106. inpanel/public/lib/bootstrap/js/bootstrap.min.js +7 -0
  107. inpanel/public/lib/bootstrap/js/npm.js +13 -0
  108. inpanel/public/lib/codemirror/codemirror-compressed.js +1 -0
  109. inpanel/public/lib/codemirror/codemirror.css +173 -0
  110. inpanel/public/lib/jquery/jquery-1.12.4.min.js +5 -0
  111. inpanel/public/lib/md5/md5.js +379 -0
  112. inpanel/public/lib/md5/md5.min.js +1 -0
  113. inpanel/public/partials/database/index.html +172 -0
  114. inpanel/public/partials/database/mysql/dbedit.html +462 -0
  115. inpanel/public/partials/database/mysql/dbnew.html +348 -0
  116. inpanel/public/partials/database/mysql/useredit.html +310 -0
  117. inpanel/public/partials/database/mysql/usernew.html +97 -0
  118. inpanel/public/partials/directives/message.html +20 -0
  119. inpanel/public/partials/directives/navbar.html +25 -0
  120. inpanel/public/partials/directives/selector.html +57 -0
  121. inpanel/public/partials/directives/srvbase.html +72 -0
  122. inpanel/public/partials/directives/srvext.html +34 -0
  123. inpanel/public/partials/directives/srvfile.html +23 -0
  124. inpanel/public/partials/directives/srvinstall.html +34 -0
  125. inpanel/public/partials/directives/srvlog.html +23 -0
  126. inpanel/public/partials/directives/srvminiop.html +28 -0
  127. inpanel/public/partials/directives/srvuninstall.html +38 -0
  128. inpanel/public/partials/directives/srvupdate.html +30 -0
  129. inpanel/public/partials/ecs/account.html +156 -0
  130. inpanel/public/partials/ecs/ecs.html +198 -0
  131. inpanel/public/partials/ecs/index.html +40 -0
  132. inpanel/public/partials/ecs/setings.html +459 -0
  133. inpanel/public/partials/file/file.html +501 -0
  134. inpanel/public/partials/file/trash.html +95 -0
  135. inpanel/public/partials/ftp.html +36 -0
  136. inpanel/public/partials/log.html +83 -0
  137. inpanel/public/partials/login.html +79 -0
  138. inpanel/public/partials/logout.html +22 -0
  139. inpanel/public/partials/main.html +534 -0
  140. inpanel/public/partials/plugins/index.html +55 -0
  141. inpanel/public/partials/plugins/plugins.html +13 -0
  142. inpanel/public/partials/secure.html +13 -0
  143. inpanel/public/partials/service/apache.html +147 -0
  144. inpanel/public/partials/service/cron.html +71 -0
  145. inpanel/public/partials/service/index.html +293 -0
  146. inpanel/public/partials/service/iptables.html +40 -0
  147. inpanel/public/partials/service/lighttpd.html +63 -0
  148. inpanel/public/partials/service/mariadb.html +113 -0
  149. inpanel/public/partials/service/memcache.html +36 -0
  150. inpanel/public/partials/service/minio.html +44 -0
  151. inpanel/public/partials/service/mongodb.html +44 -0
  152. inpanel/public/partials/service/mysql.html +113 -0
  153. inpanel/public/partials/service/named.html +61 -0
  154. inpanel/public/partials/service/nginx.html +296 -0
  155. inpanel/public/partials/service/ntp.html +40 -0
  156. inpanel/public/partials/service/php.html +250 -0
  157. inpanel/public/partials/service/proftpd.html +59 -0
  158. inpanel/public/partials/service/pureftpd.html +59 -0
  159. inpanel/public/partials/service/redis.html +40 -0
  160. inpanel/public/partials/service/samba.html +58 -0
  161. inpanel/public/partials/service/sendmail.html +40 -0
  162. inpanel/public/partials/service/ssh.html +186 -0
  163. inpanel/public/partials/service/tomcat.html +65 -0
  164. inpanel/public/partials/service/vsftpd.html +195 -0
  165. inpanel/public/partials/setting.html +299 -0
  166. inpanel/public/partials/site/apache/site.html +277 -0
  167. inpanel/public/partials/site/index.html +344 -0
  168. inpanel/public/partials/site/nginx/site.html +558 -0
  169. inpanel/public/partials/sorry.html +19 -0
  170. inpanel/public/partials/storage/autofm.html +103 -0
  171. inpanel/public/partials/storage/backup.html +42 -0
  172. inpanel/public/partials/storage/index.html +360 -0
  173. inpanel/public/partials/storage/migrate.html +93 -0
  174. inpanel/public/partials/storage/movedata.html +98 -0
  175. inpanel/public/partials/storage/remote.html +77 -0
  176. inpanel/public/partials/utils/cron.html +486 -0
  177. inpanel/public/partials/utils/firewall.html +266 -0
  178. inpanel/public/partials/utils/index.html +193 -0
  179. inpanel/public/partials/utils/network.html +118 -0
  180. inpanel/public/partials/utils/process.html +239 -0
  181. inpanel/public/partials/utils/repository.html +373 -0
  182. inpanel/public/partials/utils/shell.html +28 -0
  183. inpanel/public/partials/utils/ssl.html +319 -0
  184. inpanel/public/partials/utils/time.html +109 -0
  185. inpanel/public/partials/utils/user.html +359 -0
  186. inpanel/public/robots.txt +2 -0
  187. inpanel/remote.py +109 -0
  188. inpanel/templates/file/preview.html +34 -0
  189. inpanel/templates/index.html +93 -0
  190. inpanel/utils.py +282 -0
  191. inpanel/web.py +1811 -0
  192. inpanel/yum.py +756 -0
  193. inpanel-1.2.1.dist-info/METADATA +399 -0
  194. inpanel-1.2.1.dist-info/RECORD +198 -0
  195. inpanel-1.2.1.dist-info/WHEEL +5 -0
  196. inpanel-1.2.1.dist-info/entry_points.txt +2 -0
  197. inpanel-1.2.1.dist-info/licenses/LICENSE +30 -0
  198. inpanel-1.2.1.dist-info/top_level.txt +1 -0
inpanel/lib/pyDes.py ADDED
@@ -0,0 +1,867 @@
1
+ #############################################################################
2
+ # Documentation #
3
+ #############################################################################
4
+
5
+ # Author: Todd Whiteman
6
+ # Date: 16th March, 2009
7
+ # Verion: 2.0.0
8
+ # License: Public Domain - free to do as you wish
9
+ # Homepage: http://twhiteman.netfirms.com/des.html
10
+ #
11
+ # This is a pure python implementation of the DES encryption algorithm.
12
+ # It's pure python to avoid portability issues, since most DES
13
+ # implementations are programmed in C (for performance reasons).
14
+ #
15
+ # Triple DES class is also implemented, utilising the DES base. Triple DES
16
+ # is either DES-EDE3 with a 24 byte key, or DES-EDE2 with a 16 byte key.
17
+ #
18
+ # See the README.txt that should come with this python module for the
19
+ # implementation methods used.
20
+ #
21
+ # Thanks to:
22
+ # * David Broadwell for ideas, comments and suggestions.
23
+ # * Mario Wolff for pointing out and debugging some triple des CBC errors.
24
+ # * Santiago Palladino for providing the PKCS5 padding technique.
25
+ # * Shaya for correcting the PAD_PKCS5 triple des CBC errors.
26
+ #
27
+ """A pure python implementation of the DES and TRIPLE DES encryption algorithms.
28
+
29
+ Class initialization
30
+ --------------------
31
+ pyDes.des(key, [mode], [IV], [pad], [padmode])
32
+ pyDes.triple_des(key, [mode], [IV], [pad], [padmode])
33
+
34
+ key -> Bytes containing the encryption key. 8 bytes for DES, 16 or 24 bytes
35
+ for Triple DES
36
+ mode -> Optional argument for encryption type, can be either
37
+ pyDes.ECB (Electronic Code Book) or pyDes.CBC (Cypher Block Chaining)
38
+ IV -> Optional Initial Value bytes, must be supplied if using CBC mode.
39
+ Length must be 8 bytes.
40
+ pad -> Optional argument, set the pad character (PAD_NORMAL) to use during
41
+ all encrypt/decrpt operations done with this instance.
42
+ padmode -> Optional argument, set the padding mode (PAD_NORMAL or PAD_PKCS5)
43
+ to use during all encrypt/decrpt operations done with this instance.
44
+
45
+ I recommend to use PAD_PKCS5 padding, as then you never need to worry about any
46
+ padding issues, as the padding can be removed unambiguously upon decrypting
47
+ data that was encrypted using PAD_PKCS5 padmode.
48
+
49
+ Common methods
50
+ --------------
51
+ encrypt(data, [pad], [padmode])
52
+ decrypt(data, [pad], [padmode])
53
+
54
+ data -> Bytes to be encrypted/decrypted
55
+ pad -> Optional argument. Only when using padmode of PAD_NORMAL. For
56
+ encryption, adds this characters to the end of the data block when
57
+ data is not a multiple of 8 bytes. For decryption, will remove the
58
+ trailing characters that match this pad character from the last 8
59
+ bytes of the unencrypted data block.
60
+ padmode -> Optional argument, set the padding mode, must be one of PAD_NORMAL
61
+ or PAD_PKCS5). Defaults to PAD_NORMAL.
62
+
63
+
64
+ Example
65
+ -------
66
+ from pyDes import *
67
+
68
+ data = "Please encrypt my data"
69
+ k = des("DESCRYPT", CBC, "\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
70
+ # For Python3, you'll need to use bytes, i.e.:
71
+ # data = b"Please encrypt my data"
72
+ # k = des(b"DESCRYPT", CBC, b"\0\0\0\0\0\0\0\0", pad=None, padmode=PAD_PKCS5)
73
+ d = k.encrypt(data)
74
+ print("Encrypted: %r" % d)
75
+ print("Decrypted: %r" % k.decrypt(d))
76
+ assert k.decrypt(d, padmode=PAD_PKCS5) == data
77
+
78
+
79
+ See the module source (pyDes.py) for more examples of use.
80
+ You can also run the pyDes.py file without and arguments to see a simple test.
81
+
82
+ Note: This code was not written for high-end systems needing a fast
83
+ implementation, but rather a handy portable solution with small usage.
84
+
85
+ """
86
+
87
+ import sys
88
+
89
+ # _pythonMajorVersion is used to handle Python2 and Python3 differences.
90
+ _pythonMajorVersion = sys.version_info[0]
91
+
92
+ # Modes of crypting / cyphering
93
+ ECB = 0
94
+ CBC = 1
95
+
96
+ # Modes of padding
97
+ PAD_NORMAL = 1
98
+ PAD_PKCS5 = 2
99
+
100
+ # PAD_PKCS5: is a method that will unambiguously remove all padding
101
+ # characters after decryption, when originally encrypted with
102
+ # this padding mode.
103
+ # For a good description of the PKCS5 padding technique, see:
104
+ # http://www.faqs.org/rfcs/rfc1423.html
105
+
106
+ # The base class shared by des and triple des.
107
+
108
+
109
+ class _baseDes(object):
110
+ def __init__(self, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
111
+ if IV:
112
+ IV = self._guardAgainstUnicode(IV)
113
+ if pad:
114
+ pad = self._guardAgainstUnicode(pad)
115
+ self.block_size = 8
116
+ # Sanity checking of arguments.
117
+ if pad and padmode == PAD_PKCS5:
118
+ raise ValueError("Cannot use a pad character with PAD_PKCS5")
119
+ if IV and len(IV) != self.block_size:
120
+ raise ValueError(
121
+ "Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
122
+
123
+ # Set the passed in variables
124
+ self._mode = mode
125
+ self._iv = IV
126
+ self._padding = pad
127
+ self._padmode = padmode
128
+
129
+ def getKey(self):
130
+ """getKey() -> bytes"""
131
+ return self.__key
132
+
133
+ def setKey(self, key):
134
+ """Will set the crypting key for this object."""
135
+ key = self._guardAgainstUnicode(key)
136
+ self.__key = key
137
+
138
+ def getMode(self):
139
+ """getMode() -> pyDes.ECB or pyDes.CBC"""
140
+ return self._mode
141
+
142
+ def setMode(self, mode):
143
+ """Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
144
+ self._mode = mode
145
+
146
+ def getPadding(self):
147
+ """getPadding() -> bytes of length 1. Padding character."""
148
+ return self._padding
149
+
150
+ def setPadding(self, pad):
151
+ """setPadding() -> bytes of length 1. Padding character."""
152
+ if pad is not None:
153
+ pad = self._guardAgainstUnicode(pad)
154
+ self._padding = pad
155
+
156
+ def getPadMode(self):
157
+ """getPadMode() -> pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
158
+ return self._padmode
159
+
160
+ def setPadMode(self, mode):
161
+ """Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
162
+ self._padmode = mode
163
+
164
+ def getIV(self):
165
+ """getIV() -> bytes"""
166
+ return self._iv
167
+
168
+ def setIV(self, IV):
169
+ """Will set the Initial Value, used in conjunction with CBC mode"""
170
+ if not IV or len(IV) != self.block_size:
171
+ raise ValueError(
172
+ "Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
173
+ IV = self._guardAgainstUnicode(IV)
174
+ self._iv = IV
175
+
176
+ def _padData(self, data, pad, padmode):
177
+ # Pad data depending on the mode
178
+ if padmode is None:
179
+ # Get the default padding mode.
180
+ padmode = self.getPadMode()
181
+ if pad and padmode == PAD_PKCS5:
182
+ raise ValueError("Cannot use a pad character with PAD_PKCS5")
183
+
184
+ if padmode == PAD_NORMAL:
185
+ if len(data) % self.block_size == 0:
186
+ # No padding required.
187
+ return data
188
+
189
+ if not pad:
190
+ # Get the default padding.
191
+ pad = self.getPadding()
192
+ if not pad:
193
+ raise ValueError("Data must be a multiple of " + str(self.block_size) +
194
+ " bytes in length. Use padmode=PAD_PKCS5 or set the pad character.")
195
+ data += (self.block_size - (len(data) % self.block_size)) * pad
196
+
197
+ elif padmode == PAD_PKCS5:
198
+ pad_len = 8 - (len(data) % self.block_size)
199
+ if _pythonMajorVersion < 3:
200
+ data += pad_len * chr(pad_len)
201
+ else:
202
+ data += bytes([pad_len] * pad_len)
203
+
204
+ return data
205
+
206
+ def _unpadData(self, data, pad, padmode):
207
+ # Unpad data depending on the mode.
208
+ if not data:
209
+ return data
210
+ if pad and padmode == PAD_PKCS5:
211
+ raise ValueError("Cannot use a pad character with PAD_PKCS5")
212
+ if padmode is None:
213
+ # Get the default padding mode.
214
+ padmode = self.getPadMode()
215
+
216
+ if padmode == PAD_NORMAL:
217
+ if not pad:
218
+ # Get the default padding.
219
+ pad = self.getPadding()
220
+ if pad:
221
+ data = data[:-self.block_size] + \
222
+ data[-self.block_size:].rstrip(pad)
223
+
224
+ elif padmode == PAD_PKCS5:
225
+ if _pythonMajorVersion < 3:
226
+ pad_len = ord(data[-1])
227
+ else:
228
+ pad_len = data[-1]
229
+ data = data[:-pad_len]
230
+
231
+ return data
232
+
233
+ def _guardAgainstUnicode(self, data):
234
+ # Only accept byte strings or ascii unicode values, otherwise
235
+ # there is no way to correctly decode the data into bytes.
236
+ if _pythonMajorVersion < 3:
237
+ if isinstance(data, unicode):
238
+ raise ValueError(
239
+ "pyDes can only work with bytes, not Unicode strings.")
240
+ else:
241
+ if isinstance(data, str):
242
+ # Only accept ascii unicode values.
243
+ try:
244
+ return data.encode('ascii')
245
+ except UnicodeEncodeError:
246
+ pass
247
+ raise ValueError(
248
+ "pyDes can only work with encoded strings, not Unicode.")
249
+ return data
250
+
251
+ #############################################################################
252
+ # DES #
253
+ #############################################################################
254
+
255
+
256
+ class des(_baseDes):
257
+ """DES encryption/decrytpion class
258
+
259
+ Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
260
+
261
+ pyDes.des(key,[mode], [IV])
262
+
263
+ key -> Bytes containing the encryption key, must be exactly 8 bytes
264
+ mode -> Optional argument for encryption type, can be either pyDes.ECB
265
+ (Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
266
+ IV -> Optional Initial Value bytes, must be supplied if using CBC mode.
267
+ Must be 8 bytes in length.
268
+ pad -> Optional argument, set the pad character (PAD_NORMAL) to use
269
+ during all encrypt/decrpt operations done with this instance.
270
+ padmode -> Optional argument, set the padding mode (PAD_NORMAL or
271
+ PAD_PKCS5) to use during all encrypt/decrpt operations done
272
+ with this instance.
273
+ """
274
+
275
+ # Permutation and translation tables for DES
276
+ __pc1 = [56, 48, 40, 32, 24, 16, 8,
277
+ 0, 57, 49, 41, 33, 25, 17,
278
+ 9, 1, 58, 50, 42, 34, 26,
279
+ 18, 10, 2, 59, 51, 43, 35,
280
+ 62, 54, 46, 38, 30, 22, 14,
281
+ 6, 61, 53, 45, 37, 29, 21,
282
+ 13, 5, 60, 52, 44, 36, 28,
283
+ 20, 12, 4, 27, 19, 11, 3
284
+ ]
285
+
286
+ # number left rotations of pc1
287
+ __left_rotations = [
288
+ 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
289
+ ]
290
+
291
+ # permuted choice key (table 2)
292
+ __pc2 = [
293
+ 13, 16, 10, 23, 0, 4,
294
+ 2, 27, 14, 5, 20, 9,
295
+ 22, 18, 11, 3, 25, 7,
296
+ 15, 6, 26, 19, 12, 1,
297
+ 40, 51, 30, 36, 46, 54,
298
+ 29, 39, 50, 44, 32, 47,
299
+ 43, 48, 38, 55, 33, 52,
300
+ 45, 41, 49, 35, 28, 31
301
+ ]
302
+
303
+ # initial permutation IP
304
+ __ip = [57, 49, 41, 33, 25, 17, 9, 1,
305
+ 59, 51, 43, 35, 27, 19, 11, 3,
306
+ 61, 53, 45, 37, 29, 21, 13, 5,
307
+ 63, 55, 47, 39, 31, 23, 15, 7,
308
+ 56, 48, 40, 32, 24, 16, 8, 0,
309
+ 58, 50, 42, 34, 26, 18, 10, 2,
310
+ 60, 52, 44, 36, 28, 20, 12, 4,
311
+ 62, 54, 46, 38, 30, 22, 14, 6
312
+ ]
313
+
314
+ # Expansion table for turning 32 bit blocks into 48 bits
315
+ __expansion_table = [
316
+ 31, 0, 1, 2, 3, 4,
317
+ 3, 4, 5, 6, 7, 8,
318
+ 7, 8, 9, 10, 11, 12,
319
+ 11, 12, 13, 14, 15, 16,
320
+ 15, 16, 17, 18, 19, 20,
321
+ 19, 20, 21, 22, 23, 24,
322
+ 23, 24, 25, 26, 27, 28,
323
+ 27, 28, 29, 30, 31, 0
324
+ ]
325
+
326
+ # The (in)famous S-boxes
327
+ __sbox = [
328
+ # S1
329
+ [14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
330
+ 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
331
+ 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
332
+ 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
333
+
334
+ # S2
335
+ [15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
336
+ 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
337
+ 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
338
+ 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
339
+
340
+ # S3
341
+ [10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
342
+ 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
343
+ 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
344
+ 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
345
+
346
+ # S4
347
+ [7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
348
+ 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
349
+ 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
350
+ 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
351
+
352
+ # S5
353
+ [2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
354
+ 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
355
+ 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
356
+ 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
357
+
358
+ # S6
359
+ [12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
360
+ 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
361
+ 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
362
+ 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
363
+
364
+ # S7
365
+ [4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
366
+ 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
367
+ 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
368
+ 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
369
+
370
+ # S8
371
+ [13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
372
+ 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
373
+ 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
374
+ 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
375
+ ]
376
+
377
+ # 32-bit permutation function P used on the output of the S-boxes
378
+ __p = [
379
+ 15, 6, 19, 20, 28, 11,
380
+ 27, 16, 0, 14, 22, 25,
381
+ 4, 17, 30, 9, 1, 7,
382
+ 23, 13, 31, 26, 2, 8,
383
+ 18, 12, 29, 5, 21, 10,
384
+ 3, 24
385
+ ]
386
+
387
+ # final permutation IP^-1
388
+ __fp = [
389
+ 39, 7, 47, 15, 55, 23, 63, 31,
390
+ 38, 6, 46, 14, 54, 22, 62, 30,
391
+ 37, 5, 45, 13, 53, 21, 61, 29,
392
+ 36, 4, 44, 12, 52, 20, 60, 28,
393
+ 35, 3, 43, 11, 51, 19, 59, 27,
394
+ 34, 2, 42, 10, 50, 18, 58, 26,
395
+ 33, 1, 41, 9, 49, 17, 57, 25,
396
+ 32, 0, 40, 8, 48, 16, 56, 24
397
+ ]
398
+
399
+ # Type of crypting being done
400
+ ENCRYPT = 0x00
401
+ DECRYPT = 0x01
402
+
403
+ # Initialisation
404
+ def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
405
+ # Sanity checking of arguments.
406
+ if len(key) != 8:
407
+ raise ValueError(
408
+ "Invalid DES key size. Key must be exactly 8 bytes long.")
409
+ _baseDes.__init__(self, mode, IV, pad, padmode)
410
+ self.key_size = 8
411
+
412
+ self.L = []
413
+ self.R = []
414
+ self.Kn = [[0] * 48] * 16 # 16 48-bit keys (K1 - K16)
415
+ self.final = []
416
+
417
+ self.setKey(key)
418
+
419
+ def setKey(self, key):
420
+ """Will set the crypting key for this object. Must be 8 bytes."""
421
+ _baseDes.setKey(self, key)
422
+ self.__create_sub_keys()
423
+
424
+ def __String_to_BitList(self, data):
425
+ """Turn the string data, into a list of bits (1, 0)'s"""
426
+ if _pythonMajorVersion < 3:
427
+ # Turn the strings into integers. Python 3 uses a bytes
428
+ # class, which already has this behaviour.
429
+ data = [ord(c) for c in data]
430
+ l = len(data) * 8
431
+ result = [0] * l
432
+ pos = 0
433
+ for ch in data:
434
+ i = 7
435
+ while i >= 0:
436
+ if ch & (1 << i) != 0:
437
+ result[pos] = 1
438
+ else:
439
+ result[pos] = 0
440
+ pos += 1
441
+ i -= 1
442
+
443
+ return result
444
+
445
+ def __BitList_to_String(self, data):
446
+ """Turn the list of bits -> data, into a string"""
447
+ result = []
448
+ pos = 0
449
+ c = 0
450
+ while pos < len(data):
451
+ c += data[pos] << (7 - (pos % 8))
452
+ if (pos % 8) == 7:
453
+ result.append(c)
454
+ c = 0
455
+ pos += 1
456
+
457
+ if _pythonMajorVersion < 3:
458
+ return ''.join([chr(c) for c in result])
459
+ else:
460
+ return bytes(result)
461
+
462
+ def __permutate(self, table, block):
463
+ """Permutate this block with the specified table"""
464
+ return list(map(lambda x: block[x], table))
465
+
466
+ # Transform the secret key, so that it is ready for data processing
467
+ # Create the 16 subkeys, K[1] - K[16]
468
+ def __create_sub_keys(self):
469
+ """Create the 16 subkeys K[1] to K[16] from the given key"""
470
+ key = self.__permutate(
471
+ des.__pc1, self.__String_to_BitList(self.getKey()))
472
+ i = 0
473
+ # Split into Left and Right sections
474
+ self.L = key[:28]
475
+ self.R = key[28:]
476
+ while i < 16:
477
+ j = 0
478
+ # Perform circular left shifts
479
+ while j < des.__left_rotations[i]:
480
+ self.L.append(self.L[0])
481
+ del self.L[0]
482
+
483
+ self.R.append(self.R[0])
484
+ del self.R[0]
485
+
486
+ j += 1
487
+
488
+ # Create one of the 16 subkeys through pc2 permutation
489
+ self.Kn[i] = self.__permutate(des.__pc2, self.L + self.R)
490
+
491
+ i += 1
492
+
493
+ # Main part of the encryption algorithm, the number cruncher :)
494
+ def __des_crypt(self, block, crypt_type):
495
+ """Crypt the block of data through DES bit-manipulation"""
496
+ block = self.__permutate(des.__ip, block)
497
+ self.L = block[:32]
498
+ self.R = block[32:]
499
+
500
+ # Encryption starts from Kn[1] through to Kn[16]
501
+ if crypt_type == des.ENCRYPT:
502
+ iteration = 0
503
+ iteration_adjustment = 1
504
+ # Decryption starts from Kn[16] down to Kn[1]
505
+ else:
506
+ iteration = 15
507
+ iteration_adjustment = -1
508
+
509
+ i = 0
510
+ while i < 16:
511
+ # Make a copy of R[i-1], this will later become L[i]
512
+ tempR = self.R[:]
513
+
514
+ # Permutate R[i - 1] to start creating R[i]
515
+ self.R = self.__permutate(des.__expansion_table, self.R)
516
+
517
+ # Exclusive or R[i - 1] with K[i], create B[1] to B[8] whilst here
518
+ self.R = list(map(lambda x, y: x ^ y, self.R, self.Kn[iteration]))
519
+ B = [self.R[:6], self.R[6:12], self.R[12:18], self.R[18:24],
520
+ self.R[24:30], self.R[30:36], self.R[36:42], self.R[42:]]
521
+ # Optimization: Replaced below commented code with above
522
+ #j = 0
523
+ #B = []
524
+ # while j < len(self.R):
525
+ # self.R[j] = self.R[j] ^ self.Kn[iteration][j]
526
+ # j += 1
527
+ # if j % 6 == 0:
528
+ # B.append(self.R[j-6:j])
529
+
530
+ # Permutate B[1] to B[8] using the S-Boxes
531
+ j = 0
532
+ Bn = [0] * 32
533
+ pos = 0
534
+ while j < 8:
535
+ # Work out the offsets
536
+ m = (B[j][0] << 1) + B[j][5]
537
+ n = (B[j][1] << 3) + (B[j][2] << 2) + (B[j][3] << 1) + B[j][4]
538
+
539
+ # Find the permutation value
540
+ v = des.__sbox[j][(m << 4) + n]
541
+
542
+ # Turn value into bits, add it to result: Bn
543
+ Bn[pos] = (v & 8) >> 3
544
+ Bn[pos + 1] = (v & 4) >> 2
545
+ Bn[pos + 2] = (v & 2) >> 1
546
+ Bn[pos + 3] = v & 1
547
+
548
+ pos += 4
549
+ j += 1
550
+
551
+ # Permutate the concatination of B[1] to B[8] (Bn)
552
+ self.R = self.__permutate(des.__p, Bn)
553
+
554
+ # Xor with L[i - 1]
555
+ self.R = list(map(lambda x, y: x ^ y, self.R, self.L))
556
+ # Optimization: This now replaces the below commented code
557
+ #j = 0
558
+ # while j < len(self.R):
559
+ # self.R[j] = self.R[j] ^ self.L[j]
560
+ # j += 1
561
+
562
+ # L[i] becomes R[i - 1]
563
+ self.L = tempR
564
+
565
+ i += 1
566
+ iteration += iteration_adjustment
567
+
568
+ # Final permutation of R[16]L[16]
569
+ self.final = self.__permutate(des.__fp, self.R + self.L)
570
+ return self.final
571
+
572
+ # Data to be encrypted/decrypted
573
+
574
+ def crypt(self, data, crypt_type):
575
+ """Crypt the data in blocks, running it through des_crypt()"""
576
+
577
+ # Error check the data
578
+ if not data:
579
+ return ''
580
+ if len(data) % self.block_size != 0:
581
+ if crypt_type == des.DECRYPT: # Decryption must work on 8 byte blocks
582
+ raise ValueError(
583
+ "Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n.")
584
+ if not self.getPadding():
585
+ raise ValueError("Invalid data length, data must be a multiple of " + str(
586
+ self.block_size) + " bytes\n. Try setting the optional padding character")
587
+ else:
588
+ data += (self.block_size - (len(data) %
589
+ self.block_size)) * self.getPadding()
590
+ # print("Len of data: %f" % (len(data) / self.block_size))
591
+
592
+ if self.getMode() == CBC:
593
+ if self.getIV():
594
+ iv = self.__String_to_BitList(self.getIV())
595
+ else:
596
+ raise ValueError(
597
+ "For CBC mode, you must supply the Initial Value (IV) for ciphering")
598
+
599
+ # Split the data into blocks, crypting each one seperately
600
+ i = 0
601
+ tdict = {}
602
+ result = []
603
+ #cached = 0
604
+ #lines = 0
605
+ while i < len(data):
606
+ # Test code for caching encryption results
607
+ #lines += 1
608
+ # if data[i:i+8] in tdict:
609
+ #print("Cached result for: %s" % data[i:i+8])
610
+ # cached += 1
611
+ # result.append(tdict[data[i:i+8]])
612
+ # i += 8
613
+ # continue
614
+
615
+ block = self.__String_to_BitList(data[i:i+8])
616
+
617
+ # Xor with IV if using CBC mode
618
+ if self.getMode() == CBC:
619
+ if crypt_type == des.ENCRYPT:
620
+ block = list(map(lambda x, y: x ^ y, block, iv))
621
+ #j = 0
622
+ # while j < len(block):
623
+ # block[j] = block[j] ^ iv[j]
624
+ # j += 1
625
+
626
+ processed_block = self.__des_crypt(block, crypt_type)
627
+
628
+ if crypt_type == des.DECRYPT:
629
+ processed_block = list(
630
+ map(lambda x, y: x ^ y, processed_block, iv))
631
+ #j = 0
632
+ # while j < len(processed_block):
633
+ # processed_block[j] = processed_block[j] ^ iv[j]
634
+ # j += 1
635
+ iv = block
636
+ else:
637
+ iv = processed_block
638
+ else:
639
+ processed_block = self.__des_crypt(block, crypt_type)
640
+
641
+ # Add the resulting crypted block to our list
642
+ #d = self.__BitList_to_String(processed_block)
643
+ # result.append(d)
644
+ result.append(self.__BitList_to_String(processed_block))
645
+ #tdict[data[i:i+8]] = d
646
+ i += 8
647
+
648
+ # print("Lines: %d, cached: %d" % (lines, cached))
649
+
650
+ # Return the full crypted string
651
+ if _pythonMajorVersion < 3:
652
+ return ''.join(result)
653
+ else:
654
+ return bytes.fromhex('').join(result)
655
+
656
+ def encrypt(self, data, pad=None, padmode=None):
657
+ """encrypt(data, [pad], [padmode]) -> bytes
658
+
659
+ data : Bytes to be encrypted
660
+ pad : Optional argument for encryption padding. Must only be one byte
661
+ padmode : Optional argument for overriding the padding mode.
662
+
663
+ The data must be a multiple of 8 bytes and will be encrypted
664
+ with the already specified key. Data does not have to be a
665
+ multiple of 8 bytes if the padding character is supplied, or
666
+ the padmode is set to PAD_PKCS5, as bytes will then added to
667
+ ensure the be padded data is a multiple of 8 bytes.
668
+ """
669
+ data = self._guardAgainstUnicode(data)
670
+ if pad is not None:
671
+ pad = self._guardAgainstUnicode(pad)
672
+ data = self._padData(data, pad, padmode)
673
+ return self.crypt(data, des.ENCRYPT)
674
+
675
+ def decrypt(self, data, pad=None, padmode=None):
676
+ """decrypt(data, [pad], [padmode]) -> bytes
677
+
678
+ data : Bytes to be encrypted
679
+ pad : Optional argument for decryption padding. Must only be one byte
680
+ padmode : Optional argument for overriding the padding mode.
681
+
682
+ The data must be a multiple of 8 bytes and will be decrypted
683
+ with the already specified key. In PAD_NORMAL mode, if the
684
+ optional padding character is supplied, then the un-encrypted
685
+ data will have the padding characters removed from the end of
686
+ the bytes. This pad removal only occurs on the last 8 bytes of
687
+ the data (last data block). In PAD_PKCS5 mode, the special
688
+ padding end markers will be removed from the data after decrypting.
689
+ """
690
+ data = self._guardAgainstUnicode(data)
691
+ if pad is not None:
692
+ pad = self._guardAgainstUnicode(pad)
693
+ data = self.crypt(data, des.DECRYPT)
694
+ return self._unpadData(data, pad, padmode)
695
+
696
+
697
+ #############################################################################
698
+ # Triple DES #
699
+ #############################################################################
700
+ class triple_des(_baseDes):
701
+ """Triple DES encryption/decrytpion class
702
+
703
+ This algorithm uses the DES-EDE3 (when a 24 byte key is supplied) or
704
+ the DES-EDE2 (when a 16 byte key is supplied) encryption methods.
705
+ Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
706
+
707
+ pyDes.des(key, [mode], [IV])
708
+
709
+ key -> Bytes containing the encryption key, must be either 16 or
710
+ 24 bytes long
711
+ mode -> Optional argument for encryption type, can be either pyDes.ECB
712
+ (Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
713
+ IV -> Optional Initial Value bytes, must be supplied if using CBC mode.
714
+ Must be 8 bytes in length.
715
+ pad -> Optional argument, set the pad character (PAD_NORMAL) to use
716
+ during all encrypt/decrpt operations done with this instance.
717
+ padmode -> Optional argument, set the padding mode (PAD_NORMAL or
718
+ PAD_PKCS5) to use during all encrypt/decrpt operations done
719
+ with this instance.
720
+ """
721
+
722
+ def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
723
+ _baseDes.__init__(self, mode, IV, pad, padmode)
724
+ self.setKey(key)
725
+
726
+ def setKey(self, key):
727
+ """Will set the crypting key for this object. Either 16 or 24 bytes long."""
728
+ self.key_size = 24 # Use DES-EDE3 mode
729
+ if len(key) != self.key_size:
730
+ if len(key) == 16: # Use DES-EDE2 mode
731
+ self.key_size = 16
732
+ else:
733
+ raise ValueError(
734
+ "Invalid triple DES key size. Key must be either 16 or 24 bytes long")
735
+ if self.getMode() == CBC:
736
+ if not self.getIV():
737
+ # Use the first 8 bytes of the key
738
+ self._iv = key[:self.block_size]
739
+ if len(self.getIV()) != self.block_size:
740
+ raise ValueError("Invalid IV, must be 8 bytes in length")
741
+ self.__key1 = des(key[:8], self._mode, self._iv,
742
+ self._padding, self._padmode)
743
+ self.__key2 = des(key[8:16], self._mode, self._iv,
744
+ self._padding, self._padmode)
745
+ if self.key_size == 16:
746
+ self.__key3 = self.__key1
747
+ else:
748
+ self.__key3 = des(key[16:], self._mode, self._iv,
749
+ self._padding, self._padmode)
750
+ _baseDes.setKey(self, key)
751
+
752
+ # Override setter methods to work on all 3 keys.
753
+
754
+ def setMode(self, mode):
755
+ """Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
756
+ _baseDes.setMode(self, mode)
757
+ for key in (self.__key1, self.__key2, self.__key3):
758
+ key.setMode(mode)
759
+
760
+ def setPadding(self, pad):
761
+ """setPadding() -> bytes of length 1. Padding character."""
762
+ _baseDes.setPadding(self, pad)
763
+ for key in (self.__key1, self.__key2, self.__key3):
764
+ key.setPadding(pad)
765
+
766
+ def setPadMode(self, mode):
767
+ """Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
768
+ _baseDes.setPadMode(self, mode)
769
+ for key in (self.__key1, self.__key2, self.__key3):
770
+ key.setPadMode(mode)
771
+
772
+ def setIV(self, IV):
773
+ """Will set the Initial Value, used in conjunction with CBC mode"""
774
+ _baseDes.setIV(self, IV)
775
+ for key in (self.__key1, self.__key2, self.__key3):
776
+ key.setIV(IV)
777
+
778
+ def encrypt(self, data, pad=None, padmode=None):
779
+ """encrypt(data, [pad], [padmode]) -> bytes
780
+
781
+ data : bytes to be encrypted
782
+ pad : Optional argument for encryption padding. Must only be one byte
783
+ padmode : Optional argument for overriding the padding mode.
784
+
785
+ The data must be a multiple of 8 bytes and will be encrypted
786
+ with the already specified key. Data does not have to be a
787
+ multiple of 8 bytes if the padding character is supplied, or
788
+ the padmode is set to PAD_PKCS5, as bytes will then added to
789
+ ensure the be padded data is a multiple of 8 bytes.
790
+ """
791
+ ENCRYPT = des.ENCRYPT
792
+ DECRYPT = des.DECRYPT
793
+ data = self._guardAgainstUnicode(data)
794
+ if pad is not None:
795
+ pad = self._guardAgainstUnicode(pad)
796
+ # Pad the data accordingly.
797
+ data = self._padData(data, pad, padmode)
798
+ if self.getMode() == CBC:
799
+ self.__key1.setIV(self.getIV())
800
+ self.__key2.setIV(self.getIV())
801
+ self.__key3.setIV(self.getIV())
802
+ i = 0
803
+ result = []
804
+ while i < len(data):
805
+ block = self.__key1.crypt(data[i:i+8], ENCRYPT)
806
+ block = self.__key2.crypt(block, DECRYPT)
807
+ block = self.__key3.crypt(block, ENCRYPT)
808
+ self.__key1.setIV(block)
809
+ self.__key2.setIV(block)
810
+ self.__key3.setIV(block)
811
+ result.append(block)
812
+ i += 8
813
+ if _pythonMajorVersion < 3:
814
+ return ''.join(result)
815
+ else:
816
+ return bytes.fromhex('').join(result)
817
+ else:
818
+ data = self.__key1.crypt(data, ENCRYPT)
819
+ data = self.__key2.crypt(data, DECRYPT)
820
+ return self.__key3.crypt(data, ENCRYPT)
821
+
822
+ def decrypt(self, data, pad=None, padmode=None):
823
+ """decrypt(data, [pad], [padmode]) -> bytes
824
+
825
+ data : bytes to be encrypted
826
+ pad : Optional argument for decryption padding. Must only be one byte
827
+ padmode : Optional argument for overriding the padding mode.
828
+
829
+ The data must be a multiple of 8 bytes and will be decrypted
830
+ with the already specified key. In PAD_NORMAL mode, if the
831
+ optional padding character is supplied, then the un-encrypted
832
+ data will have the padding characters removed from the end of
833
+ the bytes. This pad removal only occurs on the last 8 bytes of
834
+ the data (last data block). In PAD_PKCS5 mode, the special
835
+ padding end markers will be removed from the data after
836
+ decrypting, no pad character is required for PAD_PKCS5.
837
+ """
838
+ ENCRYPT = des.ENCRYPT
839
+ DECRYPT = des.DECRYPT
840
+ data = self._guardAgainstUnicode(data)
841
+ if pad is not None:
842
+ pad = self._guardAgainstUnicode(pad)
843
+ if self.getMode() == CBC:
844
+ self.__key1.setIV(self.getIV())
845
+ self.__key2.setIV(self.getIV())
846
+ self.__key3.setIV(self.getIV())
847
+ i = 0
848
+ result = []
849
+ while i < len(data):
850
+ iv = data[i:i+8]
851
+ block = self.__key3.crypt(iv, DECRYPT)
852
+ block = self.__key2.crypt(block, ENCRYPT)
853
+ block = self.__key1.crypt(block, DECRYPT)
854
+ self.__key1.setIV(iv)
855
+ self.__key2.setIV(iv)
856
+ self.__key3.setIV(iv)
857
+ result.append(block)
858
+ i += 8
859
+ if _pythonMajorVersion < 3:
860
+ data = ''.join(result)
861
+ else:
862
+ data = bytes.fromhex('').join(result)
863
+ else:
864
+ data = self.__key3.crypt(data, DECRYPT)
865
+ data = self.__key2.crypt(data, ENCRYPT)
866
+ data = self.__key1.crypt(data, DECRYPT)
867
+ return self._unpadData(data, pad, padmode)