Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

first pass at working code

  • Loading branch information...
commit e9526e90f048db957820937d5de5fbf01cd4d222 1 parent 992c9d7
authored
19  LICENSE.txt
... ...
@@ -0,0 +1,19 @@
  1
+Copyright (c) 2010 Marc Sibson
  2
+
  3
+Permission is hereby granted, free of charge, to any person obtaining a copy
  4
+of this software and associated documentation files (the "Software"), to deal
  5
+in the Software without restriction, including without limitation the rights
  6
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  7
+copies of the Software, and to permit persons to whom the Software is
  8
+furnished to do so, subject to the following conditions:
  9
+
  10
+The above copyright notice and this permission notice shall be included in
  11
+all copies or substantial portions of the Software.
  12
+
  13
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  14
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  15
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  16
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  17
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  18
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  19
+THE SOFTWARE.
25  README.txt
@@ -5,3 +5,28 @@ the command line.
5 5
 
6 6
 Currently under developement and altogether not ready for general use. One
7 7
 day it might actually be useful.
  8
+
  9
+Quick Start
  10
+--------------------------------
  11
+Assuming you have a VNC server already running you can quickly try out
  12
+vncdotool by running::
  13
+
  14
+    python vncdotool -h hostaddr -d displaynum click 2
  15
+
  16
+Which for most window managers will open a context menu at the top left
  17
+corner of the screen.
  18
+
  19
+Usage
  20
+--------------------------------
  21
+
  22
+Acknowledgements
  23
+--------------------------------
  24
+Thanks to 
  25
+
  26
+(c) 2003 chris <cliechti@gmx.net>
  27
+(c) 2009 techtonik <techtonik@gmail.com>
  28
+
  29
+
  30
+whose python-vnc-viewer_, provided the RFB protocol implementation used by vncdotool.
  31
+
  32
+_python-vnc_viewer: http://code.google.com/p/python-vnc-viewer/
5  scripts/vncdotool
... ...
@@ -0,0 +1,5 @@
  1
+#!/usr/bin/env python
  2
+from vncdotool.command import main
  3
+
  4
+if __name__ == '__main__':
  5
+    main()
41  setup.py
... ...
@@ -0,0 +1,41 @@
  1
+#!/usr/bin/env python
  2
+
  3
+from distutils.core import setup
  4
+
  5
+setup(
  6
+    name='vncdotool',
  7
+    version='0.1.0dev',
  8
+    description='Send keyboard and mouse events to a VNC server from the command line',
  9
+    requires=[
  10
+        'Twisted',
  11
+    ],
  12
+
  13
+    url='http://github.com/sibson/vncdotool',
  14
+    author='Marc Sibson',
  15
+    author_email='sibson+vncdotool@gmail.com',
  16
+    download_url='',
  17
+
  18
+    scripts=['scripts/vncdotool'],
  19
+    packages=['vncdotool'],
  20
+
  21
+    classifiers=[
  22
+          'Development Status :: 2 - Pre-Alpha',
  23
+          'Environment :: Console',
  24
+          'Framework :: Twisted',
  25
+          'Intended Audience :: Developers',
  26
+          'Intended Audience :: System Administrators',
  27
+          'License :: OSI Approved :: MIT License',
  28
+          'Operating System :: MacOS :: MacOS X',
  29
+          'Operating System :: Microsoft :: Windows',
  30
+          'Operating System :: POSIX',
  31
+          'Programming Language :: Python',
  32
+          'Programming Language :: Python :: 2.4',
  33
+          'Programming Language :: Python :: 2.5',
  34
+          'Programming Language :: Python :: 2.6',
  35
+          'Programming Language :: Python :: 2.7',
  36
+          'Topic :: Multimedia :: Graphics :: Viewers',
  37
+          'Topic :: Software Development :: Testing',
  38
+    ],
  39
+
  40
+    long_description='',
  41
+)
0  vncdotool/__init__.py
No changes.
62  vncdotool/client.py
... ...
@@ -0,0 +1,62 @@
  1
+"""
  2
+
  3
+(c) 2010 Marc Sibson
  4
+
  5
+MIT License
  6
+"""
  7
+
  8
+from rfb import RFBClient, RFBFactory
  9
+from twisted.internet import reactor
  10
+from twisted.internet.defer import Deferred
  11
+
  12
+
  13
+class VNCDoToolClient(RFBClient):
  14
+    x = 0
  15
+    y = 0
  16
+
  17
+    def vncConnectionMade(self):
  18
+        self.setPixelFormat()
  19
+        self.factory.deferred.callback(self)
  20
+
  21
+    def keyPress(self, key):
  22
+        self.keyEvent(ord(key), down=1)
  23
+        self.keyEvent(ord(key), down=0)
  24
+        return self
  25
+
  26
+    def mousePress(self, button):
  27
+        buttons = 1 << button
  28
+        self.pointerEvent(self.x, self.y, buttonmask=buttons)
  29
+        self.pointerEvent(self.x, self.y, buttonmask=0)
  30
+        return self
  31
+        
  32
+
  33
+    def mouseMove(self, x, y):
  34
+        self.x, self.y = x, y
  35
+        self.pointerEvent(x, y)
  36
+        return self
  37
+
  38
+    def bell(self):
  39
+        print 'ding'
  40
+
  41
+    def copy_text(self, text):
  42
+        print 'clip', repr(text)
  43
+
  44
+    def paste(self, message):
  45
+        self.clientCutText(message)
  46
+        return self
  47
+
  48
+
  49
+class VNCDoToolFactory(RFBFactory):
  50
+    protocol = VNCDoToolClient
  51
+    password = None
  52
+    shared = 1
  53
+
  54
+    def __init__(self):
  55
+        self.deferred = Deferred()
  56
+
  57
+    def clientConnectionFailed(self, connector, reason):
  58
+        print 'connection failed', reason
  59
+        reactor.callLater(0, self.deferred.errback, reason)
  60
+        self.deferred = None
  61
+        
  62
+
77  vncdotool/command.py
... ...
@@ -0,0 +1,77 @@
  1
+#!/usr/bin/env python
  2
+"""
  3
+
  4
+(c) 2010 Marc Sibson
  5
+
  6
+MIT License
  7
+"""
  8
+import optparse
  9
+
  10
+from twisted.internet import reactor
  11
