summaryrefslogtreecommitdiff
path: root/paramiko/transport.py
diff options
context:
space:
mode:
authorAlex Gaynor <alex.gaynor@gmail.com>2014-09-15 14:05:15 -0700
committerAlex Gaynor <alex.gaynor@gmail.com>2014-09-15 14:05:15 -0700
commit56a4739923a356ff5670b4620139ca55a2f30148 (patch)
tree405e2573eaacc37615607a349773d389078c31fc /paramiko/transport.py
parentf74c7d76ec2ea9d39a4af6643761b648f81bd266 (diff)
downloadparamiko-56a4739923a356ff5670b4620139ca55a2f30148.tar.gz
Switched everything to use cryptography
Diffstat (limited to 'paramiko/transport.py')
-rw-r--r--paramiko/transport.py102
1 files changed, 78 insertions, 24 deletions
diff --git a/paramiko/transport.py b/paramiko/transport.py
index 0f747343..50c7a80a 100644
--- a/paramiko/transport.py
+++ b/paramiko/transport.py
@@ -28,6 +28,9 @@ import time
import weakref
from hashlib import md5, sha1
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes
+
import paramiko
from paramiko import util
from paramiko.auth_handler import AuthHandler
@@ -63,11 +66,6 @@ from paramiko.ssh_exception import (SSHException, BadAuthenticationType,
ChannelException, ProxyCommandFailure)
from paramiko.util import retry_on_signal, clamp_value
-from Crypto.Cipher import Blowfish, AES, DES3, ARC4
-try:
- from Crypto.Util import Counter
-except ImportError:
- from paramiko.util import Counter
# for thread cleanup
@@ -89,6 +87,9 @@ class Transport (threading.Thread):
multiplexed across a single session (and often are, in the case of port
forwardings).
"""
+ _ENCRYPT = object()
+ _DECRYPT = object()
+
_PROTO_ID = '2.0'
_CLIENT_ID = 'paramiko_%s' % paramiko.__version__
@@ -100,16 +101,57 @@ class Transport (threading.Thread):
_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},
+ 'aes128-ctr': {
+ 'class': algorithms.AES,
+ 'mode': modes.CTR,
+ 'block-size': 16,
+ 'key-size': 16
+ },
+ 'aes256-ctr': {
+ 'class': algorithms.AES,
+ 'mode': modes.CTR,
+ 'block-size': 16,
+ 'key-size': 32
+ },
+ 'blowfish-cbc': {
+ 'class': algorithms.Blowfish,
+ 'mode': modes.CBC,
+ 'block-size': 8,
+ 'key-size': 16
+ },
+ 'aes128-cbc': {
+ 'class': algorithms.AES,
+ 'mode': modes.CBC,
+ 'block-size': 16,
+ 'key-size': 16
+ },
+ 'aes256-cbc': {
+ 'class': algorithms.AES,
+ 'mode': modes.CBC,
+ 'block-size': 16,
+ 'key-size': 32
+ },
+ '3des-cbc': {
+ 'class': algorithms.TripleDES,
+ 'mode': modes.CBC,
+ 'block-size': 8,
+ 'key-size': 24
+ },
+ 'arcfour128': {
+ 'class': algorithms.ARC4,
+ 'mode': None,
+ 'block size': 8,
+ 'key-size': 16
+ },
+ 'arcfour256': {
+ 'class': algorithms.ARC4,
+ 'mode': None,
+ 'block size': 8,
+ 'key-size': 32
+ },
}
+
_mac_info = {
'hmac-sha1': {'class': sha1, 'size': 20},
'hmac-sha1-96': {'class': sha1, 'size': 12},
@@ -1501,22 +1543,34 @@ class Transport (threading.Thread):
sofar += digest
return out[:nbytes]
- def _get_cipher(self, name, key, iv):
+ def _get_cipher(self, name, key, iv, operation):
if name not in self._cipher_info:
raise SSHException('Unknown client cipher ' + name)
if name in ('arcfour128', 'arcfour256'):
# arcfour cipher
- cipher = self._cipher_info[name]['class'].new(key)
+ cipher = Cipher(
+ self._cipher_info[name]['class'](key),
+ None,
+ backend=default_backend()
+ )
+ if operation is self._ENCRYPT:
+ engine = cipher.encryptor()
+ else:
+ engine = cipher.decryptor()
# 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)
+ engine.encrypt(" " * 1536)
+ return engine
else:
- return self._cipher_info[name]['class'].new(key, self._cipher_info[name]['mode'], iv)
+ cipher = Cipher(
+ self._cipher_info[name]['class'](key),
+ self._cipher_info[name]['mode'](iv),
+ backend=default_backend(),
+ )
+ if operation is self._ENCRYPT:
+ return cipher.encryptor()
+ else:
+ return cipher.decryptor()
def _set_forward_agent_handler(self, handler):
if handler is None:
@@ -1872,7 +1926,7 @@ class Transport (threading.Thread):
else:
IV_in = self._compute_key('B', block_size)
key_in = self._compute_key('D', self._cipher_info[self.remote_cipher]['key-size'])
- engine = self._get_cipher(self.remote_cipher, key_in, IV_in)
+ engine = self._get_cipher(self.remote_cipher, key_in, IV_in, self._DECRYPT)
mac_size = self._mac_info[self.remote_mac]['size']
mac_engine = self._mac_info[self.remote_mac]['class']
# initial mac keys are done in the hash's natural size (not the potentially truncated
@@ -1899,7 +1953,7 @@ class Transport (threading.Thread):
else:
IV_out = self._compute_key('A', block_size)
key_out = self._compute_key('C', self._cipher_info[self.local_cipher]['key-size'])
- engine = self._get_cipher(self.local_cipher, key_out, IV_out)
+ engine = self._get_cipher(self.local_cipher, key_out, IV_out, self._ENCRYPT)
mac_size = self._mac_info[self.local_mac]['size']
mac_engine = self._mac_info[self.local_mac]['class']
# initial mac keys are done in the hash's natural size (not the potentially truncated