From 04164981a42e6e6ef7b57dabdf4c6dc84786d7bc9c077a659c21415174ee68dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ond=C5=99ej=20S=C3=BAkup?= Date: Tue, 4 Jun 2019 13:10:36 +0000 Subject: [PATCH] =?UTF-8?q?-=20update=20to=201.17.0=20-=20drop=20old=5Fope?= =?UTF-8?q?nssl.patch=20=20*=20Added=20support=20for=20=E2=80=9Creverse=20?= =?UTF-8?q?direction=E2=80=9D=20SSH=20connections,=20useful=20to=20support?= =?UTF-8?q?=20=20=20=20applications=20like=20NETCONF=20Call=20Home,=20desc?= =?UTF-8?q?ribed=20in=20RFC=208071.=20=20*=20Added=20support=20for=20the?= =?UTF-8?q?=20PyCA=20implementation=20of=20Chacha20-Poly1305,=20eliminatin?= =?UTF-8?q?g=20=20=20=20the=20dependency=20on=20libnacl/libsodium=20to=20p?= =?UTF-8?q?rovide=20this=20functionality,=20=20=20=20as=20long=20as=20Open?= =?UTF-8?q?SSL=201.1.1b=20or=20later=20is=20installed.=20=20*=20Restored?= =?UTF-8?q?=20libnacl=20support=20for=20Curve25519/Ed25519=20on=20systems?= =?UTF-8?q?=20which=20have=20=20=20=20an=20older=20version=20of=20OpenSSL?= =?UTF-8?q?=20that=20doesn=E2=80=99t=20have=20that=20support.=20=20=20=20T?= =?UTF-8?q?his=20fallback=20also=20applies=20to=20Chacha20-Poly1305.=20=20?= =?UTF-8?q?*=20Disabled=20the=20use=20of=20RSA=20SHA-2=20signatures=20when?= =?UTF-8?q?=20using=20the=20Pageant=20or=20Windows=2010=20=20=20=20OpenSSH?= =?UTF-8?q?=20agent=20on=20Windows,=20since=20neither=20of=20those=20suppo?= =?UTF-8?q?rt=20the=20signature=20=20=20=20flags=20options=20to=20request?= =?UTF-8?q?=20them.=20=20*=20Fixed=20a=20regression=20where=20a=20callable?= =?UTF-8?q?=20was=20no=20longer=20usable=20in=20the=20=20=20=20sftp=5Ffact?= =?UTF-8?q?ory=20argument=20of=20create=5Fserver.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OBS-URL: https://build.opensuse.org/package/show/devel:languages:python/python-asyncssh?expand=0&rev=15 --- asyncssh-1.16.1.tar.gz | 3 - asyncssh-1.17.0.tar.gz | 3 + old_openssl.patch | 379 ---------------------------------------- python-asyncssh.changes | 19 ++ python-asyncssh.spec | 6 +- 5 files changed, 24 insertions(+), 386 deletions(-) delete mode 100644 asyncssh-1.16.1.tar.gz create mode 100644 asyncssh-1.17.0.tar.gz delete mode 100644 old_openssl.patch diff --git a/asyncssh-1.16.1.tar.gz b/asyncssh-1.16.1.tar.gz deleted file mode 100644 index 393aeb6..0000000 --- a/asyncssh-1.16.1.tar.gz +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:b9e4612daed054725d658726dda7dfdd9f9deb711102e874d197c326bc0a2a62 -size 323419 diff --git a/asyncssh-1.17.0.tar.gz b/asyncssh-1.17.0.tar.gz new file mode 100644 index 0000000..e311740 --- /dev/null +++ b/asyncssh-1.17.0.tar.gz @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:ed34d4731c15453af6f0528bc8ad58db2dd3d632e69d671e36259d437d9b37e3 +size 326554 diff --git a/old_openssl.patch b/old_openssl.patch deleted file mode 100644 index 00871fd..0000000 --- a/old_openssl.patch +++ /dev/null @@ -1,379 +0,0 @@ -From 1dee113bb3e4a6888de562b0413e9abd6a0f0f04 Mon Sep 17 00:00:00 2001 -From: Ron Frederick -Date: Fri, 19 Apr 2019 16:19:43 -0700 -Subject: [PATCH] Restore libnacl support for curve25519/ed25519 as a fallback - for PyCA - -This commit restores the ability to use libnacl/libsodium for -curve25519/ed25519 when the version of OpenSSL available through -the cryptography package does not have this support. - -This commit also fixes a bug where ed25519 and ed448 were being -registered as valid host key algorithms even when support for them was -not available on the system. ---- - asyncssh/crypto/ed.py | 273 +++++++++++++++++++++++++++++++----------- - asyncssh/eddsa.py | 16 ++- - docs/api.rst | 10 +- - 3 files changed, 219 insertions(+), 80 deletions(-) - -Index: asyncssh-1.16.1/asyncssh/crypto/ed.py -=================================================================== ---- asyncssh-1.16.1.orig/asyncssh/crypto/ed.py -+++ asyncssh-1.16.1/asyncssh/crypto/ed.py -@@ -18,7 +18,10 @@ - # Contributors: - # Ron Frederick - initial implementation, API, and documentation - --"""A shim around PyCA for Edwards-curve keys and key exchange""" -+"""A shim around PyCA and libnacl for Edwards-curve keys and key exchange""" -+ -+import ctypes -+import os - - from cryptography.exceptions import InvalidSignature - from cryptography.hazmat.backends.openssl import backend -@@ -38,112 +41,240 @@ curve25519_available = backend.x25519_su - curve448_available = backend.x448_supported() - - --class _EdKey(PyCAKey): -- """Base class for shim around PyCA for Ed25519/Ed448 keys""" -+if ed25519_available: # pragma: no branch -+ class _EdKey(PyCAKey): -+ """Base class for shim around PyCA for Ed25519/Ed448 keys""" - -- def __init__(self, pyca_key, pub, priv=None): -- super().__init__(pyca_key) -+ def __init__(self, pyca_key, pub, priv=None): -+ super().__init__(pyca_key) - -- self._pub = pub -- self._priv = priv -+ self._pub = pub -+ self._priv = priv - -- @property -- def public_value(self): -- """Return the public value encoded as a byte string""" -+ @property -+ def public_value(self): -+ """Return the public value encoded as a byte string""" - -- return self._pub -+ return self._pub - -- @property -- def private_value(self): -- """Return the private value encoded as a byte string""" -+ @property -+ def private_value(self): -+ """Return the private value encoded as a byte string""" - -- return self._priv -+ return self._priv - - --class EdDSAPrivateKey(_EdKey): -- """A shim around PyCA for EdDSA private keys""" -+ class EdDSAPrivateKey(_EdKey): -+ """A shim around PyCA for EdDSA private keys""" - -- _priv_classes = {b'ed25519': ed25519.Ed25519PrivateKey, -- b'ed448': ed448.Ed448PrivateKey} -+ _priv_classes = {b'ed25519': ed25519.Ed25519PrivateKey, -+ b'ed448': ed448.Ed448PrivateKey} - -- @classmethod -- def construct(cls, curve_id, priv): -- """Construct an EdDSA private key""" -+ @classmethod -+ def construct(cls, curve_id, priv): -+ """Construct an EdDSA private key""" - -- priv_cls = cls._priv_classes[curve_id] -- priv_key = priv_cls.from_private_bytes(priv) -- pub_key = priv_key.public_key() -- pub = pub_key.public_bytes(Encoding.Raw, PublicFormat.Raw) -+ priv_cls = cls._priv_classes[curve_id] -+ priv_key = priv_cls.from_private_bytes(priv) -+ pub_key = priv_key.public_key() -+ pub = pub_key.public_bytes(Encoding.Raw, PublicFormat.Raw) - -- return cls(priv_key, pub, priv) -+ return cls(priv_key, pub, priv) - -- @classmethod -- def generate(cls, curve_id): -- """Generate a new ECDSA private key""" -+ @classmethod -+ def generate(cls, curve_id): -+ """Generate a new EdDSA private key""" - -- priv_cls = cls._priv_classes[curve_id] -- priv_key = priv_cls.generate() -- priv = priv_key.private_bytes(Encoding.Raw, PrivateFormat.Raw, -- NoEncryption()) -+ priv_cls = cls._priv_classes[curve_id] -+ priv_key = priv_cls.generate() -+ priv = priv_key.private_bytes(Encoding.Raw, PrivateFormat.Raw, -+ NoEncryption()) - -- pub_key = priv_key.public_key() -- pub = pub_key.public_bytes(Encoding.Raw, PublicFormat.Raw) -+ pub_key = priv_key.public_key() -+ pub = pub_key.public_bytes(Encoding.Raw, PublicFormat.Raw) - -- return cls(priv_key, pub, priv) -+ return cls(priv_key, pub, priv) - -- def sign(self, data): -- """Sign a block of data""" -+ def sign(self, data): -+ """Sign a block of data""" - -- return self.pyca_key.sign(data) -+ return self.pyca_key.sign(data) - - --class EdDSAPublicKey(_EdKey): -- """A shim around PyCA for EdDSA public keys""" -+ class EdDSAPublicKey(_EdKey): -+ """A shim around PyCA for EdDSA public keys""" - -- _pub_classes = {b'ed25519': ed25519.Ed25519PublicKey, -- b'ed448': ed448.Ed448PublicKey} -+ _pub_classes = {b'ed25519': ed25519.Ed25519PublicKey, -+ b'ed448': ed448.Ed448PublicKey} - -- @classmethod -- def construct(cls, curve_id, pub): -- """Construct an ECDSA public key""" -+ @classmethod -+ def construct(cls, curve_id, pub): -+ """Construct an EdDSA public key""" - -- pub_cls = cls._pub_classes[curve_id] -- pub_key = pub_cls.from_public_bytes(pub) -+ pub_cls = cls._pub_classes[curve_id] -+ pub_key = pub_cls.from_public_bytes(pub) - -- return cls(pub_key, pub) -+ return cls(pub_key, pub) - -- def verify(self, data, sig): -- """Verify the signature on a block of data""" -+ def verify(self, data, sig): -+ """Verify the signature on a block of data""" - -- try: -- self.pyca_key.verify(sig, data) -- return True -- except InvalidSignature: -- return False -+ try: -+ self.pyca_key.verify(sig, data) -+ return True -+ except InvalidSignature: -+ return False -+else: # pragma: no cover -+ class _EdKey: -+ """Base class for shim around libnacl for Ed25519 keys""" - -+ def __init__(self, pub, priv=None): -+ self._pub = pub -+ self._priv = priv - --class Curve25519DH: -- """Curve25519 Diffie Hellman implementation""" -+ @property -+ def public_value(self): -+ """Return the public value encoded as a byte string""" - -- def __init__(self): -- self._priv_key = x25519.X25519PrivateKey.generate() -+ return self._pub -+ -+ @property -+ def private_value(self): -+ """Return the private value encoded as a byte string""" -+ -+ return self._priv[:-len(self._pub)] if self._priv else None -+ -+ -+ class EdDSAPrivateKey(_EdKey): -+ """A shim around libnacl for Ed25519 private keys""" -+ -+ @classmethod -+ def construct(cls, curve_id, priv): -+ """Construct an EdDSA private key""" -+ -+ # pylint: disable=unused-argument -+ -+ return cls(*_ed25519_construct_keypair(priv)) -+ -+ @classmethod -+ def generate(cls, curve_id): -+ """Generate a new EdDSA private key""" -+ -+ # pylint: disable=unused-argument -+ -+ return cls(*_ed25519_generate_keypair()) -+ -+ def sign(self, data): -+ """Sign a block of data""" -+ -+ return _ed25519_sign(data, self._priv)[:-len(data)] -+ -+ -+ class EdDSAPublicKey(_EdKey): -+ """A shim around libnacl for Ed25519 public keys""" -+ -+ @classmethod -+ def construct(cls, curve_id, pub): -+ """Construct an EdDSA public key""" -+ -+ # pylint: disable=unused-argument -+ -+ if len(pub) != _ED25519_PUBLIC_BYTES: -+ raise ValueError('Invalid Ed25519 public key') -+ -+ return cls(pub) -+ -+ def verify(self, data, sig): -+ """Verify the signature on a block of data""" -+ -+ try: -+ return _ed25519_verify(sig + data, self._pub) == data -+ except ValueError: -+ return False -+ -+ try: -+ import libnacl -+ -+ _ED25519_PUBLIC_BYTES = libnacl.crypto_sign_ed25519_PUBLICKEYBYTES -+ -+ _ed25519_construct_keypair = libnacl.crypto_sign_seed_keypair -+ _ed25519_generate_keypair = libnacl.crypto_sign_keypair -+ _ed25519_sign = libnacl.crypto_sign -+ _ed25519_verify = libnacl.crypto_sign_open -+ -+ ed25519_available = True -+ except (ImportError, OSError, AttributeError): -+ pass -+ -+ -+if curve25519_available: # pragma: no branch -+ class Curve25519DH: -+ """Curve25519 Diffie Hellman implementation based on PyCA""" -+ -+ def __init__(self): -+ self._priv_key = x25519.X25519PrivateKey.generate() -+ -+ def get_public(self): -+ """Return the public key to send in the handshake""" -+ -+ return self._priv_key.public_key().public_bytes(Encoding.Raw, -+ PublicFormat.Raw) -+ -+ def get_shared(self, peer_public): -+ """Return the shared key from the peer's public key""" -+ -+ peer_key = x25519.X25519PublicKey.from_public_bytes(peer_public) -+ shared = self._priv_key.exchange(peer_key) -+ return int.from_bytes(shared, 'big') -+else: # pragma: no cover -+ class Curve25519DH: -+ """Curve25519 Diffie Hellman implementation based on libnacl""" -+ -+ def __init__(self): -+ self._private = os.urandom(_CURVE25519_SCALARBYTES) -+ -+ def get_public(self): -+ """Return the public key to send in the handshake""" -+ -+ public = ctypes.create_string_buffer(_CURVE25519_BYTES) -+ -+ if _curve25519_base(public, self._private) != 0: -+ # This error is never returned by libsodium -+ raise ValueError('Curve25519 failed') # pragma: no cover -+ -+ return public.raw -+ -+ def get_shared(self, peer_public): -+ """Return the shared key from the peer's public key""" -+ -+ if len(peer_public) != _CURVE25519_BYTES: -+ raise ValueError('Invalid curve25519 public key size') -+ -+ shared = ctypes.create_string_buffer(_CURVE25519_BYTES) -+ -+ if _curve25519(shared, self._private, peer_public) != 0: -+ # This error is never returned by libsodium -+ raise ValueError('Curve25519 failed') # pragma: no cover -+ -+ return int.from_bytes(shared.raw, 'big') - -- def get_public(self): -- """Return the public key to send in the handshake""" -+ try: -+ from libnacl import nacl - -- return self._priv_key.public_key().public_bytes(Encoding.Raw, -- PublicFormat.Raw) -+ _CURVE25519_BYTES = nacl.crypto_scalarmult_curve25519_bytes() -+ _CURVE25519_SCALARBYTES = \ -+ nacl.crypto_scalarmult_curve25519_scalarbytes() - -- def get_shared(self, peer_public): -- """Return the shared key from the peer's public key""" -+ _curve25519 = nacl.crypto_scalarmult_curve25519 -+ _curve25519_base = nacl.crypto_scalarmult_curve25519_base - -- peer_key = x25519.X25519PublicKey.from_public_bytes(peer_public) -- shared = self._priv_key.exchange(peer_key) -- return int.from_bytes(shared, 'big') -+ curve25519_available = True -+ except (ImportError, OSError, AttributeError): -+ pass - - - class Curve448DH: -- """Curve448 Diffie Hellman implementation""" -+ """Curve448 Diffie Hellman implementation based on PyCA""" - - def __init__(self): - self._priv_key = x448.X448PrivateKey.generate() -Index: asyncssh-1.16.1/asyncssh/eddsa.py -=================================================================== ---- asyncssh-1.16.1.orig/asyncssh/eddsa.py -+++ asyncssh-1.16.1/asyncssh/eddsa.py -@@ -22,6 +22,7 @@ - - from .asn1 import ASN1DecodeError, ObjectIdentifier, der_encode, der_decode - from .crypto import EdDSAPrivateKey, EdDSAPublicKey -+from .crypto import ed25519_available, ed448_available - from .packet import String - from .public_key import OMIT, SSHKey, SSHOpenSSHCertificateV01 - from .public_key import KeyImportError, KeyExportError -@@ -186,10 +187,15 @@ class _Ed448Key(_EdKey): - all_sig_algorithms = set(sig_algorithms) - - --for _cls in (_Ed25519Key, _Ed448Key): -- _cert_algorithm = _cls.algorithm + b'-cert-v01@openssh.com' -+if ed25519_available: # pragma: no branch -+ register_public_key_alg(b'ssh-ed25519', _Ed25519Key) - -- register_public_key_alg(_cls.algorithm, _cls) -+ register_certificate_alg(1, b'ssh-ed25519', -+ b'ssh-ed25519-cert-v01@openssh.com', -+ _Ed25519Key, SSHOpenSSHCertificateV01) - -- register_certificate_alg(1, _cls.algorithm, _cert_algorithm, -- _cls, SSHOpenSSHCertificateV01) -+if ed448_available: # pragma: no branch -+ register_public_key_alg(b'ssh-ed448', _Ed448Key) -+ -+ register_certificate_alg(1, b'ssh-ed448', b'ssh-ed448-cert-v01@openssh.com', -+ _Ed448Key, SSHOpenSSHCertificateV01) diff --git a/python-asyncssh.changes b/python-asyncssh.changes index 6ceea11..7764349 100644 --- a/python-asyncssh.changes +++ b/python-asyncssh.changes @@ -1,3 +1,22 @@ +------------------------------------------------------------------- +Tue Jun 4 13:07:40 UTC 2019 - Ondřej Súkup + +- update to 1.17.0 +- drop old_openssl.patch + * Added support for “reverse direction” SSH connections, useful to support + applications like NETCONF Call Home, described in RFC 8071. + * Added support for the PyCA implementation of Chacha20-Poly1305, eliminating + the dependency on libnacl/libsodium to provide this functionality, + as long as OpenSSL 1.1.1b or later is installed. + * Restored libnacl support for Curve25519/Ed25519 on systems which have + an older version of OpenSSL that doesn’t have that support. + This fallback also applies to Chacha20-Poly1305. + * Disabled the use of RSA SHA-2 signatures when using the Pageant or Windows 10 + OpenSSH agent on Windows, since neither of those support the signature + flags options to request them. + * Fixed a regression where a callable was no longer usable in the + sftp_factory argument of create_server. + ------------------------------------------------------------------- Tue Apr 23 08:29:31 UTC 2019 - Ondřej Súkup diff --git a/python-asyncssh.spec b/python-asyncssh.spec index 222ac21..089ff8e 100644 --- a/python-asyncssh.spec +++ b/python-asyncssh.spec @@ -19,14 +19,13 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define skip_python2 1 Name: python-asyncssh -Version: 1.16.1 +Version: 1.17.0 Release: 0 Summary: Asynchronous SSHv2 client and server library License: EPL-2.0 OR GPL-2.0-or-later Group: Development/Languages/Python Url: http://asyncssh.timeheart.net Source: https://files.pythonhosted.org/packages/source/a/asyncssh/asyncssh-%{version}.tar.gz -Patch0: old_openssl.patch BuildRequires: %{python_module bcrypt >= 3.1.3} BuildRequires: %{python_module cryptography >= 2.6.1} BuildRequires: %{python_module gssapi >= 1.2.0} @@ -37,7 +36,7 @@ BuildRequires: openssh BuildRequires: openssl BuildRequires: python-rpm-macros Requires: python-bcrypt >= 3.1.3 -Requires: python-cryptography >= 2.6.1 +Requires: python-cryptography >= 2.7.0 Requires: python-gssapi >= 1.2.0 Requires: python-libnacl >= 1.4.2 Requires: python-pyOpenSSL >= 17.0.0 @@ -53,7 +52,6 @@ asyncio framework. %prep %setup -q -n asyncssh-%{version} -%patch0 -p1 %build %python_build