+
  12
+from vncdotool.client import VNCDoToolFactory, VNCDoToolClient
  13
+
  14
+def log_connected(pcol):
  15
+    print 'connected to', pcol.name
  16
+    return pcol
  17
+
  18
+
  19
+def log_failed(reason):
  20
+    print 'connection failed', reason.getErrorMesssage()
  21
+
  22
+
  23
+def stop(pcol):
  24
+    pcol.transport.loseConnection()
  25
+    reactor.callLater(0.1, reactor.stop)
  26
+
  27
+def main():
  28
+    op = optparse.OptionParser(usage='%prog [options] cmd', 
  29
+                                add_help_option=False)
  30
+    op.add_option('-d', '--display', action='store', metavar='DISPLAY',
  31
+        type='int', default=0,
  32
+        help='connect to vnc server on DISPLAY [%default]')
  33
+    op.add_option('--help', action='help', 
  34
+        help='show this help message')
  35
+    op.add_option('-h', '--host', action='store', metavar='HOST',
  36
+        default='127.0.0.1',
  37
+        help='connect to vnc server at HOST [%default]')
  38
+    op.add_option('-p', '--port', action='store', metavar='PORT',
  39
+        type='int',
  40
+        help='connect to vnc server on PORT')
  41
+    op.add_option('-v', '--verbose', action='store_true')
  42
+
  43
+    opts, args = op.parse_args()
  44
+    if opts.port is None:
  45
+        opts.port = opts.display + 5900
  46
+        
  47
+    if not len(args):
  48
+        op.error('no command provided')
  49
+
  50
+    f = VNCDoToolFactory()
  51
+    if opts.verbose:
  52
+        print 'connecting to %s:%d' % (opts.host, opts.port)
  53
+    
  54
+    if opts.verbose:
  55
+        f.deferred.addCallbacks(log_connected, log_failed)
  56
+
  57
+    while args:
  58
+        cmd = args.pop(0)
  59
+        if cmd == 'key':
  60
+            f.deferred.addCallback(VNCDoToolClient.keyPress, args.pop(0))
  61
+        elif cmd == 'move':
  62
+            x, y = int(args.pop(0)), int(args.pop(0))
  63
+            f.deferred.addCallback(VNCDoToolClient.mouseMove, x, y)
  64
+        elif cmd == 'click':
  65
+            button = int(args.pop(0))
  66
+            f.deferred.addCallback(VNCDoToolClient.mousePress, button)
  67
+        elif cmd == 'type':
  68
+            for key in args.pop(0):
  69
+                f.deferred.addCallback(VNCDoToolClient.keyPress, key)
  70
+        
  71
+    f.deferred.addCallback(stop)
  72
+
  73
+    reactor.connectTCP(opts.host, opts.port, f)
  74
+    reactor.run()
  75
+
  76
+if __name__ == '__main__':
  77
+    main()
852  vncdotool/pyDes.py
... ...
@@ -0,0 +1,852 @@
  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
+class _baseDes(object):
  108
