diff options
-rw-r--r-- | .travis.yml | 20 | ||||
-rw-r--r-- | paramiko/dsskey.py | 21 | ||||
-rw-r--r-- | paramiko/ecdsakey.py | 21 | ||||
-rw-r--r-- | paramiko/rsakey.py | 27 | ||||
-rw-r--r-- | sites/www/changelog.rst | 14 |
5 files changed, 80 insertions, 23 deletions
diff --git a/.travis.yml b/.travis.yml index 1e9af0a1..d002950f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,9 +15,27 @@ python: matrix: allow_failures: - python: "3.7-dev" + # Pull in a few specific combos of older cryptography.io as needed. + # NOTE: this should only exist in the 2.0-2.2 branches, as 2.3+ requires + # crypto 1.5+. + include: + - python: 2.7 + env: "CRYPTO=1.1" + - python: 2.7 + env: "CRYPTO=1.5" + - python: 3.6 + env: "CRYPTO=1.1" + - python: 3.6 + env: "CRYPTO=1.5" install: # Ensure modern pip/etc on Python 3.3 workers (not sure WTF, but, eh) - pip install pip==9.0.1 setuptools==36.6.0 + # Grab a specific version of Cryptography if desired. (The 'vanilla' cells + # should all end up with latest public Cryptography version.) + # Doing this before other installations ensures we don't have to do any + # downgrading/overriding. + - "if [[ $CRYPTO == '1.1' ]]; then pip install 'cryptography<1.2'; fi" + - "if [[ $CRYPTO == '1.5' ]]; then pip install 'cryptography<1.6'; fi" # Self-install for setup.py-driven deps - pip install -e . # Dev (doc/test running) requirements @@ -30,7 +48,7 @@ script: | if [[ $TRAVIS_PYTHON_VERSION == '2.6' || $TRAVIS_PYTHON_VERSION == '3.3' ]]; then flake8 - coverage run --source=paramiko -m pytest + coverage run --source=paramiko -m pytest --verbose --color=yes else inv travis.blacken flake8 diff --git a/paramiko/dsskey.py b/paramiko/dsskey.py index 489e08f0..7139daf5 100644 --- a/paramiko/dsskey.py +++ b/paramiko/dsskey.py @@ -118,9 +118,14 @@ class DSSKey(PKey): ), ), ).private_key(backend=default_backend()) - signer = key.signer(hashes.SHA1()) - signer.update(data) - r, s = decode_dss_signature(signer.finalize()) + algo = hashes.SHA1() + if hasattr(key, "sign"): # Cryptography 1.5+ + sig = key.sign(data, algo) + else: + signer = key.signer(algo) + signer.update(data) + sig = signer.finalize() + r, s = decode_dss_signature(sig) m = Message() m.add_string("ssh-dss") @@ -156,10 +161,14 @@ class DSSKey(PKey): p=self.p, q=self.q, g=self.g ), ).public_key(backend=default_backend()) - verifier = key.verifier(signature, hashes.SHA1()) - verifier.update(data) + algo = hashes.SHA1() try: - verifier.verify() + if hasattr(key, "verify"): + key.verify(signature, data, algo) + else: + verifier = key.verifier(signature, algo) + verifier.update(data) + verifier.verify() except InvalidSignature: return False else: diff --git a/paramiko/ecdsakey.py b/paramiko/ecdsakey.py index b6c00f6f..0f8c8994 100644 --- a/paramiko/ecdsakey.py +++ b/paramiko/ecdsakey.py @@ -195,9 +195,12 @@ class ECDSAKey(PKey): def sign_ssh_data(self, data): ecdsa = ec.ECDSA(self.ecdsa_curve.hash_object()) - signer = self.signing_key.signer(ecdsa) - signer.update(data) - sig = signer.finalize() + if hasattr(self.signing_key, "sign"): + sig = self.signing_key.sign(data, ecdsa) + else: + signer = self.signing_key.signer(ecdsa) + signer.update(data) + sig = signer.finalize() r, s = decode_dss_signature(sig) m = Message() @@ -212,12 +215,14 @@ class ECDSAKey(PKey): sigR, sigS = self._sigdecode(sig) signature = encode_dss_signature(sigR, sigS) - verifier = self.verifying_key.verifier( - signature, ec.ECDSA(self.ecdsa_curve.hash_object()) - ) - verifier.update(data) + algo = ec.ECDSA(self.ecdsa_curve.hash_object()) try: - verifier.verify() + if hasattr(self.verifying_key, "verify"): + self.verifying_key.verify(signature, data, algo) + else: + verifier = self.verifying_key.verifier(signature, algo) + verifier.update(data) + verifier.verify() except InvalidSignature: return False else: diff --git a/paramiko/rsakey.py b/paramiko/rsakey.py index 7e8f101c..31bb4716 100644 --- a/paramiko/rsakey.py +++ b/paramiko/rsakey.py @@ -112,11 +112,13 @@ class RSAKey(PKey): return isinstance(self.key, rsa.RSAPrivateKey) def sign_ssh_data(self, data): - signer = self.key.signer( - padding=padding.PKCS1v15(), algorithm=hashes.SHA1() - ) - signer.update(data) - sig = signer.finalize() + kwargs = dict(padding=padding.PKCS1v15(), algorithm=hashes.SHA1()) + if hasattr(self.key, "sign"): + sig = self.key.sign(data, **kwargs) + else: + signer = self.key.signer(**kwargs) + signer.update(data) + sig = signer.finalize() m = Message() m.add_string("ssh-rsa") @@ -130,14 +132,23 @@ class RSAKey(PKey): if isinstance(key, rsa.RSAPrivateKey): key = key.public_key() - verifier = key.verifier( + kwargs = dict( signature=msg.get_binary(), padding=padding.PKCS1v15(), algorithm=hashes.SHA1(), ) - verifier.update(data) try: - verifier.verify() + if hasattr(key, "verify"): + key.verify( + kwargs["signature"], + data, + kwargs["padding"], + kwargs["algorithm"], + ) + else: + verifier = key.verifier(**kwargs) + verifier.update(data) + verifier.verify() except InvalidSignature: return False else: diff --git a/sites/www/changelog.rst b/sites/www/changelog.rst index 398e0913..b50c22cc 100644 --- a/sites/www/changelog.rst +++ b/sites/www/changelog.rst @@ -2,6 +2,20 @@ Changelog ========= +- :support:`1292 backported` Backport changes from :issue:`979` (added in + Paramiko 2.3) to Paramiko 2.0-2.2, using duck-typing to preserve backwards + compatibility. This allows these older versions to use newer Cryptography + sign/verify APIs when available, without requiring them (as is the case with + Paramiko 2.3+). + + Practically speaking, this change prevents spamming of + ``CryptographyDeprecationWarning`` notices which pop up in the above scenario + (older Paramiko, newer Cryptography). + + .. note:: + This is a no-op for Paramiko 2.3+, which have required newer Cryptography + releases since they were released. + - :support:`1291 backported` Backport pytest support and application of the ``black`` code formatter (both of which previously only existed in the 2.4 branch and above) to everything 2.0 and newer. This makes back/forward |