From 56a4739923a356ff5670b4620139ca55a2f30148 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 15 Sep 2014 14:05:15 -0700 Subject: Switched everything to use cryptography --- setup.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'setup.py') diff --git a/setup.py b/setup.py index 003a0617..91e9640c 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ connections between python scripts. All major ciphers and hash methods are supported. SFTP client and server mode are both supported too. Required packages: - pyCrypto + Cryptography To install the `in-development version `_, use @@ -41,8 +41,9 @@ try: from setuptools import setup kw = { 'install_requires': [ - 'pycrypto >= 2.1, != 2.4', + 'cryptography >= 0.5.4', 'ecdsa >= 0.11', + 'pyasn1', ], } except ImportError: -- cgit v1.2.3 From d563ba28291fa1f966353c5ef7e4c32680aa93e8 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 18 Sep 2014 18:25:40 -0700 Subject: Document that pyasn1 is required --- paramiko/ssh_gss.py | 18 ++---------------- setup.py | 2 +- sites/www/installing.rst | 10 ++++------ tox-requirements.txt | 2 +- 4 files changed, 8 insertions(+), 24 deletions(-) (limited to 'setup.py') diff --git a/paramiko/ssh_gss.py b/paramiko/ssh_gss.py index ebf2cc80..dfc9ddc8 100644 --- a/paramiko/ssh_gss.py +++ b/paramiko/ssh_gss.py @@ -39,22 +39,8 @@ import sys """ GSS_AUTH_AVAILABLE = True -try: - from pyasn1.type.univ import ObjectIdentifier - from pyasn1.codec.der import encoder, decoder -except ImportError: - GSS_AUTH_AVAILABLE = False - class ObjectIdentifier(object): - def __init__(self, *args): - raise NotImplementedError("Module pyasn1 not importable") - - class decoder(object): - def decode(self): - raise NotImplementedError("Module pyasn1 not importable") - - class encoder(object): - def encode(self): - raise NotImplementedError("Module pyasn1 not importable") +from pyasn1.type.univ import ObjectIdentifier +from pyasn1.codec.der import encoder, decoder from paramiko.common import MSG_USERAUTH_REQUEST from paramiko.ssh_exception import SSHException diff --git a/setup.py b/setup.py index 91e9640c..05933c03 100644 --- a/setup.py +++ b/setup.py @@ -43,7 +43,7 @@ try: 'install_requires': [ 'cryptography >= 0.5.4', 'ecdsa >= 0.11', - 'pyasn1', + 'pyasn1 >= 0.1.7', ], } except ImportError: diff --git a/sites/www/installing.rst b/sites/www/installing.rst index d6edbd5a..dc20590e 100644 --- a/sites/www/installing.rst +++ b/sites/www/installing.rst @@ -20,10 +20,10 @@ We currently support **Python 2.6, 2.7, 3.3+, and PyPy** (Python **3.2** should also work but has a less-strong compatibility guarantee from us.) Users on Python 2.5 or older are urged to upgrade. -Paramiko has two hard dependencies: the pure-Python ECDSA module ``ecdsa``, and -the Cryptography library. ``ecdsa`` is easily installable from wherever you -obtained Paramiko's package; Cryptography may require more work. Read on for -details. +Paramiko has three hard dependencies: the pure-Python ECDSA module ``ecdsa`` +and ASN1 module ``pyasn1``, and the Cryptography library. ``ecdsa`` is easily +installable from wherever you obtained Paramiko's package; Cryptography may +require more work. Read on for details. If you need GSS-API / SSPI support, see :ref:`the below subsection on it ` for details on additional dependencies. @@ -85,8 +85,6 @@ due to their infrequent utility & non-platform-agnostic requirements): * It hopefully goes without saying but **all platforms** need **a working installation of GSS-API itself**, e.g. Heimdal. -* **All platforms** need `pyasn1 `_ - ``0.1.7`` or better. * **Unix** needs `python-gssapi `_ ``0.6.1`` or better. diff --git a/tox-requirements.txt b/tox-requirements.txt index 3a834b7f..e66a4534 100644 --- a/tox-requirements.txt +++ b/tox-requirements.txt @@ -1,3 +1,3 @@ # Not sure why tox can't just read setup.py? cryptography >= 0.5.4 -pyasn1 +pyasn1 >= 0.1.7 -- cgit v1.2.3 From d3d816efba4798a9a81f5f0463fb2f70871644db Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Mon, 29 Sep 2014 19:44:26 -0700 Subject: Bump version numbers --- README | 2 +- setup.py | 2 +- tox-requirements.txt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'setup.py') diff --git a/README b/README index 666a0911..939fcc8c 100644 --- a/README +++ b/README @@ -36,7 +36,7 @@ Requirements - Python 2.6 or better - this includes Python 3.2 and higher as well. - - Cryptography 0.5.4 or better + - Cryptography 0.6 or better - ecdsa 0.9 or better If you have setuptools, you can build and install paramiko and all its diff --git a/setup.py b/setup.py index 05933c03..491f937d 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,7 @@ try: from setuptools import setup kw = { 'install_requires': [ - 'cryptography >= 0.5.4', + 'cryptography >= 0.6', 'ecdsa >= 0.11', 'pyasn1 >= 0.1.7', ], diff --git a/tox-requirements.txt b/tox-requirements.txt index e66a4534..0b93acf3 100644 --- a/tox-requirements.txt +++ b/tox-requirements.txt @@ -1,3 +1,3 @@ # Not sure why tox can't just read setup.py? -cryptography >= 0.5.4 +cryptography >= 0.6 pyasn1 >= 0.1.7 -- cgit v1.2.3 From 37756f3a8892dbb41dfda74dcf37e21053bf4e34 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 8 Nov 2014 12:35:43 -0300 Subject: Start porting ECDSA to cryptography. Everything except the to_der seems to work --- README | 1 - paramiko/dsskey.py | 2 -- paramiko/ecdsakey.py | 87 +++++++++++++++++++++++++++++++++++----------------- paramiko/util.py | 3 +- setup.py | 1 - 5 files changed, 60 insertions(+), 34 deletions(-) (limited to 'setup.py') diff --git a/README b/README index b6c2c957..7be87eff 100644 --- a/README +++ b/README @@ -37,7 +37,6 @@ Requirements - Python 2.6 or better - this includes Python 3.2 and higher as well. - Cryptography 0.6 or better - - ecdsa 0.9 or better - pyasn1 0.1.7 or better If you have setuptools, you can build and install paramiko and all its diff --git a/paramiko/dsskey.py b/paramiko/dsskey.py index 87293e3c..496e8527 100644 --- a/paramiko/dsskey.py +++ b/paramiko/dsskey.py @@ -20,8 +20,6 @@ DSS keys. """ -import os - from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes diff --git a/paramiko/ecdsakey.py b/paramiko/ecdsakey.py index fefd5eb5..831fa003 100644 --- a/paramiko/ecdsakey.py +++ b/paramiko/ecdsakey.py @@ -20,19 +20,28 @@ ECDSA keys """ +import base64 import binascii +import textwrap from hashlib import sha256 -from ecdsa import SigningKey, VerifyingKey, der, curves +from cryptography.exceptions import InvalidSignature +from cryptography.hazmat.backends import default_backend +from cryptography.hazmat.primitives import hashes, serialization +from cryptography.hazmat.primitives.asymmetric import ec + +from pyasn1.codec.der import decoder, encoder from paramiko.common import four_byte, one_byte +from paramiko.dsskey import _DSSSigValue from paramiko.message import Message from paramiko.pkey import PKey from paramiko.py3compat import byte_chr, u from paramiko.ssh_exception import SSHException +from paramiko.util import deflate_long, inflate_long -class ECDSAKey (PKey): +class ECDSAKey(PKey): """ Representation of an ECDSA key which can be used to sign and verify SSH2 data. @@ -65,9 +74,13 @@ class ECDSAKey (PKey): if pointinfo[0:1] != four_byte: raise SSHException('Point compression is being used: %s' % binascii.hexlify(pointinfo)) - self.verifying_key = VerifyingKey.from_string(pointinfo[1:], - curve=curves.NIST256p, - validate_point=validate_point) + curve = ec.SECP256R1() + numbers = ec.EllipticCurvePublicNumbers( + x=inflate_long(pointinfo[1:1 + curve.key_size // 8], always_positive=True), + y=inflate_long(pointinfo[1 + curve.key_size // 8:], always_positive=True), + curve=curve + ) + self.verifying_key = numbers.public_key(backend=default_backend()) self.size = 256 def asbytes(self): @@ -76,8 +89,15 @@ class ECDSAKey (PKey): m.add_string('ecdsa-sha2-nistp256') m.add_string('nistp256') - point_str = four_byte + key.to_string() + numbers = key.public_numbers() + + x_bytes = deflate_long(numbers.x, add_sign_padding=False) + x_bytes = b'\x00' * (len(x_bytes) - key.curve.key_size // 8) + x_bytes + y_bytes = deflate_long(numbers.y, add_sign_padding=False) + y_bytes = b'\x00' * (len(y_bytes) - key.curve.key_size // 8) + y_bytes + + point_str = four_byte + x_bytes + y_bytes m.add_string(point_str) return m.asbytes() @@ -86,8 +106,8 @@ class ECDSAKey (PKey): def __hash__(self): h = hash(self.get_name()) - h = h * 37 + hash(self.verifying_key.pubkey.point.x()) - h = h * 37 + hash(self.verifying_key.pubkey.point.y()) + h = h * 37 + hash(self.verifying_key.public_numbers().x) + h = h * 37 + hash(self.verifying_key.public_numbers().y) return hash(h) def get_name(self): @@ -100,23 +120,34 @@ class ECDSAKey (PKey): return self.signing_key is not None def sign_ssh_data(self, data): - sig = self.signing_key.sign_deterministic( - data, sigencode=self._sigencode, hashfunc=sha256) + signer = self.signing_key.signer(ec.ECDSA(hashes.SHA256())) + signer.update(data) + sig = signer.finalize() + (r, s), _ = decoder.decode(sig) + m = Message() m.add_string('ecdsa-sha2-nistp256') - m.add_string(sig) + m.add_string(self._sigencode(r, s)) return m def verify_ssh_sig(self, data, msg): if msg.get_text() != 'ecdsa-sha2-nistp256': return False sig = msg.get_binary() - - # verify the signature by SHA'ing the data and encrypting it - # using the public key. - hash_obj = sha256(data).digest() - return self.verifying_key.verify_digest(sig, hash_obj, - sigdecode=self._sigdecode) + sigR, sigS = self._sigdecode(sig) + sig_asn1 = _DSSSigValue() + sig_asn1.setComponentByName('r', sigR) + sig_asn1.setComponentByName('s', sigS) + signature = encoder.encode(sig_asn1) + + verifier = self.verifying_key.verifier(signature, ec.ECDSA(hashes.SHA256())) + verifier.update(data) + try: + verifier.verify() + except InvalidSignature: + return False + else: + return True def write_private_key_file(self, filename, password=None): key = self.signing_key or self.verifying_key @@ -126,7 +157,7 @@ class ECDSAKey (PKey): key = self.signing_key or self.verifying_key self._write_private_key('EC', file_obj, key.to_der(), password) - def generate(curve=curves.NIST256p, progress_func=None): + def generate(curve=ec.SECP256R1(), progress_func=None): """ Generate a new private RSA key. This factory function can be used to generate a new host key or authentication key. @@ -153,23 +184,23 @@ class ECDSAKey (PKey): byte_chr(5) * 5, byte_chr(6) * 6, byte_chr(7) * 7] def _decode_key(self, data): - s, padding = der.remove_sequence(data) - if padding: - if padding not in self.ALLOWED_PADDINGS: - raise ValueError("weird padding: %s" % u(binascii.hexlify(data))) - data = data[:-len(padding)] - key = SigningKey.from_der(data) + s = """ +-----BEGIN EC PRIVATE KEY----- +%s +-----END EC PRIVATE KEY----- +""" % "\n".join(textwrap.wrap(base64.b64encode(data), 64)) + key = serialization.load_pem_private_key(s, password=None, backend=default_backend()) self.signing_key = key - self.verifying_key = key.get_verifying_key() - self.size = 256 + self.verifying_key = key.public_key() + self.size = key.curve.key_size - def _sigencode(self, r, s, order): + def _sigencode(self, r, s): msg = Message() msg.add_mpint(r) msg.add_mpint(s) return msg.asbytes() - def _sigdecode(self, sig, order): + def _sigdecode(self, sig): msg = Message(sig) r = msg.get_mpint() s = msg.get_mpint() diff --git a/paramiko/util.py b/paramiko/util.py index 25062d00..d90fd981 100644 --- a/paramiko/util.py +++ b/paramiko/util.py @@ -22,7 +22,6 @@ Useful functions used by the rest of paramiko. from __future__ import generators -import array from binascii import hexlify, unhexlify import errno import sys @@ -32,7 +31,7 @@ import threading import logging from paramiko.common import DEBUG, zero_byte, xffffffff, max_byte -from paramiko.py3compat import PY2, long, byte_ord, b, byte_chr +from paramiko.py3compat import PY2, long, byte_ord, b from paramiko.config import SSHConfig diff --git a/setup.py b/setup.py index 491f937d..e67cbd56 100644 --- a/setup.py +++ b/setup.py @@ -42,7 +42,6 @@ try: kw = { 'install_requires': [ 'cryptography >= 0.6', - 'ecdsa >= 0.11', 'pyasn1 >= 0.1.7', ], } -- cgit v1.2.3 From eb3e117d29aa2e16b6ca0ff206062d36474f8bfd Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Thu, 18 Dec 2014 11:26:09 -0800 Subject: A bunch of cleanup --- README | 2 +- paramiko/dsskey.py | 21 +++++---------------- paramiko/ecdsakey.py | 13 +++++-------- paramiko/util.py | 34 ---------------------------------- setup.py | 2 +- tox-requirements.txt | 2 +- 6 files changed, 13 insertions(+), 61 deletions(-) (limited to 'setup.py') diff --git a/README b/README index 7be87eff..7177ce80 100644 --- a/README +++ b/README @@ -36,7 +36,7 @@ Requirements - Python 2.6 or better - this includes Python 3.2 and higher as well. - - Cryptography 0.6 or better + - Cryptography 0.7 or better - pyasn1 0.1.7 or better If you have setuptools, you can build and install paramiko and all its diff --git a/paramiko/dsskey.py b/paramiko/dsskey.py index 6ea29d9c..2c90694f 100644 --- a/paramiko/dsskey.py +++ b/paramiko/dsskey.py @@ -24,9 +24,9 @@ from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.asymmetric import dsa - -from pyasn1.codec.der import encoder, decoder -from pyasn1.type import namedtype, univ +from cryptography.hazmat.primitives.asymmetric.utils import ( + decode_rfc6979_signature, encode_rfc6979_signature +) from paramiko import util from paramiko.common import zero_byte @@ -36,13 +36,6 @@ from paramiko.ber import BER, BERException from paramiko.pkey import PKey -class _DSSSigValue(univ.Sequence): - componentType = namedtype.NamedTypes( - namedtype.NamedType('r', univ.Integer()), - namedtype.NamedType('s', univ.Integer()) - ) - - class DSSKey(PKey): """ Representation of a DSS key which can be used to sign an verify SSH2 @@ -120,8 +113,7 @@ class DSSKey(PKey): ).private_key(backend=default_backend()) signer = key.signer(hashes.SHA1()) signer.update(data) - signature = signer.finalize() - (r, s), _ = decoder.decode(signature) + r, s = decode_rfc6979_signature(signer.finalize()) m = Message() m.add_string('ssh-dss') @@ -149,10 +141,7 @@ class DSSKey(PKey): sigR = util.inflate_long(sig[:20], 1) sigS = util.inflate_long(sig[20:], 1) - sig_asn1 = _DSSSigValue() - sig_asn1.setComponentByName('r', sigR) - sig_asn1.setComponentByName('s', sigS) - signature = encoder.encode(sig_asn1) + signature = encode_rfc6979_signature(sigR, sigS) key = dsa.DSAPublicNumbers( y=self.y, diff --git a/paramiko/ecdsakey.py b/paramiko/ecdsakey.py index c3d66c30..cf3f04db 100644 --- a/paramiko/ecdsakey.py +++ b/paramiko/ecdsakey.py @@ -28,11 +28,11 @@ from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec - -from pyasn1.codec.der import decoder, encoder +from cryptography.hazmat.primitives.asymmetric.utils import ( + decode_rfc6979_signature, encode_rfc6979_signature +) from paramiko.common import four_byte, one_byte -from paramiko.dsskey import _DSSSigValue from paramiko.message import Message from paramiko.pkey import PKey from paramiko.py3compat import byte_chr @@ -122,7 +122,7 @@ class ECDSAKey(PKey): signer = self.signing_key.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) sig = signer.finalize() - (r, s), _ = decoder.decode(sig) + r, s = decode_rfc6979_signature(sig) m = Message() m.add_string('ecdsa-sha2-nistp256') @@ -134,10 +134,7 @@ class ECDSAKey(PKey): return False sig = msg.get_binary() sigR, sigS = self._sigdecode(sig) - sig_asn1 = _DSSSigValue() - sig_asn1.setComponentByName('r', sigR) - sig_asn1.setComponentByName('s', sigS) - signature = encoder.encode(sig_asn1) + signature = encode_rfc6979_signature(sigR, sigS) verifier = self.verifying_key.verifier(signature, ec.ECDSA(hashes.SHA256())) verifier.update(data) diff --git a/paramiko/util.py b/paramiko/util.py index 4d89ccf6..4947a129 100644 --- a/paramiko/util.py +++ b/paramiko/util.py @@ -273,40 +273,6 @@ def retry_on_signal(function): raise -<<<<<<< HEAD -======= -class Counter (object): - """Stateful counter for CTR mode crypto""" - def __init__(self, nbits, initial_value=long(1), overflow=long(0)): - self.blocksize = nbits / 8 - self.overflow = overflow - # start with value - 1 so we don't have to store intermediate values when counting - # could the iv be 0? - if initial_value == 0: - self.value = array.array('c', max_byte * self.blocksize) - else: - x = deflate_long(initial_value - 1, add_sign_padding=False) - self.value = array.array('c', zero_byte * (self.blocksize - len(x)) + x) - - def __call__(self): - """Increament the counter and return the new value""" - i = self.blocksize - 1 - while i > -1: - c = self.value[i] = byte_chr((byte_ord(self.value[i]) + 1) % 256) - if c != zero_byte: - return self.value.tostring() - i -= 1 - # counter reset - x = deflate_long(self.overflow, add_sign_padding=False) - self.value = array.array('c', zero_byte * (self.blocksize - len(x)) + x) - return self.value.tostring() - - @classmethod - def new(cls, nbits, initial_value=long(1), overflow=long(0)): - return cls(nbits, initial_value=initial_value, overflow=overflow) - - ->>>>>>> master def constant_time_bytes_eq(a, b): if len(a) != len(b): return False diff --git a/setup.py b/setup.py index e67cbd56..e10a6390 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,7 @@ try: from setuptools import setup kw = { 'install_requires': [ - 'cryptography >= 0.6', + 'cryptography >= 0.7', 'pyasn1 >= 0.1.7', ], } diff --git a/tox-requirements.txt b/tox-requirements.txt index 0b93acf3..23ed06d8 100644 --- a/tox-requirements.txt +++ b/tox-requirements.txt @@ -1,3 +1,3 @@ # Not sure why tox can't just read setup.py? -cryptography >= 0.6 +cryptography >= 0.7 pyasn1 >= 0.1.7 -- cgit v1.2.3 From 5130ad1f755ce0939ad51d88720a9b90fd8b3c00 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sun, 15 Mar 2015 13:10:35 -0400 Subject: Update for cryptography 0.8 and general cleanups --- README | 2 +- paramiko/dsskey.py | 4 +-- paramiko/ecdsakey.py | 70 ++++-------------------------------------------- setup.py | 2 +- sites/www/installing.rst | 6 ++--- tox-requirements.txt | 2 +- 6 files changed, 12 insertions(+), 74 deletions(-) (limited to 'setup.py') diff --git a/README b/README index 7e848aca..36d7055f 100644 --- a/README +++ b/README @@ -36,7 +36,7 @@ Requirements - Python 2.6 or better - this includes Python 3.2 and higher as well. - - Cryptography 0.7 or better + - Cryptography 0.8 or better - pyasn1 0.1.7 or better If you have setuptools, you can build and install paramiko and all its diff --git a/paramiko/dsskey.py b/paramiko/dsskey.py index 2c90694f..8e0c2ba9 100644 --- a/paramiko/dsskey.py +++ b/paramiko/dsskey.py @@ -118,8 +118,8 @@ class DSSKey(PKey): m = Message() m.add_string('ssh-dss') # apparently, in rare cases, r or s may be shorter than 20 bytes! - rstr = util.deflate_long(int(r), 0) - sstr = util.deflate_long(int(s), 0) + rstr = util.deflate_long(r, 0) + sstr = util.deflate_long(s, 0) if len(rstr) < 20: rstr = zero_byte * (20 - len(rstr)) + rstr if len(sstr) < 20: diff --git a/paramiko/ecdsakey.py b/paramiko/ecdsakey.py index bc76b639..2f5c2c31 100644 --- a/paramiko/ecdsakey.py +++ b/paramiko/ecdsakey.py @@ -32,9 +32,6 @@ from cryptography.hazmat.primitives.asymmetric.utils import ( decode_rfc6979_signature, encode_rfc6979_signature ) -from pyasn1.codec.der import encoder -from pyasn1.type import namedtype, namedval, tag, univ - from paramiko.common import four_byte, one_byte, zero_byte from paramiko.message import Message from paramiko.pkey import PKey @@ -43,40 +40,6 @@ from paramiko.ssh_exception import SSHException from paramiko.util import deflate_long, inflate_long -# RFC 5480, section 2.1.1 -class _ECParameters(univ.Choice): - # TODO: There are a few more options for this choice I think, the RFC says - # not to use them though... - componentType = namedtype.NamedTypes( - namedtype.NamedType("namedCurve", univ.ObjectIdentifier()), - ) - - -# RFC 5915, Appendix A -class _ECPrivateKey(univ.Sequence): - componentType = namedtype.NamedTypes( - namedtype.NamedType( - "version", - univ.Integer( - namedValues=namedval.NamedValues( - ("ecPrivkeyVer1", 1), - ) - ), - ), - namedtype.NamedType("privateKey", univ.OctetString()), - namedtype.OptionalNamedType("parameters", _ECParameters().subtype( - implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0), - )), - namedtype.OptionalNamedType("publicKey", univ.BitString().subtype( - implicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 1), - )), - ) - - -_CURVE_TO_OID = { - ec.SECP256R1: univ.ObjectIdentifier("1.2.840.10045.3.1.7") -} - class ECDSAKey(PKey): """ Representation of an ECDSA key which can be used to sign and verify SSH2 @@ -216,40 +179,17 @@ class ECDSAKey(PKey): byte_chr(5) * 5, byte_chr(6) * 6, byte_chr(7) * 7] def _decode_key(self, data): - s = """ ------BEGIN EC PRIVATE KEY----- -%s ------END EC PRIVATE KEY----- -""" % "\n".join(textwrap.wrap(base64.b64encode(data).decode(), 64)) - key = serialization.load_pem_private_key(s.encode(), password=None, backend=default_backend()) + key = serialization.load_der_private_key(data, password=None, backend=default_backend()) self.signing_key = key self.verifying_key = key.public_key() self.size = key.curve.key_size def _to_der(self, key): - private_numbers = key.private_numbers() - public_numbers = private_numbers.public_numbers - - private_key = deflate_long( - private_numbers.private_value, add_sign_padding=False + return key.private_bytes( + serialization.Encoding.DER, + serialization.Format.TraditionalOpenSSL, + serialization.NoEncryption(), ) - x_str = deflate_long(public_numbers.x, add_sign_padding=False) - y_str = deflate_long(public_numbers.y, add_sign_padding=False) - - key_length = key.curve.key_size // 8 - if len(x_str) < key_length: - x_str = zero_byte * (key_length - len(x_str)) + x_str - if len(y_str) < key_length: - y_str = zero_byte * (key_length - len(y_str)) + y_str - public_key = b"\x04" + x_str + y_str - - asn1_key = _ECPrivateKey() - asn1_key.setComponentByName("version", 1) - asn1_key.setComponentByName("privateKey", private_key) - asn1_key.setComponentByName("parameters") - asn1_key.getComponentByName("parameters").setComponentByName("namedCurve", _CURVE_TO_OID[type(key.curve)]) - asn1_key.setComponentByName("publicKey", "'%s'H" % binascii.hexlify(public_key).decode()) - return encoder.encode(asn1_key) def _sigencode(self, r, s): msg = Message() diff --git a/setup.py b/setup.py index e10a6390..a4977c15 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,7 @@ try: from setuptools import setup kw = { 'install_requires': [ - 'cryptography >= 0.7', + 'cryptography >= 0.8', 'pyasn1 >= 0.1.7', ], } diff --git a/sites/www/installing.rst b/sites/www/installing.rst index dc20590e..57b639f0 100644 --- a/sites/www/installing.rst +++ b/sites/www/installing.rst @@ -20,10 +20,8 @@ We currently support **Python 2.6, 2.7, 3.3+, and PyPy** (Python **3.2** should also work but has a less-strong compatibility guarantee from us.) Users on Python 2.5 or older are urged to upgrade. -Paramiko has three hard dependencies: the pure-Python ECDSA module ``ecdsa`` -and ASN1 module ``pyasn1``, and the Cryptography library. ``ecdsa`` is easily -installable from wherever you obtained Paramiko's package; Cryptography may -require more work. Read on for details. +Paramiko has two hard dependencies: the pure-Python ASN1 module ``pyasn1``, and +the Cryptography library. Read on for details on installing ``cryptography``. If you need GSS-API / SSPI support, see :ref:`the below subsection on it ` for details on additional dependencies. diff --git a/tox-requirements.txt b/tox-requirements.txt index 23ed06d8..47ddd792 100644 --- a/tox-requirements.txt +++ b/tox-requirements.txt @@ -1,3 +1,3 @@ # Not sure why tox can't just read setup.py? -cryptography >= 0.7 +cryptography >= 0.8 pyasn1 >= 0.1.7 -- cgit v1.2.3 From 583d6eaedfe2b004777b100ab8a8185bb9bec073 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Mon, 2 Nov 2015 17:32:00 -0800 Subject: We ought to work on python 3.4/3.5... --- .travis.yml | 2 ++ setup.py | 2 ++ 2 files changed, 4 insertions(+) (limited to 'setup.py') diff --git a/.travis.yml b/.travis.yml index dc5bd561..f841a71e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,8 @@ python: - "2.6" - "2.7" - "3.3" + - "3.4" + - "3.5" install: # Self-install for setup.py-driven deps - pip install -e . diff --git a/setup.py b/setup.py index 235fd0e3..9e08323d 100644 --- a/setup.py +++ b/setup.py @@ -86,6 +86,8 @@ setup( 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', ], **kw ) -- cgit v1.2.3 From 9855de91b881e66f13440a7b50225c52670e9e22 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Sat, 27 Feb 2016 17:20:42 -0800 Subject: Remove whitespace in install_requires to avoid potential setuptools bugs Fixes #697 --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'setup.py') diff --git a/setup.py b/setup.py index 9e08323d..9fa13d15 100644 --- a/setup.py +++ b/setup.py @@ -41,7 +41,7 @@ try: from setuptools import setup kw = { 'install_requires': [ - 'pycrypto >= 2.1, != 2.4', + 'pycrypto>=2.1,!=2.4', 'ecdsa', ], } -- cgit v1.2.3 From ecc04e50909054c388904673f3cd6b41fe3940e6 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 27 Feb 2016 21:02:33 -0500 Subject: removed the whitespace as was done on master --- setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'setup.py') diff --git a/setup.py b/setup.py index 280305ec..4f3cab9d 100644 --- a/setup.py +++ b/setup.py @@ -41,8 +41,8 @@ try: from setuptools import setup kw = { 'install_requires': [ - 'cryptography >= 0.8', - 'pyasn1 >= 0.1.7', + 'cryptography>=0.8', + 'pyasn1>=0.1.7', ], } except ImportError: -- cgit v1.2.3 From 76a14eddc6796c264d45d8069c8f02345a855624 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Sat, 23 Apr 2016 13:53:07 -0400 Subject: Simplify setup.py by always relying on setuptools It is installed everywhere now, there is no practical way to use python without it. --- setup.py | 24 +++++++----------------- 1 file changed, 7 insertions(+), 17 deletions(-) (limited to 'setup.py') diff --git a/setup.py b/setup.py index f9c4b4fe..ad957329 100644 --- a/setup.py +++ b/setup.py @@ -31,23 +31,10 @@ To install the `in-development version `pip install paramiko==dev`. ''' -# if someday we want to *require* setuptools, uncomment this: -# (it will cause setuptools to be automatically downloaded) -#import ez_setup -#ez_setup.use_setuptools() - import sys -try: - from setuptools import setup - kw = { - 'install_requires': [ - 'pycrypto>=2.1,!=2.4', - 'ecdsa>=0.11', - ], - } -except ImportError: - from distutils.core import setup - kw = {} + +from setuptools import setup + if sys.platform == 'darwin': import setup_helper @@ -89,5 +76,8 @@ setup( 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: 3.5', ], - **kw + install_requires=[ + 'pycrypto>=2.1,!=2.4', + 'ecdsa>=0.11', + ], ) -- cgit v1.2.3 From 1e7849ba910365e6008fd276b271e90a718fd618 Mon Sep 17 00:00:00 2001 From: Alex Gaynor Date: Wed, 27 Apr 2016 20:43:14 -0400 Subject: Use a more recent cryptography and call a function --- paramiko/dsskey.py | 6 +++--- paramiko/ecdsakey.py | 25 ++++++++++--------------- setup.py | 2 +- tox-requirements.txt | 2 +- 4 files changed, 15 insertions(+), 20 deletions(-) (limited to 'setup.py') diff --git a/paramiko/dsskey.py b/paramiko/dsskey.py index 7e14422c..4644e9a6 100644 --- a/paramiko/dsskey.py +++ b/paramiko/dsskey.py @@ -25,7 +25,7 @@ from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import dsa from cryptography.hazmat.primitives.asymmetric.utils import ( - decode_rfc6979_signature, encode_rfc6979_signature + decode_dss_signature, encode_dss_signature ) from paramiko import util @@ -113,7 +113,7 @@ class DSSKey(PKey): ).private_key(backend=default_backend()) signer = key.signer(hashes.SHA1()) signer.update(data) - r, s = decode_rfc6979_signature(signer.finalize()) + r, s = decode_dss_signature(signer.finalize()) m = Message() m.add_string('ssh-dss') @@ -141,7 +141,7 @@ class DSSKey(PKey): sigR = util.inflate_long(sig[:20], 1) sigS = util.inflate_long(sig[20:], 1) - signature = encode_rfc6979_signature(sigR, sigS) + signature = encode_dss_signature(sigR, sigS) key = dsa.DSAPublicNumbers( y=self.y, diff --git a/paramiko/ecdsakey.py b/paramiko/ecdsakey.py index c69bef73..9200dd8b 100644 --- a/paramiko/ecdsakey.py +++ b/paramiko/ecdsakey.py @@ -20,21 +20,19 @@ ECDSA keys """ -import binascii - from cryptography.exceptions import InvalidSignature from cryptography.hazmat.backends import default_backend from cryptography.hazmat.primitives import hashes, serialization from cryptography.hazmat.primitives.asymmetric import ec from cryptography.hazmat.primitives.asymmetric.utils import ( - decode_rfc6979_signature, encode_rfc6979_signature + decode_dss_signature, encode_dss_signature ) from paramiko.common import four_byte from paramiko.message import Message from paramiko.pkey import PKey from paramiko.ssh_exception import SSHException -from paramiko.util import deflate_long, inflate_long +from paramiko.util import deflate_long class ECDSAKey(PKey): @@ -67,15 +65,12 @@ class ECDSAKey(PKey): raise SSHException("Can't handle curve of type %s" % curvename) pointinfo = msg.get_binary() - if pointinfo[0:1] != four_byte: - raise SSHException('Point compression is being used: %s' % - binascii.hexlify(pointinfo)) - curve = ec.SECP256R1() - numbers = ec.EllipticCurvePublicNumbers( - x=inflate_long(pointinfo[1:1 + curve.key_size // 8], always_positive=True), - y=inflate_long(pointinfo[1 + curve.key_size // 8:], always_positive=True), - curve=curve - ) + try: + numbers = ec.EllipticCurvePublicNumbers.from_encoded_point( + ec.SECP256R1(), pointinfo + ) + except ValueError: + raise SSHException("Invalid public key") self.verifying_key = numbers.public_key(backend=default_backend()) self.size = 256 @@ -119,7 +114,7 @@ class ECDSAKey(PKey): signer = self.signing_key.signer(ec.ECDSA(hashes.SHA256())) signer.update(data) sig = signer.finalize() - r, s = decode_rfc6979_signature(sig) + r, s = decode_dss_signature(sig) m = Message() m.add_string('ecdsa-sha2-nistp256') @@ -131,7 +126,7 @@ class ECDSAKey(PKey): return False sig = msg.get_binary() sigR, sigS = self._sigdecode(sig) - signature = encode_rfc6979_signature(sigR, sigS) + signature = encode_dss_signature(sigR, sigS) verifier = self.verifying_key.verifier( signature, ec.ECDSA(hashes.SHA256()) diff --git a/setup.py b/setup.py index 4f370d63..ed3bbcd6 100644 --- a/setup.py +++ b/setup.py @@ -76,7 +76,7 @@ setup( 'Programming Language :: Python :: 3.5', ], install_requires=[ - 'cryptography>=0.8', + 'cryptography>=1.1', 'pyasn1>=0.1.7', ], ) diff --git a/tox-requirements.txt b/tox-requirements.txt index 47ddd792..9645f854 100644 --- a/tox-requirements.txt +++ b/tox-requirements.txt @@ -1,3 +1,3 @@ # Not sure why tox can't just read setup.py? -cryptography >= 0.8 +cryptography >= 1.1 pyasn1 >= 0.1.7 -- cgit v1.2.3 From fed0924df3a063d816f9d939018543aa1e5e1df7 Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Sun, 8 May 2016 14:18:59 -0700 Subject: Improved deps pinning --- dev-requirements.txt | 12 ++++++------ setup.py | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) (limited to 'setup.py') diff --git a/dev-requirements.txt b/dev-requirements.txt index feae948a..0c1fc020 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,11 +1,11 @@ # Older junk tox>=1.4,<1.5 # For newer tasks like building Sphinx docs. -invoke>=0.11.1 -invocations>=0.11.0 -sphinx>=1.1.3 -alabaster>=0.7.5 -releases>=1.1.0 -semantic_version<3 +invoke>=0.11.1,<2.0 +invocations>=0.11.0,<2.0 +sphinx>=1.1.3,<2.0 +alabaster>=0.7.5,<2.0 +releases>=1.1.0,<2.0 +semantic_version<3.0 wheel==0.24 twine==1.5 diff --git a/setup.py b/setup.py index ad957329..31d67139 100644 --- a/setup.py +++ b/setup.py @@ -77,7 +77,7 @@ setup( 'Programming Language :: Python :: 3.5', ], install_requires=[ - 'pycrypto>=2.1,!=2.4', - 'ecdsa>=0.11', + 'pycrypto>=2.1,!=2.4,<3.0', + 'ecdsa>=0.11,<2.0', ], ) -- cgit v1.2.3 From 79459e0bab5fb1542c6bfe0a72e559af21e5856c Mon Sep 17 00:00:00 2001 From: Jeff Forcier Date: Thu, 15 Sep 2016 10:57:57 -0700 Subject: ==dev is no more --- setup.py | 5 ++--- sites/www/installing.rst | 4 ---- 2 files changed, 2 insertions(+), 7 deletions(-) (limited to 'setup.py') diff --git a/setup.py b/setup.py index 31d67139..9292df22 100644 --- a/setup.py +++ b/setup.py @@ -26,9 +26,8 @@ are supported. SFTP client and server mode are both supported too. Required packages: pyCrypto -To install the `in-development version -`_, use -`pip install paramiko==dev`. +To install the development version, ``pip install -e +git+https://github.com/paramiko/paramiko/#egg=paramiko``. ''' import sys diff --git a/sites/www/installing.rst b/sites/www/installing.rst index a657c3fc..3e96a50f 100644 --- a/sites/www/installing.rst +++ b/sites/www/installing.rst @@ -12,10 +12,6 @@ via `pip `_:: $ pip install paramiko -.. note:: - Users who want the bleeding edge can install the development version via - ``pip install paramiko==dev``. - We currently support **Python 2.6, 2.7 and 3.3+** (Python **3.2** should also work but has a less-strong compatibility guarantee from us.) Users on Python 2.5 or older are urged to upgrade. -- cgit v1.2.3