+	def __init__(self, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
  109
+		if IV:
  110
+			IV = self._guardAgainstUnicode(IV)
  111
+		if pad:
  112
+			pad = self._guardAgainstUnicode(pad)
  113
+		self.block_size = 8
  114
+		# Sanity checking of arguments.
  115
+		if pad and padmode == PAD_PKCS5:
  116
+			raise ValueError("Cannot use a pad character with PAD_PKCS5")
  117
+		if IV and len(IV) != self.block_size:
  118
+			raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
  119
+
  120
+		# Set the passed in variables
  121
+		self._mode = mode
  122
+		self._iv = IV
  123
+		self._padding = pad
  124
+		self._padmode = padmode
  125
+
  126
+	def getKey(self):
  127
+		"""getKey() -> bytes"""
  128
+		return self.__key
  129
+
  130
+	def setKey(self, key):
  131
+		"""Will set the crypting key for this object."""
  132
+		key = self._guardAgainstUnicode(key)
  133
+		self.__key = key
  134
+
  135
+	def getMode(self):
  136
+		"""getMode() -> pyDes.ECB or pyDes.CBC"""
  137
+		return self._mode
  138
+
  139
+	def setMode(self, mode):
  140
+		"""Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
  141
+		self._mode = mode
  142
+
  143
+	def getPadding(self):
  144
+		"""getPadding() -> bytes of length 1. Padding character."""
  145
+		return self._padding
  146
+
  147
+	def setPadding(self, pad):
  148
+		"""setPadding() -> bytes of length 1. Padding character."""
  149
+		if pad is not None:
  150
+			pad = self._guardAgainstUnicode(pad)
  151
+		self._padding = pad
  152
+
  153
+	def getPadMode(self):
  154
+		"""getPadMode() -> pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
  155
+		return self._padmode
  156
+		
  157
+	def setPadMode(self, mode):
  158
+		"""Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
  159
+		self._padmode = mode
  160
+
  161
+	def getIV(self):
  162
+		"""getIV() -> bytes"""
  163
+		return self._iv
  164
+
  165
+	def setIV(self, IV):
  166
+		"""Will set the Initial Value, used in conjunction with CBC mode"""
  167
+		if not IV or len(IV) != self.block_size:
  168
+			raise ValueError("Invalid Initial Value (IV), must be a multiple of " + str(self.block_size) + " bytes")
  169
+		IV = self._guardAgainstUnicode(IV)
  170
+		self._iv = IV
  171
+
  172
+	def _padData(self, data, pad, padmode):
  173
+		# Pad data depending on the mode
  174
+		if padmode is None:
  175
+			# Get the default padding mode.
  176
+			padmode = self.getPadMode()
  177
+		if pad and padmode == PAD_PKCS5:
  178
+			raise ValueError("Cannot use a pad character with PAD_PKCS5")
  179
+
  180
+		if padmode == PAD_NORMAL:
  181
+			if len(data) % self.block_size == 0:
  182
+				# No padding required.
  183
+				return data
  184
+
  185
+			if not pad:
  186
+				# Get the default padding.
  187
+				pad = self.getPadding()
  188
+			if not pad:
  189
+				raise ValueError("Data must be a multiple of " + str(self.block_size) + " bytes in length. Use padmode=PAD_PKCS5 or set the pad character.")
  190
+			data += (self.block_size - (len(data) % self.block_size)) * pad
  191
+		
  192
+		elif padmode == PAD_PKCS5:
  193
+			pad_len = 8 - (len(data) % self.block_size)
  194
+			if _pythonMajorVersion < 3:
  195
+				data += pad_len * chr(pad_len)
  196
+			else:
  197
+				data += bytes([pad_len] * pad_len)
  198
+
  199
+		return data
  200
+
  201
+	def _unpadData(self, data, pad, padmode):
  202
+		# Unpad data depending on the mode.
  203
+		if not data:
  204
+			return data
  205
+		if pad and padmode == PAD_PKCS5:
  206
+			raise ValueError("Cannot use a pad character with PAD_PKCS5")
  207
+		if padmode is None:
  208
+			# Get the default padding mode.
  209
+			padmode = self.getPadMode()
  210
+
  211
+		if padmode == PAD_NORMAL:
  212
+			if not pad:
  213
+				# Get the default padding.
  214
+				pad = self.getPadding()
  215
+			if pad:
  216
+				data = data[:-self.block_size] + \
  217
+				       data[-self.block_size:].rstrip(pad)
  218
+
  219
+		elif padmode == PAD_PKCS5:
  220
+			if _pythonMajorVersion < 3:
  221
+				pad_len = ord(data[-1])
  222
+			else:
  223
+				pad_len = data[-1]
  224
+			data = data[:-pad_len]
  225
+
  226
+		return data
  227
+
  228
+	def _guardAgainstUnicode(self, data):
  229
+		# Only accept byte strings or ascii unicode values, otherwise
  230
+		# there is no way to correctly decode the data into bytes.
  231
+		if _pythonMajorVersion < 3:
  232
+			if isinstance(data, unicode):
  233
+				raise ValueError("pyDes can only work with bytes, not Unicode strings.")
  234
+		else:
  235
+			if isinstance(data, str):
  236
+				# Only accept ascii unicode values.
  237
+				try:
  238
+					return data.encode('ascii')
  239
+				except UnicodeEncodeError:
  240
+					pass
  241
+				raise ValueError("pyDes can only work with encoded strings, not Unicode.")
  242
+		return data
  243
+
  244
+#############################################################################
  245
+# 				    DES					    #
  246
+#############################################################################
  247
+class des(_baseDes):
  248
+	"""DES encryption/decrytpion class
  249
+
  250
+	Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
  251
+
  252
+	pyDes.des(key,[mode], [IV])
  253
+
  254
+	key  -> Bytes containing the encryption key, must be exactly 8 bytes
  255
+	mode -> Optional argument for encryption type, can be either pyDes.ECB
  256
+		(Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
  257
+	IV   -> Optional Initial Value bytes, must be supplied if using CBC mode.
  258
+		Must be 8 bytes in length.
  259
+	pad  -> Optional argument, set the pad character (PAD_NORMAL) to use
  260
+		during all encrypt/decrpt operations done with this instance.
  261
+	padmode -> Optional argument, set the padding mode (PAD_NORMAL or
  262
+		PAD_PKCS5) to use during all encrypt/decrpt operations done
  263
+		with this instance.
  264
+	"""
  265
+
  266
+
  267
+	# Permutation and translation tables for DES
  268
+	__pc1 = [56, 48, 40, 32, 24, 16,  8,
  269
+		  0, 57, 49, 41, 33, 25, 17,
  270
+		  9,  1, 58, 50, 42, 34, 26,
  271
+		 18, 10,  2, 59, 51, 43, 35,
  272
+		 62, 54, 46, 38, 30, 22, 14,
  273
+		  6, 61, 53, 45, 37, 29, 21,
  274
+		 13,  5, 60, 52, 44, 36, 28,
  275
+		 20, 12,  4, 27, 19, 11,  3
  276
+	]
  277
+
  278
+	# number left rotations of pc1
  279
+	__left_rotations = [
  280
+		1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
  281
+	]
  282
+
  283
+	# permuted choice key (table 2)
  284
+	__pc2 = [
  285
+		13, 16, 10, 23,  0,  4,
  286
+		 2, 27, 14,  5, 20,  9,
  287
+		22, 18, 11,  3, 25,  7,
  288
+		15,  6, 26, 19, 12,  1,
  289
+		40, 51, 30, 36, 46, 54,
  290
+		29, 39, 50, 44, 32, 47,
  291
+		43, 48, 38, 55, 33, 52,
  292
+		45, 41, 49, 35, 28, 31
  293
+	]
  294
+
  295
+	# initial permutation IP
  296
+	__ip = [57, 49, 41, 33, 25, 17, 9,  1,
  297
+		59, 51, 43, 35, 27, 19, 11, 3,
  298
+		61, 53, 45, 37, 29, 21, 13, 5,
  299
+		63, 55, 47, 39, 31, 23, 15, 7,
  300
+		56, 48, 40, 32, 24, 16, 8,  0,
  301
+		58, 50, 42, 34, 26, 18, 10, 2,
  302
+		60, 52, 44, 36, 28, 20, 12, 4,
  303
+		62, 54, 46, 38, 30, 22, 14, 6
  304
+	]
  305
+
  306
+	# Expansion table for turning 32 bit blocks into 48 bits
  307
+	__expansion_table = [
  308
+		31,  0,  1,  2,  3,  4,
  309
+		 3,  4,  5,  6,  7,  8,
  310
+		 7,  8,  9, 10, 11, 12,
  311
+		11, 12, 13, 14, 15, 16,
  312
+		15, 16, 17, 18, 19, 20,
  313
+		19, 20, 21, 22, 23, 24,
  314
+		23, 24, 25, 26, 27, 28,
  315
+		27, 28, 29, 30, 31,  0
  316
+	]
  317
+
  318
+	# The (in)famous S-boxes
  319
+	__sbox = [
  320
+		# S1
  321
+		[14, 4, 13, 1, 2, 15, 11, 8, 3, 10, 6, 12, 5, 9, 0, 7,
  322
+		 0, 15, 7, 4, 14, 2, 13, 1, 10, 6, 12, 11, 9, 5, 3, 8,
  323
+		 4, 1, 14, 8, 13, 6, 2, 11, 15, 12, 9, 7, 3, 10, 5, 0,
  324
+		 15, 12, 8, 2, 4, 9, 1, 7, 5, 11, 3, 14, 10, 0, 6, 13],
  325
+
  326
+		# S2
  327
+		[15, 1, 8, 14, 6, 11, 3, 4, 9, 7, 2, 13, 12, 0, 5, 10,
  328
+		 3, 13, 4, 7, 15, 2, 8, 14, 12, 0, 1, 10, 6, 9, 11, 5,
  329
+		 0, 14, 7, 11, 10, 4, 13, 1, 5, 8, 12, 6, 9, 3, 2, 15,
  330
+		 13, 8, 10, 1, 3, 15, 4, 2, 11, 6, 7, 12, 0, 5, 14, 9],
  331
+
  332
+		# S3
  333
+		[10, 0, 9, 14, 6, 3, 15, 5, 1, 13, 12, 7, 11, 4, 2, 8,
  334
+		 13, 7, 0, 9, 3, 4, 6, 10, 2, 8, 5, 14, 12, 11, 15, 1,
  335
+		 13, 6, 4, 9, 8, 15, 3, 0, 11, 1, 2, 12, 5, 10, 14, 7,
  336
+		 1, 10, 13, 0, 6, 9, 8, 7, 4, 15, 14, 3, 11, 5, 2, 12],
  337
+
  338
+		# S4
  339
+		[7, 13, 14, 3, 0, 6, 9, 10, 1, 2, 8, 5, 11, 12, 4, 15,
  340
+		 13, 8, 11, 5, 6, 15, 0, 3, 4, 7, 2, 12, 1, 10, 14, 9,
  341
+		 10, 6, 9, 0, 12, 11, 7, 13, 15, 1, 3, 14, 5, 2, 8, 4,
  342
+		 3, 15, 0, 6, 10, 1, 13, 8, 9, 4, 5, 11, 12, 7, 2, 14],
  343
+
  344
+		# S5
  345
+		[2, 12, 4, 1, 7, 10, 11, 6, 8, 5, 3, 15, 13, 0, 14, 9,
  346
+		 14, 11, 2, 12, 4, 7, 13, 1, 5, 0, 15, 10, 3, 9, 8, 6,
  347
+		 4, 2, 1, 11, 10, 13, 7, 8, 15, 9, 12, 5, 6, 3, 0, 14,
  348
+		 11, 8, 12, 7, 1, 14, 2, 13, 6, 15, 0, 9, 10, 4, 5, 3],
  349
+
  350
+		# S6
  351
+		[12, 1, 10, 15, 9, 2, 6, 8, 0, 13, 3, 4, 14, 7, 5, 11,
  352
+		 10, 15, 4, 2, 7, 12, 9, 5, 6, 1, 13, 14, 0, 11, 3, 8,
  353
+		 9, 14, 15, 5, 2, 8, 12, 3, 7, 0, 4, 10, 1, 13, 11, 6,
  354
+		 4, 3, 2, 12, 9, 5, 15, 10, 11, 14, 1, 7, 6, 0, 8, 13],
  355
+
  356
+		# S7
  357
+		[4, 11, 2, 14, 15, 0, 8, 13, 3, 12, 9, 7, 5, 10, 6, 1,
  358
+		 13, 0, 11, 7, 4, 9, 1, 10, 14, 3, 5, 12, 2, 15, 8, 6,
  359
+		 1, 4, 11, 13, 12, 3, 7, 14, 10, 15, 6, 8, 0, 5, 9, 2,
  360
+		 6, 11, 13, 8, 1, 4, 10, 7, 9, 5, 0, 15, 14, 2, 3, 12],
  361
+
  362
+		# S8
  363
+		[13, 2, 8, 4, 6, 15, 11, 1, 10, 9, 3, 14, 5, 0, 12, 7,
  364
+		 1, 15, 13, 8, 10, 3, 7, 4, 12, 5, 6, 11, 0, 14, 9, 2,
  365
+		 7, 11, 4, 1, 9, 12, 14, 2, 0, 6, 10, 13, 15, 3, 5, 8,
  366
+		 2, 1, 14, 7, 4, 10, 8, 13, 15, 12, 9, 0, 3, 5, 6, 11],
  367
+	]
  368
+
  369
+
  370
+	# 32-bit permutation function P used on the output of the S-boxes
  371
+	__p = [
  372
+		15, 6, 19, 20, 28, 11,
  373
+		27, 16, 0, 14, 22, 25,
  374
+		4, 17, 30, 9, 1, 7,
  375
+		23,13, 31, 26, 2, 8,
  376
+		18, 12, 29, 5, 21, 10,
  377
+		3, 24
  378
+	]
  379
+
  380
+	# final permutation IP^-1
  381
+	__fp = [
  382
+		39,  7, 47, 15, 55, 23, 63, 31,
  383
+		38,  6, 46, 14, 54, 22, 62, 30,
  384
+		37,  5, 45, 13, 53, 21, 61, 29,
  385
+		36,  4, 44, 12, 52, 20, 60, 28,
  386
+		35,  3, 43, 11, 51, 19, 59, 27,
  387
+		34,  2, 42, 10, 50, 18, 58, 26,
  388
+		33,  1, 41,  9, 49, 17, 57, 25,
  389
+		32,  0, 40,  8, 48, 16, 56, 24
  390
+	]
  391
+
  392
+	# Type of crypting being done
  393
+	ENCRYPT =	0x00
  394
+	DECRYPT =	0x01
  395
+
  396
+	# Initialisation
  397
+	def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
  398
+		# Sanity checking of arguments.
  399
+		if len(key) != 8:
  400
+			raise ValueError("Invalid DES key size. Key must be exactly 8 bytes long.")
  401
+		_baseDes.__init__(self, mode, IV, pad, padmode)
  402
+		self.key_size = 8
  403
+
  404
+		self.L = []
  405
+		self.R = []
  406
+		self.Kn = [ [0] * 48 ] * 16	# 16 48-bit keys (K1 - K16)
  407
+		self.final = []
  408
+
  409
+		self.setKey(key)
  410
+
  411
+	def setKey(self, key):
  412
+		"""Will set the crypting key for this object. Must be 8 bytes."""
  413
+		_baseDes.setKey(self, key)
  414
+		self.__create_sub_keys()
  415
+
  416
+	def __String_to_BitList(self, data):
  417
+		"""Turn the string data, into a list of bits (1, 0)'s"""
  418
+		if _pythonMajorVersion < 3:
  419
+			# Turn the strings into integers. Python 3 uses a bytes
  420
+			# class, which already has this behaviour.
  421
+			data = [ord(c) for c in data]
  422
+		l = len(data) * 8
  423
+		result = [0] * l
  424
+		pos = 0
  425
+		for ch in data:
  426
+			i = 7
  427
+			while i >= 0:
  428
+				if ch & (1 << i) != 0:
  429
+					result[pos] = 1
  430
+				else:
  431
+					result[pos] = 0
  432
+				pos += 1
  433
+				i -= 1
  434
+
  435
+		return result
  436
+
  437
+	def __BitList_to_String(self, data):
  438
+		"""Turn the list of bits -> data, into a string"""
  439
+		result = []
  440
+		pos = 0
  441
+		c = 0
  442
+		while pos < len(data):
  443
+			c += data[pos] << (7 - (pos % 8))
  444
+			if (pos % 8) == 7:
  445
+				result.append(c)
  446
+				c = 0
  447
+			pos += 1
  448
+
  449
+		if _pythonMajorVersion < 3:
  450
+			return ''.join([ chr(c) for c in result ])
  451
+		else:
  452
+			return bytes(result)
  453
+
  454
+	def __permutate(self, table, block):
  455
+		"""Permutate this block with the specified table"""
  456
+		return list(map(lambda x: block[x], table))
  457
+	
  458
+	# Transform the secret key, so that it is ready for data processing
  459
+	# Create the 16 subkeys, K[1] - K[16]
  460
+	def __create_sub_keys(self):
  461
+		"""Create the 16 subkeys K[1] to K[16] from the given key"""
  462
+		key = self.__permutate(des.__pc1, self.__String_to_BitList(self.getKey()))
  463
+		i = 0
  464
+		# Split into Left and Right sections
  465
+		self.L = key[:28]
  466
+		self.R = key[28:]
  467
+		while i < 16:
  468
+			j = 0
  469
+			# Perform circular left shifts
  470
+			while j < des.__left_rotations[i]:
  471
+				self.L.append(self.L[0])
  472
+				del self.L[0]
  473
+
  474
+				self.R.append(self.R[0])
  475
+				del self.R[0]
  476
+
  477
+				j += 1
  478
+
  479
+			# Create one of the 16 subkeys through pc2 permutation
  480
+			self.Kn[i] = self.__permutate(des.__pc2, self.L + self.R)
  481
+
  482
+			i += 1
  483
+
  484
+	# Main part of the encryption algorithm, the number cruncher :)
  485
+	def __des_crypt(self, block, crypt_type):
  486
+		"""Crypt the block of data through DES bit-manipulation"""
  487
+		block = self.__permutate(des.__ip, block)
  488
+		self.L = block[:32]
  489
+		self.R = block[32:]
  490
+
  491
+		# Encryption starts from Kn[1] through to Kn[16]
  492
+		if crypt_type == des.ENCRYPT:
  493
+			iteration = 0
  494
+			iteration_adjustment = 1
  495
+		# Decryption starts from Kn[16] down to Kn[1]
  496
+		else:
  497
+			iteration = 15
  498
+			iteration_adjustment = -1
  499
+
  500
+		i = 0
  501
+		while i < 16:
  502
+			# Make a copy of R[i-1], this will later become L[i]
  503
+			tempR = self.R[:]
  504
+
  505
+			# Permutate R[i - 1] to start creating R[i]
  506
+			self.R = self.__permutate(des.__expansion_table, self.R)
  507
+
  508
+			# Exclusive or R[i - 1] with K[i], create B[1] to B[8] whilst here
  509
+			self.R = list(map(lambda x, y: x ^ y, self.R, self.Kn[iteration]))
  510
+			B = [self.R[:6], self.R[6:12], self.R[12:18], self.R[18:24], self.R[24:30], self.R[30:36], self.R[36:42], self.R[42:]]
  511
+			# Optimization: Replaced below commented code with above
  512
+			#j = 0
  513
+			#B = []
  514
+			#while j < len(self.R):
  515
+			#	self.R[j] = self.R[j] ^ self.Kn[iteration][j]
  516
+			#	j += 1
  517
+			#	if j % 6 == 0:
  518
+			#		B.append(self.R[j-6:j])
  519
+
  520
+			# Permutate B[1] to B[8] using the S-Boxes
  521
+			j = 0
  522
+			Bn = [0] * 32
  523
+			pos = 0
  524
+			while j < 8:
  525
+				# Work out the offsets
  526
+				m = (B[j][0] << 1) + B[j][5]
  527
+				n = (B[j][1] << 3) + (B[j][2] << 2) + (B[j][3] << 1) + B[j][4]
  528
+
  529
+				# Find the permutation value
  530
+				v = des.__sbox[j][(m << 4) + n]
  531
+
  532
+				# Turn value into bits, add it to result: Bn
  533
+				Bn[pos] = (v & 8) >> 3
  534
+				Bn[pos + 1] = (v & 4) >> 2
  535
+				Bn[pos + 2] = (v & 2) >> 1
  536
+				Bn[pos + 3] = v & 1
  537
+
  538
+				pos += 4
  539
+				j += 1
  540
+
  541
+			# Permutate the concatination of B[1] to B[8] (Bn)
  542
+			self.R = self.__permutate(des.__p, Bn)
  543
+
  544
+			# Xor with L[i - 1]
  545
+			self.R = list(map(lambda x, y: x ^ y, self.R, self.L))
  546
+			# Optimization: This now replaces the below commented code
  547
+			#j = 0
  548
+			#while j < len(self.R):
  549
+			#	self.R[j] = self.R[j] ^ self.L[j]
  550
+			#	j += 1
  551
+
  552
+			# L[i] becomes R[i - 1]
  553
+			self.L = tempR
  554
+
  555
+			i += 1
  556
+			iteration += iteration_adjustment
  557
+		
  558
+		# Final permutation of R[16]L[16]
  559
+		self.final = self.__permutate(des.__fp, self.R + self.L)
  560
+		return self.final
  561
+
  562
+
  563
+	# Data to be encrypted/decrypted
  564
+	def crypt(self, data, crypt_type):
  565
+		"""Crypt the data in blocks, running it through des_crypt()"""
  566
+
  567
+		# Error check the data
  568
+		if not data:
  569
+			return ''
  570
+		if len(data) % self.block_size != 0:
  571
+			if crypt_type == des.DECRYPT: # Decryption must work on 8 byte blocks
  572
+				raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n.")
  573
+			if not self.getPadding():
  574
+				raise ValueError("Invalid data length, data must be a multiple of " + str(self.block_size) + " bytes\n. Try setting the optional padding character")
  575
+			else:
  576
+				data += (self.block_size - (len(data) % self.block_size)) * self.getPadding()
  577
+			# print "Len of data: %f" % (len(data) / self.block_size)
  578
+
  579
+		if self.getMode() == CBC:
  580
+			if self.getIV():
  581
+				iv = self.__String_to_BitList(self.getIV())
  582
+			else:
  583
+				raise ValueError("For CBC mode, you must supply the Initial Value (IV) for ciphering")
  584
+
  585
+		# Split the data into blocks, crypting each one seperately
  586
+		i = 0
  587
+		dict = {}
  588
+		result = []
  589
+		#cached = 0
  590
+		#lines = 0
  591
+		while i < len(data):
  592
+			# Test code for caching encryption results
  593
+			#lines += 1
  594
+			#if dict.has_key(data[i:i+8]):
  595
+				#print "Cached result for: %s" % data[i:i+8]
  596
+			#	cached += 1
  597
+			#	result.append(dict[data[i:i+8]])
  598
+			#	i += 8
  599
+			#	continue
  600
+				
  601
+			block = self.__String_to_BitList(data[i:i+8])
  602
+
  603
+			# Xor with IV if using CBC mode
  604
+			if self.getMode() == CBC:
  605
+				if crypt_type == des.ENCRYPT:
  606
+					block = list(map(lambda x, y: x ^ y, block, iv))
  607
+					#j = 0
  608
+					#while j < len(block):
  609
+					#	block[j] = block[j] ^ iv[j]
  610
+					#	j += 1
  611
+
  612
+				processed_block = self.__des_crypt(block, crypt_type)
  613
+
  614
+				if crypt_type == des.DECRYPT:
  615
+					processed_block = list(map(lambda x, y: x ^ y, processed_block, iv))
  616
+					#j = 0
  617
+					#while j < len(processed_block):
  618
+					#	processed_block[j] = processed_block[j] ^ iv[j]
  619
+					#	j += 1
  620
+					iv = block
  621
+				else:
  622
+					iv = processed_block
  623
+			else:
  624
+				processed_block = self.__des_crypt(block, crypt_type)
  625
+
  626
+
  627
+			# Add the resulting crypted block to our list
  628
+			#d = self.__BitList_to_String(processed_block)
  629
+			#result.append(d)
  630
+			result.append(self.__BitList_to_String(processed_block))
  631
+			#dict[data[i:i+8]] = d
  632
+			i += 8
  633
+
  634
+		# print "Lines: %d, cached: %d" % (lines, cached)
  635
+
  636
+		# Return the full crypted string
  637
+		if _pythonMajorVersion < 3:
  638
+			return ''.join(result)
  639
+		else:
  640
+			return bytes.fromhex('').join(result)
  641
+
  642
+	def encrypt(self, data, pad=None, padmode=None):
  643
+		"""encrypt(data, [pad], [padmode]) -> bytes
  644
+
  645
+		data : Bytes to be encrypted
  646
+		pad  : Optional argument for encryption padding. Must only be one byte
  647
+		padmode : Optional argument for overriding the padding mode.
  648
+
  649
+		The data must be a multiple of 8 bytes and will be encrypted
  650
+		with the already specified key. Data does not have to be a
  651
+		multiple of 8 bytes if the padding character is supplied, or
  652
+		the padmode is set to PAD_PKCS5, as bytes will then added to
  653
+		ensure the be padded data is a multiple of 8 bytes.
  654
+		"""
  655
+		data = self._guardAgainstUnicode(data)
  656
+		if pad is not None:
  657
+			pad = self._guardAgainstUnicode(pad)
  658
+		data = self._padData(data, pad, padmode)
  659
+		return self.crypt(data, des.ENCRYPT)
  660
+
  661
+	def decrypt(self, data, pad=None, padmode=None):
  662
+		"""decrypt(data, [pad], [padmode]) -> bytes
  663
+
  664
+		data : Bytes to be encrypted
  665
+		pad  : Optional argument for decryption padding. Must only be one byte
  666
+		padmode : Optional argument for overriding the padding mode.
  667
+
  668
+		The data must be a multiple of 8 bytes and will be decrypted
  669
+		with the already specified key. In PAD_NORMAL mode, if the
  670
+		optional padding character is supplied, then the un-encrypted
  671
+		data will have the padding characters removed from the end of
  672
+		the bytes. This pad removal only occurs on the last 8 bytes of
  673
+		the data (last data block). In PAD_PKCS5 mode, the special
  674
+		padding end markers will be removed from the data after decrypting.
  675
+		"""
  676
+		data = self._guardAgainstUnicode(data)
  677
+		if pad is not None:
  678
+			pad = self._guardAgainstUnicode(pad)
  679
+		data = self.crypt(data, des.DECRYPT)
  680
+		return self._unpadData(data, pad, padmode)
  681
+
  682
+
  683
+
  684
+#############################################################################
  685
+# 				Triple DES				    #
  686
+#############################################################################
  687
+class triple_des(_baseDes):
  688
+	"""Triple DES encryption/decrytpion class
  689
+
  690
+	This algorithm uses the DES-EDE3 (when a 24 byte key is supplied) or
  691
+	the DES-EDE2 (when a 16 byte key is supplied) encryption methods.
  692
+	Supports ECB (Electronic Code Book) and CBC (Cypher Block Chaining) modes.
  693
+
  694
+	pyDes.des(key, [mode], [IV])
  695
+
  696
+	key  -> Bytes containing the encryption key, must be either 16 or
  697
+	        24 bytes long
  698
+	mode -> Optional argument for encryption type, can be either pyDes.ECB
  699
+		(Electronic Code Book), pyDes.CBC (Cypher Block Chaining)
  700
+	IV   -> Optional Initial Value bytes, must be supplied if using CBC mode.
  701
+		Must be 8 bytes in length.
  702
+	pad  -> Optional argument, set the pad character (PAD_NORMAL) to use
  703
+		during all encrypt/decrpt operations done with this instance.
  704
+	padmode -> Optional argument, set the padding mode (PAD_NORMAL or
  705
+		PAD_PKCS5) to use during all encrypt/decrpt operations done
  706
+		with this instance.
  707
+	"""
  708
+	def __init__(self, key, mode=ECB, IV=None, pad=None, padmode=PAD_NORMAL):
  709
+		_baseDes.__init__(self, mode, IV, pad, padmode)
  710
+		self.setKey(key)
  711
+
  712
+	def setKey(self, key):
  713
+		"""Will set the crypting key for this object. Either 16 or 24 bytes long."""
  714
+		self.key_size = 24  # Use DES-EDE3 mode
  715
+		if len(key) != self.key_size:
  716
+			if len(key) == 16: # Use DES-EDE2 mode
  717
+				self.key_size = 16
  718
+			else:
  719
+				raise ValueError("Invalid triple DES key size. Key must be either 16 or 24 bytes long")
  720
+		if self.getMode() == CBC:
  721
+			if not self.getIV():
  722
+				# Use the first 8 bytes of the key
  723
+				self._iv = key[:self.block_size]
  724
+			if len(self.getIV()) != self.block_size:
  725
+				raise ValueError("Invalid IV, must be 8 bytes in length")
  726
+		self.__key1 = des(key[:8], self._mode, self._iv,
  727
+				  self._padding, self._padmode)
  728
+		self.__key2 = des(key[8:16], self._mode, self._iv,
  729
+				  self._padding, self._padmode)
  730
+		if self.key_size == 16:
  731
+			self.__key3 = self.__key1
  732
+		else:
  733
+			self.__key3 = des(key[16:], self._mode, self._iv,
  734
+					  self._padding, self._padmode)
  735
+		_baseDes.setKey(self, key)
  736
+
  737
+	# Override setter methods to work on all 3 keys.
  738
+
  739
+	def setMode(self, mode):
  740
+		"""Sets the type of crypting mode, pyDes.ECB or pyDes.CBC"""
  741
+		_baseDes.setMode(self, mode)
  742
+		for key in (self.__key1, self.__key2, self.__key3):
  743
+			key.setMode(mode)
  744
+
  745
+	def setPadding(self, pad):
  746
+		"""setPadding() -> bytes of length 1. Padding character."""
  747
+		_baseDes.setPadding(self, pad)
  748
+		for key in (self.__key1, self.__key2, self.__key3):
  749
+			key.setPadding(pad)
  750
+
  751
+	def setPadMode(self, mode):
  752
+		"""Sets the type of padding mode, pyDes.PAD_NORMAL or pyDes.PAD_PKCS5"""
  753
+		_baseDes.setPadMode(self, mode)
  754
+		for key in (self.__key1, self.__key2, self.__key3):
  755
+			key.setPadMode(mode)
  756
+
  757
+	def setIV(self, IV):
  758
+		"""Will set the Initial Value, used in conjunction with CBC mode"""
  759
+		_baseDes.setIV(self, IV)
  760
+		for key in (self.__key1, self.__key2, self.__key3):
  761
+			key.setIV(IV)
  762
+
  763
+	def encrypt(self, data, pad=None, padmode=None):
  764
+		"""encrypt(data, [pad], [padmode]) -> bytes
  765
+
  766
+		data : bytes to be encrypted
  767
+		pad  : Optional argument for encryption padding. Must only be one byte
  768
+		padmode : Optional argument for overriding the padding mode.
  769
+
  770
+		The data must be a multiple of 8 bytes and will be encrypted
  771
+		with the already specified key. Data does not have to be a
  772
+		multiple of 8 bytes if the padding character is supplied, or
  773
+		the padmode is set to PAD_PKCS5, as bytes will then added to
  774
+		ensure the be padded data is a multiple of 8 bytes.
  775
+		"""
  776
+		ENCRYPT = des.ENCRYPT
  777
+		DECRYPT = des.DECRYPT
  778
+		data = self._guardAgainstUnicode(data)
  779
+		if pad is not None:
  780
+			pad = self._guardAgainstUnicode(pad)
  781
+		# Pad the data accordingly.
  782
+		data = self._padData(data, pad, padmode)
  783
+		if self.getMode() == CBC:
  784
+			self.__key1.setIV(self.getIV())
  785
+			self.__key2.setIV(self.getIV())
  786
+			self.__key3.setIV(self.getIV())
  787
+			i = 0
  788
+			result = []
  789
+			while i < len(data):
  790
+				block = self.__key1.crypt(data[i:i+8], ENCRYPT)
  791
+				block = self.__key2.crypt(block, DECRYPT)
  792
+				block = self.__key3.crypt(block, ENCRYPT)
  793
+				self.__key1.setIV(block)
  794
+				self.__key2.setIV(block)
  795
+				self.__key3.setIV(block)
  796
+				result.append(block)
  797
+				i += 8
  798
+			if _pythonMajorVersion < 3:
  799
+				return ''.join(result)
  800
+			else:
  801
+				return bytes.fromhex('').join(result)
  802
+		else:
  803
+			data = self.__key1.crypt(data, ENCRYPT)
  804
+			data = self.__key2.crypt(data, DECRYPT)
  805
+			return self.__key3.crypt(data, ENCRYPT)
  806
+
  807
+	def decrypt(self, data, pad=None, padmode=None):
  808
+		"""decrypt(data, [pad], [padmode]) -> bytes
  809
+
  810
+		data : bytes to be encrypted
  811
+		pad  : Optional argument for decryption padding. Must only be one byte
  812
+		padmode : Optional argument for overriding the padding mode.
  813
+
  814
+		The data must be a multiple of 8 bytes and will be decrypted
  815
+		with the already specified key. In PAD_NORMAL mode, if the
  816
+		optional padding character is supplied, then the un-encrypted
  817
+		data will have the padding characters removed from the end of
  818
+		the bytes. This pad removal only occurs on the last 8 bytes of
  819
+		the data (last data block). In PAD_PKCS5 mode, the special
  820
+		padding end markers will be removed from the data after
  821
+		decrypting, no pad character is required for PAD_PKCS5.
  822
+		"""
  823
+		ENCRYPT = des.ENCRYPT
  824
+		DECRYPT = des.DECRYPT
  825
+		data = self._guardAgainstUnicode(data)
  826
+		if pad is not None:
  827
+			pad = self._guardAgainstUnicode(pad)
  828
+		if self.getMode() == CBC:
  829
+			self.__key1.setIV(self.getIV())
  830
+			self.__key2.setIV(self.getIV())
  831
+			self.__key3.setIV(self.getIV())
  832
+			i = 0
  833
+			result = []
  834
+			while i < len(data):
  835
+				iv = data[i:i+8]
  836
+				block = self.__key3.crypt(iv,    DECRYPT)
  837
+				block = self.__key2.crypt(block, ENCRYPT)
  838
+				block = self.__key1.crypt(block, DECRYPT)
  839
+				self.__key1.setIV(iv)
  840
+				self.__key2.setIV(iv)
  841
+				self.__key3.setIV(iv)
  842
+				result.append(block)
  843
+				i += 8
  844
+			if _pythonMajorVersion < 3:
  845
+				data = ''.join(result)
  846
+			else:
  847
+				data = bytes.fromhex('').join(result)
  848
+		else:
  849
+			data = self.__key3.crypt(data, DECRYPT)
  850
+			data = self.__key2.crypt(data, ENCRYPT)
  851
+			data = self.__key1.crypt(data, DECRYPT)
  852
+		return self._unpadData(data, pad, padmode)
661  vncdotool/rfb.py
... ...
@@ -0,0 +1,661 @@
  1
+"""
  2
+RFB protocol implementattion, client side.
  3
+
  4
+Override RFBClient and RFBFactory in your application.
  5
+See vncviewer.py for an example.
  6
+
  7
+Reference:
  8
+http://www.realvnc.com/docs/rfbproto.pdf
  9
+
  10
+(C) 2003 cliechti@gmx.net
  11
+
  12
+MIT License
  13
+"""
  14
+
  15
+import sys
  16
+from struct import pack, unpack
  17
+import pyDes
  18
+from twisted.python import usage, log
  19
+from twisted.internet.protocol import Factory, Protocol
  20
+from twisted.internet import protocol
  21
+from twisted.application import internet, service
  22
+
  23
+#~ from twisted.internet import reactor
  24
+
  25
+
  26
+#encoding-type
  27
+#for SetEncodings()
  28
+RAW_ENCODING =                  0
  29
+COPY_RECTANGLE_ENCODING =       1
  30
+RRE_ENCODING =                  2
  31
+CORRE_ENCODING =                4
  32
+HEXTILE_ENCODING =              5
  33
+ZLIB_ENCODING =                 6
  34
+TIGHT_ENCODING =                7
  35
+ZLIBHEX_ENCODING =              8 
  36
+ZRLE_ENCODING =                 16
  37
+#0xffffff00 to 0xffffffff tight options
  38
+
  39
+#keycodes
  40
+#for KeyEvent()
  41
+KEY_BackSpace = 0xff08
  42
+KEY_Tab =       0xff09
  43
+KEY_Return =    0xff0d
  44
+KEY_Escape =    0xff1b
  45
+KEY_Insert =    0xff63
  46
+KEY_Delete =    0xffff
  47
+KEY_Home =      0xff50
  48
+KEY_End =       0xff57
  49
+KEY_PageUp =    0xff55
  50
+KEY_PageDown =  0xff56
  51
+KEY_Left =      0xff51
  52
+KEY_Up =        0xff52
  53
+KEY_Right =     0xff53
  54
+KEY_Down =      0xff54
  55
+KEY_F1 =        0xffbe
  56
+KEY_F2 =        0xffbf
  57
+KEY_F3 =        0xffc0
  58
+KEY_F4 =        0xffc1
  59
+KEY_F5 =        0xffc2
  60
+KEY_F6 =        0xffc3
  61
+KEY_F7 =        0xffc4
  62
+KEY_F8 =        0xffc5
  63
+KEY_F9 =        0xffc6
  64
+KEY_F10 =       0xffc7
  65
+KEY_F11 =       0xffc8
  66
+KEY_F12 =       0xffc9
  67
+KEY_F13 =       0xFFCA
  68
+KEY_F14 =       0xFFCB
  69
+KEY_F15 =       0xFFCC
  70
+KEY_F16 =       0xFFCD
  71
+KEY_F17 =       0xFFCE
  72
+KEY_F18 =       0xFFCF
  73
+KEY_F19 =       0xFFD0
  74
+KEY_F20 =       0xFFD1
  75
+KEY_ShiftLeft = 0xffe1
  76
+KEY_ShiftRight = 0xffe2
  77
+KEY_ControlLeft = 0xffe3
  78
+KEY_ControlRight = 0xffe4
  79
+KEY_MetaLeft =  0xffe7
  80
+KEY_MetaRight = 0xffe8
  81
+KEY_AltLeft =   0xffe9
  82
+KEY_AltRight =  0xffea
  83
+
  84
+KEY_Scroll_Lock = 0xFF14
  85
+KEY_Sys_Req =   0xFF15
  86
+KEY_Num_Lock =  0xFF7F
  87
+KEY_Caps_Lock = 0xFFE5
  88
+KEY_Pause =     0xFF13
  89
+KEY_Super_L =   0xFFEB
  90
+KEY_Super_R =   0xFFEC
  91
+KEY_Hyper_L =   0xFFED
  92
+KEY_Hyper_R =   0xFFEE
  93
+
  94
+KEY_KP_0 =      0xFFB0
  95
+KEY_KP_1 =      0xFFB1
  96
+KEY_KP_2 =      0xFFB2
  97
+KEY_KP_3 =      0xFFB3
  98
+KEY_KP_4 =      0xFFB4
  99
+KEY_KP_5 =      0xFFB5
  100
+KEY_KP_6 =      0xFFB6
  101
+KEY_KP_7 =      0xFFB7
  102
+KEY_KP_8 =      0xFFB8
  103
+KEY_KP_9 =      0xFFB9
  104
+KEY_KP_Enter =  0xFF8D
  105
+
  106
+class RFBClient(Protocol):
  107
+    
  108
+    def __init__(self):