summaryrefslogtreecommitdiffhomepage
path: root/paramiko/transport.py
diff options
context:
space:
mode:
Diffstat (limited to 'paramiko/transport.py')
-rw-r--r--paramiko/transport.py27
1 files changed, 24 insertions, 3 deletions
diff --git a/paramiko/transport.py b/paramiko/transport.py
index 5a871e95..63a2a27f 100644
--- a/paramiko/transport.py
+++ b/paramiko/transport.py
@@ -50,8 +50,12 @@ from paramiko.ssh_exception import SSHException, BadAuthenticationType, ChannelE
# i believe this on the standards track.
# PyCrypt compiled for Win32 can be downloaded from the HashTar homepage:
# http://nitace.bsd.uchicago.edu:8080/hashtar
-from Crypto.Cipher import Blowfish, AES, DES3
+from Crypto.Cipher import Blowfish, AES, DES3, ARC4
from Crypto.Hash import SHA, MD5
+try:
+ from Crypto.Util import Counter
+except ImportError:
+ from paramiko.util import Counter
# for thread cleanup
@@ -196,17 +200,22 @@ class Transport (threading.Thread):
_PROTO_ID = '2.0'
_CLIENT_ID = 'paramiko_1.7.4'
- _preferred_ciphers = ( 'aes128-cbc', 'blowfish-cbc', 'aes256-cbc', '3des-cbc' )
+ _preferred_ciphers = ( 'aes128-ctr', 'aes256-ctr', 'aes128-cbc', 'blowfish-cbc', 'aes256-cbc', '3des-cbc',
+ 'arcfour128', 'arcfour256' )
_preferred_macs = ( 'hmac-sha1', 'hmac-md5', 'hmac-sha1-96', 'hmac-md5-96' )
_preferred_keys = ( 'ssh-rsa', 'ssh-dss' )
_preferred_kex = ( 'diffie-hellman-group1-sha1', 'diffie-hellman-group-exchange-sha1' )
_preferred_compression = ( 'none', )
_cipher_info = {
+ 'aes128-ctr': { 'class': AES, 'mode': AES.MODE_CTR, 'block-size': 16, 'key-size': 16 },
+ 'aes256-ctr': { 'class': AES, 'mode': AES.MODE_CTR, 'block-size': 16, 'key-size': 32 },
'blowfish-cbc': { 'class': Blowfish, 'mode': Blowfish.MODE_CBC, 'block-size': 8, 'key-size': 16 },
'aes128-cbc': { 'class': AES, 'mode': AES.MODE_CBC, 'block-size': 16, 'key-size': 16 },
'aes256-cbc': { 'class': AES, 'mode': AES.MODE_CBC, 'block-size': 16, 'key-size': 32 },
'3des-cbc': { 'class': DES3, 'mode': DES3.MODE_CBC, 'block-size': 8, 'key-size': 24 },
+ 'arcfour128': { 'class': ARC4, 'mode': None, 'block-size': 8, 'key-size': 16 },
+ 'arcfour256': { 'class': ARC4, 'mode': None, 'block-size': 8, 'key-size': 32 },
}
_mac_info = {
@@ -1447,7 +1456,19 @@ class Transport (threading.Thread):
def _get_cipher(self, name, key, iv):
if name not in self._cipher_info:
raise SSHException('Unknown client cipher ' + name)
- return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv)
+ if name in ('arcfour128', 'arcfour256'):
+ # arcfour cipher
+ cipher = self._cipher_info[name]['class'].new(key)
+ # as per RFC 4345, the first 1536 bytes of keystream
+ # generated by the cipher MUST be discarded
+ cipher.encrypt(" " * 1536)
+ return cipher
+ elif name.endswith("-ctr"):
+ # CTR modes, we need a counter
+ counter = Counter.new(nbits=self._cipher_info[name]['block-size'] * 8, initial_value=util.inflate_long(iv, True))
+ return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv, counter)
+ else:
+ return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv)
def _set_x11_handler(self, handler):
# only called if a channel has turned on x11 forwarding