New Upstream Snapshot - sshpubkeys

Ready changes

Summary

Merged new upstream version: 3.3.1+git20220130.2.5f7619c (was: 3.3.1+git20220130.1.5f7619c).

Resulting package

Built on 2022-12-19T04:06 (took 4m54s)

The resulting binary packages can be installed (if you have the apt repository enabled) by running one of:

apt install -t fresh-snapshots python3-sshpubkeys

Lintian Result

Diff

diff --git a/LICENSE.txt b/LICENSE.txt
new file mode 100644
index 0000000..89ac673
--- /dev/null
+++ b/LICENSE.txt
@@ -0,0 +1,28 @@
+Copyright (c) 2014, Olli Jarva <olli@jarva.fi>
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without 
+modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, 
+   this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice,
+   this list of conditions and the following disclaimer in the documentation
+   and/or other materials provided with the distribution.
+
+3. Neither the name of the copyright holder nor the names of its 
+   contributors may be used to endorse or promote products derived from this
+   software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
+CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGE.
diff --git a/MANIFEST.in b/MANIFEST.in
index 9561fb1..4111503 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1 +1,3 @@
 include README.rst
+include LICENSE.txt
+graft tests
diff --git a/PKG-INFO b/PKG-INFO
index 4681bb6..b438898 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,142 +1,139 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
 Name: sshpubkeys
-Version: 3.1.0
+Version: 3.3.1
 Summary: SSH public key parser
 Home-page: https://github.com/ojarva/python-sshpubkeys
 Author: Olli Jarva
 Author-email: olli@jarva.fi
 License: BSD
-Description: OpenSSH Public Key Parser for Python
-        ====================================
-        
-        .. image:: https://travis-ci.org/ojarva/python-sshpubkeys.svg?branch=master
-            :target: https://travis-ci.org/ojarva/python-sshpubkeys
-        
-        Major changes between versions 2 and 3
-        --------------------------------------
-        
-        - Dropped support for Python 2.6 and 3.3
-        - Even in loose mode, DSA keys must be 1024, 2048, or 3072 bits (earlier this was looser)
-        - The interface (API) is exactly the same
-        
-        
-        Usage
-        -----
-        
-        Native implementation for validating OpenSSH public keys.
-        
-        Currently ssh-rsa, ssh-dss (DSA), ssh-ed25519 and ecdsa keys with NIST curves are supported.
-        
-        Installation:
-        
-        ::
-        
-          pip install sshpubkeys
-        
-        or clone the `repository <https://github.com/ojarva/sshpubkeys>`_ and use
-        
-        ::
-        
-          python setup.py install
-        
-        Usage:
-        
-        ::
-        
-          import sys
-          from sshpubkeys import SSHKey
-        
-          ssh = SSHKey("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQCxO38tKAJXIs9ivPxt7AY"
-                "dfybgtAR1ow3Qkb9GPQ6wkFHQqcFDe6faKCxH6iDRteo4D8L8B"
-                "xwzN42uZSB0nfmjkIxFTcEU3mFSXEbWByg78aoddMrAAjatyrh"
-                "H1pON6P0= ojarva@ojar-laptop", strict=True)
-          try:
-              ssh.parse()
-          except InvalidKeyError as err:
-              print("Invalid key:", err)
-              sys.exit(1)
-          except NotImplementedError as err:
-              print("Invalid key type:", err)
-              sys.exit(1)
-        
-          print(ssh.bits)  # 768
-          print(ssh.hash_md5())  # 56:84:1e:90:08:3b:60:c7:29:70:5f:5e:25:a6:3b:86
-          print(ssh.hash_sha256())  # SHA256:xk3IEJIdIoR9MmSRXTP98rjDdZocmXJje/28ohMQEwM
-          print(ssh.hash_sha512())  # SHA512:1C3lNBhjpDVQe39hnyy+xvlZYU3IPwzqK1rVneGavy6O3/ebjEQSFvmeWoyMTplIanmUK1hmr9nA8Skmj516HA
-          print(ssh.comment)  # ojar@ojar-laptop
-          print(ssh.options_raw)  # None (string of optional options at the beginning of public key)
-          print(ssh.options)  # None (options as a dictionary, parsed and validated)
-        
-        
-        Parsing of `authorized_keys` files:
-        
-        ::
-        
-          from sshpubkeys import AuthorizedKeysFile
-        
-          key_file = AuthorizedKeysFile("""ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEGODBKRjsFB/1v3pDRGpA6xR+QpOJg9vat0brlbUNDD\n"""
-                     """#This is a comment\n\n"""
-                     """ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAF9QpvUneTvt8"""
-                     """lu0ePSuzr7iLE9ZMPu2DFTmqh7BVn89IHuQ5dfg9pArxfHZWgu9lMdlOykVx0I6OXkE35A/mFqwwApyiPmiwno"""
-                     """jmRnN//pApl6QQFINHzV/PGOSi599F1Y2tHQwcdb44CPOhkUmHtC9wKazSvw/ivbxNjcMzhhHsWGnA=="""
-                     strict=True, disallow_options=True)
-          for key in key_file.keys:
-              print(key.key_type, key.bits, key.hash_512())
-        
-        
-        Options
-        -------
-        
-        Set options in constructor as a keywords (i.e., `SSHKey(None, strict=False)`)
-        
-        - strict: defaults to True. Disallows keys OpenSSH's ssh-keygen refuses to create. For instance, this includes DSA keys where length != 1024 bits and RSA keys shorter than 1024-bit. If set to False, tries to allow all keys OpenSSH accepts, including highly insecure 1-bit DSA keys.
-        - skip_option_parsing: if set to True, options string is not parsed (ssh.options_raw is populated, but ssh.options is not).
-        - disallow_options: if set to True, options are not allowed and it will raise an
-          InvalidOptionsError.
-        
-        Exceptions
-        ----------
-        
-        - NotImplementedError if invalid ecdsa curve or unknown key type is encountered.
-        - InvalidKeyError if any other error is encountered:
-            - TooShortKeyError if key is too short (<768 bits for RSA, <1024 for DSA, <256 for ED25519)
-            - TooLongKeyError if key is too long (>16384 for RSA, >1024 for DSA, >256 for ED25519)
-            - InvalidTypeError if key type ("ssh-rsa" in above example) does not match to what is included in base64 encoded data.
-            - MalformedDataError if decoding and extracting the data fails.
-            - InvalidOptionsError if options string is invalid.
-                - InvalidOptionNameError if option name contains invalid characters.
-                    - UnknownOptionNameError if option name is not recognized.
-                - MissingMandatoryOptionValueError if option needs to have parameter, but it is absent.
-        
-        Tests
-        -----
-        
-        See "`tests/ <https://github.com/ojarva/sshpubkeys/tree/master/tests>`_" folder for unit tests. Use
-        
-        ::
-        
-          python setup.py test
-        
-        or
-        
-        ::
-        
-          python3 setup.py test
-        
-        to run test suite. If you have keys that are not parsed properly, or malformed keys that raise incorrect exception, please send your *public key* to olli@jarva.fi, and I'll include it. Alternatively, `create a new issue <https://github.com/ojarva/sshpubkeys/issues/new>`_ or make `a pull request <https://github.com/ojarva/sshpubkeys/compare>`_ in github.
-        
 Keywords: ssh pubkey public key openssh ssh-rsa ssh-dss ssh-ed25519
-Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
 Classifier: Intended Audience :: Developers
 Classifier: Intended Audience :: System Administrators
 Classifier: Topic :: Security
 Classifier: License :: OSI Approved :: BSD License
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: Implementation :: PyPy
+Requires-Python: >=3
+Provides-Extra: dev
+License-File: LICENSE.txt
+
+OpenSSH Public Key Parser for Python
+====================================
+
+.. image:: https://github.com/ojarva/python-sshpubkeys/workflows/Run%20python%20tests/badge.svg
+
+Major changes between versions 2 and 3
+--------------------------------------
+
+- Dropped support for Python 2.6 and 3.3
+- Even in loose mode, DSA keys must be 1024, 2048, or 3072 bits (earlier this was looser)
+- The interface (API) is exactly the same
+
+
+Usage
+-----
+
+Native implementation for validating OpenSSH public keys.
+
+Currently ssh-rsa, ssh-dss (DSA), ssh-ed25519 and ecdsa keys with NIST curves are supported.
+
+Installation:
+
+::
+
+  pip install sshpubkeys
+
+or clone the `repository <https://github.com/ojarva/sshpubkeys>`_ and use
+
+::
+
+  python setup.py install
+
+Usage:
+
+::
+
+  import sys
+  from sshpubkeys import SSHKey
+
+  ssh = SSHKey("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQCxO38tKAJXIs9ivPxt7AY"
+        "dfybgtAR1ow3Qkb9GPQ6wkFHQqcFDe6faKCxH6iDRteo4D8L8B"
+        "xwzN42uZSB0nfmjkIxFTcEU3mFSXEbWByg78aoddMrAAjatyrh"
+        "H1pON6P0= ojarva@ojar-laptop", strict=True)
+  try:
+      ssh.parse()
+  except InvalidKeyError as err:
+      print("Invalid key:", err)
+      sys.exit(1)
+  except NotImplementedError as err:
+      print("Invalid key type:", err)
+      sys.exit(1)
+
+  print(ssh.bits)  # 768
+  print(ssh.hash_md5())  # 56:84:1e:90:08:3b:60:c7:29:70:5f:5e:25:a6:3b:86
+  print(ssh.hash_sha256())  # SHA256:xk3IEJIdIoR9MmSRXTP98rjDdZocmXJje/28ohMQEwM
+  print(ssh.hash_sha512())  # SHA512:1C3lNBhjpDVQe39hnyy+xvlZYU3IPwzqK1rVneGavy6O3/ebjEQSFvmeWoyMTplIanmUK1hmr9nA8Skmj516HA
+  print(ssh.comment)  # ojar@ojar-laptop
+  print(ssh.options_raw)  # None (string of optional options at the beginning of public key)
+  print(ssh.options)  # None (options as a dictionary, parsed and validated)
+
+
+Parsing of `authorized_keys` files:
+
+::
+
+  import os
+  from sshpubkeys import AuthorizedKeysFile
+  f = open(os.environ["HOME"] + "/.ssh/authorized_keys", "r")
+  key_file = AuthorizedKeysFile(f, strict=False)
+
+  for key in key_file.keys:
+      print(key.key_type, key.bits, key.hash_sha512())
+
+
+Options
+-------
+
+Set options in constructor as a keywords (i.e., `SSHKey(None, strict=False)`)
+
+- strict: defaults to True. Disallows keys OpenSSH's ssh-keygen refuses to create. For instance, this includes DSA keys where length != 1024 bits and RSA keys shorter than 1024-bit. If set to False, tries to allow all keys OpenSSH accepts, including highly insecure 1-bit DSA keys.
+- skip_option_parsing: if set to True, options string is not parsed (ssh.options_raw is populated, but ssh.options is not).
+- disallow_options: if set to True, options are not allowed and it will raise an
+  InvalidOptionsError.
+
+Exceptions
+----------
+
+- NotImplementedError if invalid ecdsa curve or unknown key type is encountered.
+- InvalidKeyError if any other error is encountered:
+    - TooShortKeyError if key is too short (<768 bits for RSA, <1024 for DSA, <256 for ED25519)
+    - TooLongKeyError if key is too long (>16384 for RSA, >1024 for DSA, >256 for ED25519)
+    - InvalidTypeError if key type ("ssh-rsa" in above example) does not match to what is included in base64 encoded data.
+    - MalformedDataError if decoding and extracting the data fails.
+    - InvalidOptionsError if options string is invalid.
+        - InvalidOptionNameError if option name contains invalid characters.
+            - UnknownOptionNameError if option name is not recognized.
+        - MissingMandatoryOptionValueError if option needs to have parameter, but it is absent.
+
+Tests
+-----
+
+See "`tests/ <https://github.com/ojarva/sshpubkeys/tree/master/tests>`_" folder for unit tests. Use
+
+::
+
+  python setup.py test
+
+or
+
+::
+
+  python3 setup.py test
+
+to run test suite. If you have keys that are not parsed properly, or malformed keys that raise incorrect exception, please send your *public key* to olli@jarva.fi, and I'll include it. Alternatively, `create a new issue <https://github.com/ojarva/sshpubkeys/issues/new>`_ or make `a pull request <https://github.com/ojarva/sshpubkeys/compare>`_ in github.
diff --git a/README.rst b/README.rst
index 1a9c97e..3396691 100644
--- a/README.rst
+++ b/README.rst
@@ -1,8 +1,7 @@
 OpenSSH Public Key Parser for Python
 ====================================
 
-.. image:: https://travis-ci.org/ojarva/python-sshpubkeys.svg?branch=master
-    :target: https://travis-ci.org/ojarva/python-sshpubkeys
+.. image:: https://github.com/ojarva/python-sshpubkeys/workflows/Run%20python%20tests/badge.svg
 
 Major changes between versions 2 and 3
 --------------------------------------
@@ -64,16 +63,13 @@ Parsing of `authorized_keys` files:
 
 ::
 
+  import os
   from sshpubkeys import AuthorizedKeysFile
+  f = open(os.environ["HOME"] + "/.ssh/authorized_keys", "r")
+  key_file = AuthorizedKeysFile(f, strict=False)
 
-  key_file = AuthorizedKeysFile("""ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEGODBKRjsFB/1v3pDRGpA6xR+QpOJg9vat0brlbUNDD\n"""
-             """#This is a comment\n\n"""
-             """ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAF9QpvUneTvt8"""
-             """lu0ePSuzr7iLE9ZMPu2DFTmqh7BVn89IHuQ5dfg9pArxfHZWgu9lMdlOykVx0I6OXkE35A/mFqwwApyiPmiwno"""
-             """jmRnN//pApl6QQFINHzV/PGOSi599F1Y2tHQwcdb44CPOhkUmHtC9wKazSvw/ivbxNjcMzhhHsWGnA=="""
-             strict=True, disallow_options=True)
   for key in key_file.keys:
-      print(key.key_type, key.bits, key.hash_512())
+      print(key.key_type, key.bits, key.hash_sha512())
 
 
 Options
diff --git a/debian/changelog b/debian/changelog
index 4a1c303..e4989c2 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,10 +1,12 @@
-sshpubkeys (3.1.0-4) UNRELEASED; urgency=medium
+sshpubkeys (3.3.1+git20220130.2.5f7619c-1) UNRELEASED; urgency=medium
 
   * Bump debhelper from deprecated 9 to 13.
   * Set upstream metadata fields: Bug-Database, Bug-Submit, Repository,
     Repository-Browse.
+  * New upstream snapshot.
+  * New upstream snapshot.
 
- -- Debian Janitor <janitor@jelmer.uk>  Thu, 15 Sep 2022 11:32:41 -0000
+ -- Debian Janitor <janitor@jelmer.uk>  Mon, 19 Dec 2022 04:02:07 -0000
 
 sshpubkeys (3.1.0-3) unstable; urgency=medium
 
diff --git a/setup.cfg b/setup.cfg
index 6f08d0e..adf5ed7 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -4,5 +4,4 @@ universal = 1
 [egg_info]
 tag_build = 
 tag_date = 0
-tag_svn_revision = 0
 
diff --git a/setup.py b/setup.py
index 7f026b7..b899d48 100644
--- a/setup.py
+++ b/setup.py
@@ -9,37 +9,33 @@ with codecs_open(path.join(here, 'README.rst'), encoding='utf-8') as f:
 
 setup(
     name='sshpubkeys',
-    version='3.1.0',
+    version='3.3.1',
     description='SSH public key parser',
     long_description=long_description,
     url='https://github.com/ojarva/python-sshpubkeys',
     author='Olli Jarva',
     author_email='olli@jarva.fi',
     license='BSD',
-
     classifiers=[
         'Development Status :: 4 - Beta',
-
         'Intended Audience :: Developers',
         'Intended Audience :: System Administrators',
         'Topic :: Security',
         'License :: OSI Approved :: BSD License',
-
-        'Programming Language :: Python :: 2.6',
-        'Programming Language :: Python :: 2.7',
         'Programming Language :: Python :: 3',
-        'Programming Language :: Python :: 3.2',
-        'Programming Language :: Python :: 3.3',
-        'Programming Language :: Python :: 3.4',
-        'Programming Language :: Python :: 3.5',
+        'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: 3.7',
+        'Programming Language :: Python :: 3.8',
+        'Programming Language :: Python :: 3.9',
+        'Programming Language :: Python :: 3.10',
         'Programming Language :: Python :: Implementation :: PyPy',
     ],
     keywords='ssh pubkey public key openssh ssh-rsa ssh-dss ssh-ed25519',
     packages=["sshpubkeys"],
     test_suite="tests",
-    install_requires=['cryptography>=2.1.4', 'ecdsa>=0.13'],
-
+    python_requires='>=3',
+    install_requires=['cryptography>=2.5'],
     extras_require={
-        'dev': ['twine', 'wheel'],
+        'dev': ['twine', 'wheel', 'yapf'],
     },
 )
diff --git a/sshpubkeys.egg-info/PKG-INFO b/sshpubkeys.egg-info/PKG-INFO
index 4681bb6..b438898 100644
--- a/sshpubkeys.egg-info/PKG-INFO
+++ b/sshpubkeys.egg-info/PKG-INFO
@@ -1,142 +1,139 @@
-Metadata-Version: 1.1
+Metadata-Version: 2.1
 Name: sshpubkeys
-Version: 3.1.0
+Version: 3.3.1
 Summary: SSH public key parser
 Home-page: https://github.com/ojarva/python-sshpubkeys
 Author: Olli Jarva
 Author-email: olli@jarva.fi
 License: BSD
-Description: OpenSSH Public Key Parser for Python
-        ====================================
-        
-        .. image:: https://travis-ci.org/ojarva/python-sshpubkeys.svg?branch=master
-            :target: https://travis-ci.org/ojarva/python-sshpubkeys
-        
-        Major changes between versions 2 and 3
-        --------------------------------------
-        
-        - Dropped support for Python 2.6 and 3.3
-        - Even in loose mode, DSA keys must be 1024, 2048, or 3072 bits (earlier this was looser)
-        - The interface (API) is exactly the same
-        
-        
-        Usage
-        -----
-        
-        Native implementation for validating OpenSSH public keys.
-        
-        Currently ssh-rsa, ssh-dss (DSA), ssh-ed25519 and ecdsa keys with NIST curves are supported.
-        
-        Installation:
-        
-        ::
-        
-          pip install sshpubkeys
-        
-        or clone the `repository <https://github.com/ojarva/sshpubkeys>`_ and use
-        
-        ::
-        
-          python setup.py install
-        
-        Usage:
-        
-        ::
-        
-          import sys
-          from sshpubkeys import SSHKey
-        
-          ssh = SSHKey("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQCxO38tKAJXIs9ivPxt7AY"
-                "dfybgtAR1ow3Qkb9GPQ6wkFHQqcFDe6faKCxH6iDRteo4D8L8B"
-                "xwzN42uZSB0nfmjkIxFTcEU3mFSXEbWByg78aoddMrAAjatyrh"
-                "H1pON6P0= ojarva@ojar-laptop", strict=True)
-          try:
-              ssh.parse()
-          except InvalidKeyError as err:
-              print("Invalid key:", err)
-              sys.exit(1)
-          except NotImplementedError as err:
-              print("Invalid key type:", err)
-              sys.exit(1)
-        
-          print(ssh.bits)  # 768
-          print(ssh.hash_md5())  # 56:84:1e:90:08:3b:60:c7:29:70:5f:5e:25:a6:3b:86
-          print(ssh.hash_sha256())  # SHA256:xk3IEJIdIoR9MmSRXTP98rjDdZocmXJje/28ohMQEwM
-          print(ssh.hash_sha512())  # SHA512:1C3lNBhjpDVQe39hnyy+xvlZYU3IPwzqK1rVneGavy6O3/ebjEQSFvmeWoyMTplIanmUK1hmr9nA8Skmj516HA
-          print(ssh.comment)  # ojar@ojar-laptop
-          print(ssh.options_raw)  # None (string of optional options at the beginning of public key)
-          print(ssh.options)  # None (options as a dictionary, parsed and validated)
-        
-        
-        Parsing of `authorized_keys` files:
-        
-        ::
-        
-          from sshpubkeys import AuthorizedKeysFile
-        
-          key_file = AuthorizedKeysFile("""ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEGODBKRjsFB/1v3pDRGpA6xR+QpOJg9vat0brlbUNDD\n"""
-                     """#This is a comment\n\n"""
-                     """ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAF9QpvUneTvt8"""
-                     """lu0ePSuzr7iLE9ZMPu2DFTmqh7BVn89IHuQ5dfg9pArxfHZWgu9lMdlOykVx0I6OXkE35A/mFqwwApyiPmiwno"""
-                     """jmRnN//pApl6QQFINHzV/PGOSi599F1Y2tHQwcdb44CPOhkUmHtC9wKazSvw/ivbxNjcMzhhHsWGnA=="""
-                     strict=True, disallow_options=True)
-          for key in key_file.keys:
-              print(key.key_type, key.bits, key.hash_512())
-        
-        
-        Options
-        -------
-        
-        Set options in constructor as a keywords (i.e., `SSHKey(None, strict=False)`)
-        
-        - strict: defaults to True. Disallows keys OpenSSH's ssh-keygen refuses to create. For instance, this includes DSA keys where length != 1024 bits and RSA keys shorter than 1024-bit. If set to False, tries to allow all keys OpenSSH accepts, including highly insecure 1-bit DSA keys.
-        - skip_option_parsing: if set to True, options string is not parsed (ssh.options_raw is populated, but ssh.options is not).
-        - disallow_options: if set to True, options are not allowed and it will raise an
-          InvalidOptionsError.
-        
-        Exceptions
-        ----------
-        
-        - NotImplementedError if invalid ecdsa curve or unknown key type is encountered.
-        - InvalidKeyError if any other error is encountered:
-            - TooShortKeyError if key is too short (<768 bits for RSA, <1024 for DSA, <256 for ED25519)
-            - TooLongKeyError if key is too long (>16384 for RSA, >1024 for DSA, >256 for ED25519)
-            - InvalidTypeError if key type ("ssh-rsa" in above example) does not match to what is included in base64 encoded data.
-            - MalformedDataError if decoding and extracting the data fails.
-            - InvalidOptionsError if options string is invalid.
-                - InvalidOptionNameError if option name contains invalid characters.
-                    - UnknownOptionNameError if option name is not recognized.
-                - MissingMandatoryOptionValueError if option needs to have parameter, but it is absent.
-        
-        Tests
-        -----
-        
-        See "`tests/ <https://github.com/ojarva/sshpubkeys/tree/master/tests>`_" folder for unit tests. Use
-        
-        ::
-        
-          python setup.py test
-        
-        or
-        
-        ::
-        
-          python3 setup.py test
-        
-        to run test suite. If you have keys that are not parsed properly, or malformed keys that raise incorrect exception, please send your *public key* to olli@jarva.fi, and I'll include it. Alternatively, `create a new issue <https://github.com/ojarva/sshpubkeys/issues/new>`_ or make `a pull request <https://github.com/ojarva/sshpubkeys/compare>`_ in github.
-        
 Keywords: ssh pubkey public key openssh ssh-rsa ssh-dss ssh-ed25519
-Platform: UNKNOWN
 Classifier: Development Status :: 4 - Beta
 Classifier: Intended Audience :: Developers
 Classifier: Intended Audience :: System Administrators
 Classifier: Topic :: Security
 Classifier: License :: OSI Approved :: BSD License
-Classifier: Programming Language :: Python :: 2.6
-Classifier: Programming Language :: Python :: 2.7
 Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.2
-Classifier: Programming Language :: Python :: 3.3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
 Classifier: Programming Language :: Python :: Implementation :: PyPy
+Requires-Python: >=3
+Provides-Extra: dev
+License-File: LICENSE.txt
+
+OpenSSH Public Key Parser for Python
+====================================
+
+.. image:: https://github.com/ojarva/python-sshpubkeys/workflows/Run%20python%20tests/badge.svg
+
+Major changes between versions 2 and 3
+--------------------------------------
+
+- Dropped support for Python 2.6 and 3.3
+- Even in loose mode, DSA keys must be 1024, 2048, or 3072 bits (earlier this was looser)
+- The interface (API) is exactly the same
+
+
+Usage
+-----
+
+Native implementation for validating OpenSSH public keys.
+
+Currently ssh-rsa, ssh-dss (DSA), ssh-ed25519 and ecdsa keys with NIST curves are supported.
+
+Installation:
+
+::
+
+  pip install sshpubkeys
+
+or clone the `repository <https://github.com/ojarva/sshpubkeys>`_ and use
+
+::
+
+  python setup.py install
+
+Usage:
+
+::
+
+  import sys
+  from sshpubkeys import SSHKey
+
+  ssh = SSHKey("ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQCxO38tKAJXIs9ivPxt7AY"
+        "dfybgtAR1ow3Qkb9GPQ6wkFHQqcFDe6faKCxH6iDRteo4D8L8B"
+        "xwzN42uZSB0nfmjkIxFTcEU3mFSXEbWByg78aoddMrAAjatyrh"
+        "H1pON6P0= ojarva@ojar-laptop", strict=True)
+  try:
+      ssh.parse()
+  except InvalidKeyError as err:
+      print("Invalid key:", err)
+      sys.exit(1)
+  except NotImplementedError as err:
+      print("Invalid key type:", err)
+      sys.exit(1)
+
+  print(ssh.bits)  # 768
+  print(ssh.hash_md5())  # 56:84:1e:90:08:3b:60:c7:29:70:5f:5e:25:a6:3b:86
+  print(ssh.hash_sha256())  # SHA256:xk3IEJIdIoR9MmSRXTP98rjDdZocmXJje/28ohMQEwM
+  print(ssh.hash_sha512())  # SHA512:1C3lNBhjpDVQe39hnyy+xvlZYU3IPwzqK1rVneGavy6O3/ebjEQSFvmeWoyMTplIanmUK1hmr9nA8Skmj516HA
+  print(ssh.comment)  # ojar@ojar-laptop
+  print(ssh.options_raw)  # None (string of optional options at the beginning of public key)
+  print(ssh.options)  # None (options as a dictionary, parsed and validated)
+
+
+Parsing of `authorized_keys` files:
+
+::
+
+  import os
+  from sshpubkeys import AuthorizedKeysFile
+  f = open(os.environ["HOME"] + "/.ssh/authorized_keys", "r")
+  key_file = AuthorizedKeysFile(f, strict=False)
+
+  for key in key_file.keys:
+      print(key.key_type, key.bits, key.hash_sha512())
+
+
+Options
+-------
+
+Set options in constructor as a keywords (i.e., `SSHKey(None, strict=False)`)
+
+- strict: defaults to True. Disallows keys OpenSSH's ssh-keygen refuses to create. For instance, this includes DSA keys where length != 1024 bits and RSA keys shorter than 1024-bit. If set to False, tries to allow all keys OpenSSH accepts, including highly insecure 1-bit DSA keys.
+- skip_option_parsing: if set to True, options string is not parsed (ssh.options_raw is populated, but ssh.options is not).
+- disallow_options: if set to True, options are not allowed and it will raise an
+  InvalidOptionsError.
+
+Exceptions
+----------
+
+- NotImplementedError if invalid ecdsa curve or unknown key type is encountered.
+- InvalidKeyError if any other error is encountered:
+    - TooShortKeyError if key is too short (<768 bits for RSA, <1024 for DSA, <256 for ED25519)
+    - TooLongKeyError if key is too long (>16384 for RSA, >1024 for DSA, >256 for ED25519)
+    - InvalidTypeError if key type ("ssh-rsa" in above example) does not match to what is included in base64 encoded data.
+    - MalformedDataError if decoding and extracting the data fails.
+    - InvalidOptionsError if options string is invalid.
+        - InvalidOptionNameError if option name contains invalid characters.
+            - UnknownOptionNameError if option name is not recognized.
+        - MissingMandatoryOptionValueError if option needs to have parameter, but it is absent.
+
+Tests
+-----
+
+See "`tests/ <https://github.com/ojarva/sshpubkeys/tree/master/tests>`_" folder for unit tests. Use
+
+::
+
+  python setup.py test
+
+or
+
+::
+
+  python3 setup.py test
+
+to run test suite. If you have keys that are not parsed properly, or malformed keys that raise incorrect exception, please send your *public key* to olli@jarva.fi, and I'll include it. Alternatively, `create a new issue <https://github.com/ojarva/sshpubkeys/issues/new>`_ or make `a pull request <https://github.com/ojarva/sshpubkeys/compare>`_ in github.
diff --git a/sshpubkeys.egg-info/SOURCES.txt b/sshpubkeys.egg-info/SOURCES.txt
index 7f95e88..d507dcd 100644
--- a/sshpubkeys.egg-info/SOURCES.txt
+++ b/sshpubkeys.egg-info/SOURCES.txt
@@ -1,3 +1,4 @@
+LICENSE.txt
 MANIFEST.in
 README.rst
 setup.cfg
@@ -9,4 +10,13 @@ sshpubkeys.egg-info/PKG-INFO
 sshpubkeys.egg-info/SOURCES.txt
 sshpubkeys.egg-info/dependency_links.txt
 sshpubkeys.egg-info/requires.txt
-sshpubkeys.egg-info/top_level.txt
\ No newline at end of file
+sshpubkeys.egg-info/top_level.txt
+tests/__init__.py
+tests/authorized_keys.py
+tests/invalid_authorized_keys.py
+tests/invalid_keys.py
+tests/invalid_options.py
+tests/test_dsa_keys_failing.py
+tests/valid_keys.py
+tests/valid_keys_rfc4716.py
+tests/valid_options.py
\ No newline at end of file
diff --git a/sshpubkeys.egg-info/requires.txt b/sshpubkeys.egg-info/requires.txt
index 0bde296..945f30c 100644
--- a/sshpubkeys.egg-info/requires.txt
+++ b/sshpubkeys.egg-info/requires.txt
@@ -1,6 +1,6 @@
-cryptography>=2.1.4
-ecdsa>=0.13
+cryptography>=2.5
 
 [dev]
 twine
 wheel
+yapf
diff --git a/sshpubkeys/exceptions.py b/sshpubkeys/exceptions.py
index f5b6859..e021a29 100644
--- a/sshpubkeys/exceptions.py
+++ b/sshpubkeys/exceptions.py
@@ -1,107 +1,86 @@
 # pylint:disable=line-too-long,too-many-ancestors
-
 """Exceptions for sshpubkeys."""
 
 
 class InvalidKeyException(Exception):
     """Invalid key - something is wrong with the key, and it should not be accepted, as OpenSSH will not work with it."""
-    pass
 
 
 class InvalidKeyError(InvalidKeyException):
     """Invalid key - something is wrong with the key, and it should not be accepted, as OpenSSH will not work with it."""
-    pass
 
 
 class InvalidKeyLengthException(InvalidKeyError):
     """Invalid key length - either too short or too long.
 
     See also TooShortKeyException and TooLongKeyException."""
-    pass
 
 
 class InvalidKeyLengthError(InvalidKeyError):
     """Invalid key length - either too short or too long.
 
     See also TooShortKeyException and TooLongKeyException."""
-    pass
 
 
 class TooShortKeyException(InvalidKeyLengthError):
     """Key is shorter than what the specification allow."""
-    pass
 
 
 class TooShortKeyError(TooShortKeyException):
     """Key is shorter than what the specification allows."""
-    pass
 
 
 class TooLongKeyException(InvalidKeyLengthError):
     """Key is longer than what the specification allows."""
-    pass
 
 
 class TooLongKeyError(TooLongKeyException):
     """Key is longer than what the specification allows."""
-    pass
 
 
 class InvalidTypeException(InvalidKeyError):
     """Key type is invalid or unrecognized."""
-    pass
 
 
 class InvalidTypeError(InvalidTypeException):
     """Key type is invalid or unrecognized."""
-    pass
 
 
 class MalformedDataException(InvalidKeyError):
     """The key is invalid - unable to parse the data. The data may be corrupted, truncated, or includes extra content that is not allowed."""
-    pass
 
 
 class MalformedDataError(MalformedDataException):
     """The key is invalid - unable to parse the data. The data may be corrupted, truncated, or includes extra content that is not allowed."""
-    pass
 
 
 class InvalidOptionsException(MalformedDataError):
     """Options string is invalid: it contains invalid characters, unrecognized options, or is otherwise malformed."""
-    pass
 
 
 class InvalidOptionsError(InvalidOptionsException):
     """Options string is invalid: it contains invalid characters, unrecognized options, or is otherwise malformed."""
-    pass
 
 
 class InvalidOptionNameException(InvalidOptionsError):
     """Invalid option name (contains disallowed characters, or is unrecognized.)."""
-    pass
 
 
 class InvalidOptionNameError(InvalidOptionNameException):
     """Invalid option name (contains disallowed characters, or is unrecognized.)."""
-    pass
 
 
 class UnknownOptionNameException(InvalidOptionsError):
     """Unrecognized option name."""
-    pass
 
 
 class UnknownOptionNameError(UnknownOptionNameException):
     """Unrecognized option name."""
-    pass
 
 
 class MissingMandatoryOptionValueException(InvalidOptionsError):
     """Mandatory option value is missing."""
-    pass
 
 
 class MissingMandatoryOptionValueError(MissingMandatoryOptionValueException):
     """Mandatory option value is missing."""
-    pass
diff --git a/sshpubkeys/keys.py b/sshpubkeys/keys.py
index df1a145..2e2066f 100644
--- a/sshpubkeys/keys.py
+++ b/sshpubkeys/keys.py
@@ -1,5 +1,4 @@
 # pylint:disable=line-too-long
-
 """Parser for ssh public keys. Currently supports ssh-rsa, ssh-dsa, ssh-ed25519 and ssh-dss keys.
 
 import sys
@@ -14,6 +13,18 @@ except InvalidKeyError:
     sys.exit(1)
 print(ssh_key.bits)"""
 
+from .exceptions import (
+    InvalidKeyError, InvalidKeyLengthError, InvalidOptionNameError, InvalidOptionsError, InvalidTypeError,
+    MalformedDataError, MissingMandatoryOptionValueError, TooLongKeyError, TooShortKeyError, UnknownOptionNameError
+)
+from cryptography.hazmat.backends import default_backend
+from cryptography.hazmat.primitives import hashes
+from cryptography.hazmat.primitives.asymmetric import ec
+from cryptography.hazmat.primitives.asymmetric.dsa import DSAParameterNumbers, DSAPublicNumbers
+from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers
+from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat
+from urllib.parse import urlparse
+
 import base64
 import binascii
 import hashlib
@@ -22,19 +33,55 @@ import struct
 import sys
 import warnings
 
-import ecdsa
-from cryptography.hazmat.backends import default_backend
-from cryptography.hazmat.primitives.asymmetric.dsa import DSAParameterNumbers, DSAPublicNumbers
-from cryptography.hazmat.primitives.asymmetric.rsa import RSAPublicNumbers
-
-from .exceptions import (InvalidKeyError, InvalidKeyLengthError, InvalidOptionNameError, InvalidOptionsError,
-                         InvalidTypeError, MalformedDataError, MissingMandatoryOptionValueError, TooLongKeyError,
-                         TooShortKeyError, UnknownOptionNameError)
-
 __all__ = ["AuthorizedKeysFile", "SSHKey"]
 
 
-class AuthorizedKeysFile(object):  # pylint:disable=too-few-public-methods
+class _ECVerifyingKey:
+    """ecdsa.key.VerifyingKey reimplementation
+    """
+
+    def __init__(self, pubkey, default_hashfunc):
+        self.pubkey = pubkey
+        self.default_hashfunc = default_hashfunc
+
+    @property
+    def curve(self):
+        """Curve instance"""
+        return self.pubkey.curve
+
+    def __repr__(self):
+        pub_key = self.to_string("compressed")
+        self.to_string("raw")
+        return f"VerifyingKey({pub_key!r}, {self.curve.name!r}, {self.default_hashfunc.name})"
+
+    def to_string(self, encoding="raw"):
+        """Pub key as bytes string"""
+        if encoding == "raw":
+            return self.pubkey.public_numbers().encode_point()[1:]
+        if encoding == "uncompressed":
+            return self.pubkey.public_numbers().encode_point()
+        if encoding == "compressed":
+            return self.pubkey.public_bytes(Encoding.X962, PublicFormat.CompressedPoint)
+        raise ValueError(encoding)
+
+    def to_pem(self, point_encoding="uncompressed"):
+        """Pub key as PEM"""
+        if point_encoding != "uncompressed":
+            raise ValueError(point_encoding)
+        return self.pubkey.public_bytes(Encoding.PEM, PublicFormat.SubjectPublicKeyInfo)
+
+    def to_der(self, point_encoding="uncompressed"):
+        """Pub key as ASN.1/DER"""
+        if point_encoding != "uncompressed":
+            raise ValueError(point_encoding)
+        return self.pubkey.public_bytes(Encoding.DER, PublicFormat.SubjectPublicKeyInfo)
+
+    def verify(self, signature, data):
+        """Verify signature of provided data"""
+        return self.pubkey.verify(signature, data, ec.ECDSA(self.default_hashfunc))
+
+
+class AuthorizedKeysFile:  # pylint:disable=too-few-public-methods
     """Represents a full authorized_keys file.
 
     Comments and empty lines are ignored."""
@@ -55,7 +102,7 @@ class AuthorizedKeysFile(object):  # pylint:disable=too-few-public-methods
             self.keys.append(ssh_key)
 
 
-class SSHKey(object):  # pylint:disable=too-many-instance-attributes
+class SSHKey:  # pylint:disable=too-many-instance-attributes
     """Represents a single SSH keypair.
 
     ssh_key = SSHKey(key_data, strict=True)
@@ -73,11 +120,11 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
     DSA_N_LENGTH = 160
 
     ECDSA_CURVE_DATA = {
-        b"nistp256": (ecdsa.curves.NIST256p, hashlib.sha256),
-        b"nistp192": (ecdsa.curves.NIST192p, hashlib.sha256),
-        b"nistp224": (ecdsa.curves.NIST224p, hashlib.sha256),
-        b"nistp384": (ecdsa.curves.NIST384p, hashlib.sha384),
-        b"nistp521": (ecdsa.curves.NIST521p, hashlib.sha512),
+        b"nistp256": (ec.SECP256R1(), hashes.SHA256()),
+        b"nistp192": (ec.SECP192R1(), hashes.SHA256()),
+        b"nistp224": (ec.SECP224R1(), hashes.SHA256()),
+        b"nistp384": (ec.SECP384R1(), hashes.SHA384()),
+        b"nistp521": (ec.SECP521R1(), hashes.SHA512())
     }
 
     RSA_MIN_LENGTH_STRICT = 1024
@@ -85,23 +132,26 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
     RSA_MIN_LENGTH_LOOSE = 768
     RSA_MAX_LENGTH_LOOSE = 16384
 
-    # Valid as of OpenSSH_6.9p1
+    # Valid as of OpenSSH_8.3
     # argument name, value is mandatory. Options are case-insensitive, but this list must be in lowercase.
     OPTIONS_SPEC = [
         ("agent-forwarding", False),
         ("cert-authority", False),
         ("command", True),
         ("environment", True),
+        ("expiry-time", True),
         ("from", True),
         ("no-agent-forwarding", False),
         ("no-port-forwarding", False),
         ("no-pty", False),
         ("no-user-rc", False),
         ("no-x11-forwarding", False),
+        ("permitlisten", True),
         ("permitopen", True),
         ("port-forwarding", False),
         ("principals", True),
         ("pty", False),
+        ("no-touch-required", False),
         ("restrict", False),
         ("tunnel", True),
         ("user-rc", False),
@@ -134,13 +184,18 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
                 pass
 
     def __str__(self):
-        return "Key type: %s, bits: %s, options: %s" % (self.key_type, self.bits, self.options)
+        return f"Key type: {self.key_type.decode()}, bits: {self.bits}, options: {self.options}"
 
     def reset(self):
         """Reset all data fields."""
         for field in self.FIELDS:
             setattr(self, field, None)
 
+    @property
+    def key(self):
+        """Base64 encoded key"""
+        return base64.b64encode(self._decoded_key)
+
     def hash(self):
         """Calculate md5 fingerprint.
 
@@ -172,15 +227,17 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
         # Unpack length of data field
         try:
             requested_data_length = struct.unpack('>I', data[current_position:current_position + self.INT_LEN])[0]
-        except struct.error:
-            raise MalformedDataError("Unable to unpack %s bytes from the data" % self.INT_LEN)
+        except struct.error as ex:
+            raise MalformedDataError(f"Unable to unpack {self.INT_LEN} bytes from the data") from ex
 
         # Move pointer to the beginning of the data field
         current_position += self.INT_LEN
         remaining_data_length = len(data[current_position:])
 
         if remaining_data_length < requested_data_length:
-            raise MalformedDataError("Requested %s bytes, but only %s bytes available." % (requested_data_length, remaining_data_length))
+            raise MalformedDataError(
+                f"Requested {requested_data_length} bytes, but only {remaining_data_length} bytes available."
+            )
 
         next_data = data[current_position:current_position + requested_data_length]
         # Move pointer to the end of the data field
@@ -204,7 +261,7 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
     def _split_key(self, data):
         options_raw = None
         # Terribly inefficient way to remove options, but hey, it works.
-        if not data.startswith("ssh-") and not data.startswith("ecdsa-"):
+        if not data.startswith("ssh-") and not data.startswith("ecdsa-") and not data.startswith("sk-"):
             quote_open = False
             for i, character in enumerate(data):
                 if character == '"':  # only double quotes are allowed, no need to care about single quotes
@@ -240,8 +297,8 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
         """Decode base64 coded part of the key."""
         try:
             decoded_key = base64.b64decode(pubkey_content.encode("ascii"))
-        except (TypeError, binascii.Error):
-            raise MalformedDataError("Unable to decode the key")
+        except (TypeError, binascii.Error) as ex:
+            raise MalformedDataError("Unable to decode the key") from ex
         return decoded_key
 
     @classmethod
@@ -262,15 +319,15 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
                 opt_name = opt
                 opt_value = True
             if " " in opt_name or not self.OPTION_NAME_RE.match(opt_name):
-                raise InvalidOptionNameError("%s is not valid option name." % opt_name)
+                raise InvalidOptionNameError(f"{opt_name} is not a valid option name.")
             if self.strict_mode:
                 for valid_opt_name, value_required in self.OPTIONS_SPEC:
                     if opt_name.lower() == valid_opt_name:
                         if value_required and opt_value is True:
-                            raise MissingMandatoryOptionValueError("%s is missing mandatory value." % opt_name)
+                            raise MissingMandatoryOptionValueError(f"{opt_name} is missing a mandatory value.")
                         break
                 else:
-                    raise UnknownOptionNameError("%s is unrecognized option name." % opt_name)
+                    raise UnknownOptionNameError(f"{opt_name} is an unrecognized option name.")
             if opt_name not in parsed_options:
                 parsed_options[opt_name] = []
             parsed_options[opt_name].append(opt_value)
@@ -312,9 +369,13 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
             min_length = self.RSA_MIN_LENGTH_LOOSE
             max_length = self.RSA_MAX_LENGTH_LOOSE
         if self.bits < min_length:
-            raise TooShortKeyError("%s key data can not be shorter than %s bits (was %s)" % (self.key_type, min_length, self.bits))
+            raise TooShortKeyError(
+                f"{self.key_type.decode()} key data can not be shorter than {min_length} bits (was {self.bits})"
+            )
         if self.bits > max_length:
-            raise TooLongKeyError("%s key data can not be longer than %s bits (was %s)" % (self.key_type, max_length, self.bits))
+            raise TooLongKeyError(
+                f"{self.key_type.decode()} key data can not be longer than {max_length} bits (was {self.bits})"
+            )
         return current_position
 
     def _process_ssh_dss(self, data):
@@ -328,7 +389,7 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
         q_bits = self._bits_in_number(data_fields["q"])
         p_bits = self._bits_in_number(data_fields["p"])
         if q_bits != self.DSA_N_LENGTH:
-            raise InvalidKeyError("Incorrect DSA key parameters: bits(p)=%s, q=%s" % (self.bits, q_bits))
+            raise InvalidKeyError(f"Incorrect DSA key parameters: bits(p)={self.bits}, q={q_bits}")
         if self.strict_mode:
             min_length = self.DSA_MIN_LENGTH_STRICT
             max_length = self.DSA_MAX_LENGTH_STRICT
@@ -336,9 +397,11 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
             min_length = self.DSA_MIN_LENGTH_LOOSE
             max_length = self.DSA_MAX_LENGTH_LOOSE
         if p_bits < min_length:
-            raise TooShortKeyError("%s key can not be shorter than %s bits (was %s)" % (self.key_type, min_length, p_bits))
+            raise TooShortKeyError(f"{self.key_type.decode()} key can not be shorter than {min_length} bits (was {p_bits})")
         if p_bits > max_length:
-            raise TooLongKeyError("%s key data can not be longer than %s bits (was %s)" % (self.key_type, max_length, p_bits))
+            raise TooLongKeyError(
+                f"{self.key_type.decode()} key data can not be longer than {max_length} bits (was {p_bits})"
+            )
 
         dsa_parameters = DSAParameterNumbers(data_fields["p"], data_fields["q"], data_fields["g"])
         self.dsa = DSAPublicNumbers(data_fields["y"], dsa_parameters).public_key(default_backend())
@@ -350,21 +413,20 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
         """Parses ecdsa-sha public keys."""
         current_position, curve_information = self._unpack_by_int(data, 0)
         if curve_information not in self.ECDSA_CURVE_DATA:
-            raise NotImplementedError("Invalid curve type: %s" % curve_information)
+            raise NotImplementedError(f"Invalid curve type: {curve_information}")
         curve, hash_algorithm = self.ECDSA_CURVE_DATA[curve_information]
 
         current_position, key_data = self._unpack_by_int(data, current_position)
         try:
-            # data starts with \x04, which should be discarded.
-            ecdsa_key = ecdsa.VerifyingKey.from_string(key_data[1:], curve, hash_algorithm)
-        except AssertionError:
-            raise InvalidKeyError("Invalid ecdsa key")
-        self.bits = int(curve_information.replace(b"nistp", b""))
-        self.ecdsa = ecdsa_key
+            ecdsa_pubkey = ec.EllipticCurvePublicKey.from_encoded_point(curve, key_data)
+        except ValueError as ex:
+            raise InvalidKeyError("Invalid ecdsa key") from ex
+        self.bits = curve.key_size
+        self.ecdsa = _ECVerifyingKey(ecdsa_pubkey, hash_algorithm)
         return current_position
 
-    def _process_ed25516(self, data):
-        """Parses ed25516 keys.
+    def _process_ed25519(self, data):
+        """Parses ed25519 keys.
 
         There is no (apparent) way to validate ed25519 keys. This only
         checks data length (256 bits), but does not try to validate
@@ -379,20 +441,49 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
 
         self.bits = verifying_key_length
         if self.bits != 256:
-            raise InvalidKeyLengthError("ed25519 keys must be 256 bits (was %s bits)" % self.bits)
+            raise InvalidKeyLengthError(f"ed25519 keys must be 256 bits (was {self.bits} bits)")
+        return current_position
+
+    def _validate_application_string(self, application):
+        """Validates Application string.
+
+        Has to be an URL starting with "ssh:". See ssh-keygen(1)."""
+
+        try:
+            parsed_url = urlparse(application)
+        except ValueError as err:
+            raise InvalidKeyError(f"Application string: {err}") from err
+        if parsed_url.scheme != b"ssh":
+            raise InvalidKeyError('Application string must begin with "ssh:"')
+
+    def _process_sk_ecdsa_sha(self, data):
+        """Parses sk_ecdsa-sha public keys."""
+        current_position = self._process_ecdsa_sha(data)
+        current_position, application = self._unpack_by_int(data, current_position)
+        self._validate_application_string(application)
+        return current_position
+
+    def _process_sk_ed25519(self, data):
+        """Parses sk_ed25519 public keys."""
+        current_position = self._process_ed25519(data)
+        current_position, application = self._unpack_by_int(data, current_position)
+        self._validate_application_string(application)
         return current_position
 
     def _process_key(self, data):
         if self.key_type == b"ssh-rsa":
             return self._process_ssh_rsa(data)
-        elif self.key_type == b"ssh-dss":
+        if self.key_type == b"ssh-dss":
             return self._process_ssh_dss(data)
-        elif self.key_type.strip().startswith(b"ecdsa-sha"):
+        if self.key_type.strip().startswith(b"ecdsa-sha"):
             return self._process_ecdsa_sha(data)
-        elif self.key_type == b"ssh-ed25519":
-            return self._process_ed25516(data)
-        else:
-            raise NotImplementedError("Invalid key type: %s" % self.key_type)
+        if self.key_type == b"ssh-ed25519":
+            return self._process_ed25519(data)
+        if self.key_type.strip().startswith(b"sk-ecdsa-sha"):
+            return self._process_sk_ecdsa_sha(data)
+        if self.key_type.strip().startswith(b"sk-ssh-ed25519"):
+            return self._process_sk_ed25519(data)
+        raise NotImplementedError(f"Invalid key type: {self.key_type.decode()}")
 
     def parse(self, keydata=None):
         """Validates SSH public key.
@@ -426,7 +517,7 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
         # Check key type
         current_position, unpacked_key_type = self._unpack_by_int(self._decoded_key, 0)
         if key_type is not None and key_type != unpacked_key_type.decode():
-            raise InvalidTypeError("Keytype mismatch: %s != %s" % (key_type, unpacked_key_type))
+            raise InvalidTypeError(f"Keytype mismatch: {key_type} != {unpacked_key_type.decode()}")
 
         self.key_type = unpacked_key_type
 
@@ -434,7 +525,7 @@ class SSHKey(object):  # pylint:disable=too-many-instance-attributes
         current_position = current_position + key_data_length
 
         if current_position != len(self._decoded_key):
-            raise MalformedDataError("Leftover data: %s bytes" % (len(self._decoded_key) - current_position))
+            raise MalformedDataError(f"Leftover data: {len(self._decoded_key) - current_position} bytes")
 
         if self.disallow_options and self.options:
             raise InvalidOptionsError("Options are disallowed.")
diff --git a/tests/__init__.py b/tests/__init__.py
new file mode 100644
index 0000000..32da656
--- /dev/null
+++ b/tests/__init__.py
@@ -0,0 +1,191 @@
+""" Creates tests from lists of both valid and invalid keys.
+
+New test is generated for each key so that running unittests gives out meaningful errors.
+
+"""
+
+from .authorized_keys import items as list_of_authorized_keys
+from .invalid_authorized_keys import items as list_of_invalid_authorized_keys
+from .invalid_keys import keys as list_of_invalid_keys
+from .invalid_options import options as list_of_invalid_options
+from .valid_keys import keys as list_of_valid_keys
+from .valid_keys_rfc4716 import keys as list_of_valid_keys_rfc4716
+from .valid_options import options as list_of_valid_options
+from sshpubkeys import AuthorizedKeysFile, InvalidOptionsError, SSHKey
+
+import sys
+import unittest
+
+if sys.version_info.major == 2:
+    from io import BytesIO as StringIO
+else:
+    from io import StringIO
+
+DEFAULT_KEY = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEGODBKRjsFB/1v3pDRGpA6xR+QpOJg9vat0brlbUNDD"
+
+
+class TestMisc(unittest.TestCase):
+    def test_none_to_constructor(self):
+        ssh = SSHKey(None)
+        self.assertEqual(None, ssh.keydata)  # Python2.6 does not have assertIsNone
+        self.assertRaises(ValueError, ssh.parse)
+
+
+class TestKeys(unittest.TestCase):
+    def check_key(self, pubkey, bits, fingerprint_md5, fingerprint_sha256, options, comment, **kwargs):  # pylint:disable=too-many-arguments
+        """ Checks valid key """
+        ssh = SSHKey(pubkey, **kwargs)
+        ssh.parse()
+        self.assertEqual(ssh.bits, bits)
+        self.assertEqual(ssh.hash_md5(), fingerprint_md5)
+        self.assertEqual(ssh.options_raw, options)
+        self.assertEqual(ssh.comment, comment)
+        if fingerprint_sha256 is not None:
+            self.assertEqual(ssh.hash_sha256(), fingerprint_sha256)
+        if ssh.ecdsa:
+            ec = ssh.ecdsa
+            repr(ec)
+            ec.to_pem()
+            ec.to_der()
+            ec.to_string("raw")
+            ec.to_string("uncompressed")
+            ec.to_string("compressed")
+
+    def check_fail(self, pubkey, expected_error, **kwargs):
+        """ Checks that key check raises specified exception """
+        # Don't use with statement here - it does not work with Python 2.6 unittest module
+        ssh_key = SSHKey(pubkey, **kwargs)
+        self.assertRaises(expected_error, ssh_key.parse)
+
+    def test_key_property(self):
+        ssh = SSHKey(DEFAULT_KEY)
+        self.assertEqual(ssh.key, DEFAULT_KEY.split()[1].encode())
+
+
+class TestOptions(unittest.TestCase):
+    def check_valid_option(self, option, parsed_option):
+        ssh = SSHKey()
+        parsed = ssh.parse_options(option)
+        self.assertEqual(parsed, parsed_option)
+
+    def check_invalid_option(self, option, expected_error):
+        ssh = SSHKey()
+        self.assertRaises(expected_error, ssh.parse_options, option)
+
+    def test_disallow_options(self):
+        ssh = SSHKey(disallow_options=True)
+        key = """command="dump /home",no-pty,no-port-forwarding """ + DEFAULT_KEY
+        self.assertRaises(InvalidOptionsError, ssh.parse, key)
+
+
+class TestAuthorizedKeys(unittest.TestCase):
+    def check_valid_file(self, file_str, valid_keys_count):
+        file_obj = StringIO(file_str)
+        key_file = AuthorizedKeysFile(file_obj)
+        for item in key_file.keys:
+            self.assertIsInstance(item, SSHKey)
+        self.assertEqual(len(key_file.keys), valid_keys_count)
+
+    def check_invalid_file(self, file_str, expected_error):
+        file_obj = StringIO(file_str)
+        self.assertRaises(expected_error, AuthorizedKeysFile, file_obj)
+
+    def test_disallow_options(self):
+        file_obj = StringIO("""command="dump /home",no-pty,no-port-forwarding """ + DEFAULT_KEY)
+        self.assertRaises(InvalidOptionsError, AuthorizedKeysFile, file_obj, disallow_options=True)
+        file_obj.seek(0)
+        key_file = AuthorizedKeysFile(file_obj)
+        self.assertEqual(len(key_file.keys), 1)
+
+
+def loop_options(options):
+    """ Loop over list of options and dynamically create tests """
+
+    def ch(option, parsed_option):
+        return lambda self: self.check_valid_option(option, parsed_option)
+
+    for i, items in enumerate(options):
+        prefix_tmp = f"{items[0]}_{i}"
+        setattr(TestOptions, f"test_{prefix_tmp}", ch(items[1], items[2]))
+
+
+def loop_invalid_options(options):
+    def ch(option, expected_error):
+        return lambda self: self.check_invalid_option(option, expected_error)
+
+    for i, items in enumerate(options):
+        prefix_tmp = f"{items[0]}_{i}"
+        setattr(TestOptions, f"test_{prefix_tmp}", ch(items[1], items[2]))
+
+
+def loop_valid(keyset, prefix):
+    """ Loop over list of valid keys and dynamically create tests """
+
+    def ch(pubkey, bits, fingerprint_md5, fingerprint_sha256, options, comment, **kwargs):  # pylint:disable=too-many-arguments
+        return lambda self: self.check_key(pubkey, bits, fingerprint_md5, fingerprint_sha256, options, comment, **kwargs)
+
+    for items in keyset:
+        modes = items.pop()
+        prefix_tmp = f"{prefix}_{items.pop()}"
+        for mode in modes:
+            if mode == "strict":
+                kwargs = {"strict": True}
+            else:
+                kwargs = {"strict": False}
+            if len(items) == 4:
+                pubkey, bits, fingerprint_md5, fingerprint_sha256 = items
+                options = comment = None
+            else:
+                pubkey, bits, fingerprint_md5, fingerprint_sha256, options, comment = items
+            setattr(
+                TestKeys, f"test_{prefix_tmp}_mode_{mode}",
+                ch(pubkey, bits, fingerprint_md5, fingerprint_sha256, options, comment, **kwargs)
+            )
+
+
+def loop_invalid(keyset, prefix):
+    """ Loop over list of invalid keys and dynamically create tests """
+
+    def ch(pubkey, expected_error, **kwargs):
+        return lambda self: self.check_fail(pubkey, expected_error, **kwargs)
+
+    for items in keyset:
+        modes = items.pop()
+        prefix_tmp = f"{prefix}_{items.pop()}"
+        for mode in modes:
+            if mode == "strict":
+                kwargs = {"strict": True}
+            else:
+                kwargs = {"strict": False}
+            pubkey, expected_error = items
+            setattr(TestKeys, f"test_{prefix_tmp}_mode_{mode}", ch(pubkey, expected_error, **kwargs))
+
+
+def loop_authorized_keys(keyset):
+    def ch(file_str, valid_keys_count):
+        return lambda self: self.check_valid_file(file_str, valid_keys_count)
+
+    for i, items in enumerate(keyset):
+        prefix_tmp = f"{items[0]}_{i}"
+        setattr(TestAuthorizedKeys, f"test_{prefix_tmp}", ch(items[1], items[2]))
+
+
+def loop_invalid_authorized_keys(keyset):
+    def ch(file_str, expected_error, **kwargs):
+        return lambda self: self.check_invalid_file(file_str, expected_error, **kwargs)
+
+    for i, items in enumerate(keyset):
+        prefix_tmp = f"{items[0]}_{i}"
+        setattr(TestAuthorizedKeys, f"test_invalid_{prefix_tmp}", ch(items[1], items[2]))
+
+
+loop_valid(list_of_valid_keys, "valid_key")
+loop_valid(list_of_valid_keys_rfc4716, "valid_key_rfc4716")
+loop_invalid(list_of_invalid_keys, "invalid_key")
+loop_options(list_of_valid_options)
+loop_invalid_options(list_of_invalid_options)
+loop_authorized_keys(list_of_authorized_keys)
+loop_invalid_authorized_keys(list_of_invalid_authorized_keys)
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/authorized_keys.py b/tests/authorized_keys.py
new file mode 100644
index 0000000..a213862
--- /dev/null
+++ b/tests/authorized_keys.py
@@ -0,0 +1,8 @@
+from .valid_keys import keys
+
+items = [
+    ["empty_file", "", 0],
+    ["single_key", keys[0][0], 1],
+    ["comment_only", "# Nothing else than a comment here", 0],
+    ["lines_with_spaces", " # Comments\n  \n" + keys[0][0] + "\n#asdf", 1],
+]
diff --git a/tests/invalid_authorized_keys.py b/tests/invalid_authorized_keys.py
new file mode 100644
index 0000000..d229804
--- /dev/null
+++ b/tests/invalid_authorized_keys.py
@@ -0,0 +1,8 @@
+from .invalid_keys import keys as invalid_keys
+from .valid_keys import keys as valid_keys
+from sshpubkeys.exceptions import InvalidKeyError, MalformedDataError
+
+items = [
+    ["lines_with_spaces", " # Comments\n  \n" + valid_keys[0][0] + "\nasdf", InvalidKeyError],
+    ["invalid_key", "# Comments\n" + invalid_keys[0][0], MalformedDataError],
+]
diff --git a/tests/invalid_keys.py b/tests/invalid_keys.py
new file mode 100644
index 0000000..3bdd04d
--- /dev/null
+++ b/tests/invalid_keys.py
@@ -0,0 +1,94 @@
+from sshpubkeys.exceptions import (
+    InvalidKeyError, InvalidKeyLengthError, InvalidTypeError, MalformedDataError, TooLongKeyError, TooShortKeyError
+)
+
+keys = [
+    [
+        "ssh-dss AAAAB3NzaC1kc3MAAACBAPlHIP5sD+T8/Sx1DGEiCzCXqpl7ww40jBg7wTkxu44OH6pNog5PjJt5M4NBULhKva/i+bhIM3ba+H1Or+aHWWFHACV6W2FCGk/k37ApRF8sIa4hsnN0P9qn6VfhbJKee+DBxa21WjjY/MZiljmJz7IQHx5RTxX9I/hJ7cL+aNmrAAAAFQCKteqc4IkgIrjpcpStsxYAhb3MqQAAAIEA+SfIKuTr7QPcinsZQDdmZOXqcg+u9TLzHA4c47y0Kns3T3BVPr9rWdmuh6eImzLO4wMLxLvcg3ecrqFuiCp1IHvXENkGlpB17S+uOXlVDY+sTdXyvYKRKirg5IZefIAP/m08c0QGkhFDbo4ysr9D5gXgH3LB2rMPIAbvMWm/HZQAAACBAKWtAE3hXRQX5KtI4AoIWVTly/6T4JNBt4u24ZRqV7X//CZEZ0cS5YpR/frlpUDI3WKoMtS+VmT3cBFZINashIxZyfBF8+0UX3s34HwNfp0hDW3ZdgZJU56GC2eclMantYGeVrMxgTQd80pxZFgByEhoXGeZaAwUzN8ULo9jHQo=",
+        MalformedDataError, "too_short_data", ["loose", "strict"]
+    ],
+    [
+        "ssh-dss AAAAB3NzaC1kc3MAAACBAPlHIP5sD+T8/Sx1DGEiCzCXqpl7ww40jBg7wTkxu44OH6pNog5PjJt5M4NBULhKva/i+bhIM3ba+H1Or+aHWWFHACV6W2FCGk/k37ApRF8sIa4hsnN0P9qn6VfhbJKee+DBxa21WjjY/MZiljmJz7IQHx5RTxX9I/hJ7cL+aNmrAAAAFQCKteqc4IkgIrjpcpStsxYAhb3MqQAAAIEA+SfIKuTr7QPcinsZQDdmZOXqcg+u9TLzHA4c47y0Kns3T3BVPr9rWdmuh6eImzLO4wMLxLvcg3ecrqFuiCp1IHvXENkGlpB17S+uOXlVDY+sTdXyvYKRKirg5IZefIAP/m08c0QGkhFDbo4ysr9D5gXgH3LB2rMPIAbvMWm/HZQAAACBAKWtAE3hXRQX5KtI4AoIWVTly/6T4JNBt4u24ZRqV7X//CZEZ0cS5YpR/frlpUDI3WKoMtS+VmT3cBFZINashIxZyfBF8+0UX3s34HwNfp0hDW3ZdgZJU56GC2eclMantYGeVrMxgTQd80pxZFgByEhoXGeZaAwUzN8ULo9jHQqMjA==",
+        MalformedDataError, "too_long_data", ["loose", "strict"]
+    ],
+    [
+        "ssh-dss AAAAB3NzaC1yc2EAAACBAPlHIP5sD+T8/Sx1DGEiCzCXqpl7ww40jBg7wTkxu44OH6pNog5PjJt5M4NBULhKva/i+bhIM3ba+H1Or+aHWWFHACV6W2FCGk/k37ApRF8sIa4hsnN0P9qn6VfhbJKee+DBxa21WjjY/MZiljmJz7IQHx5RTxX9I/hJ7cL+aNmrAAAAFQCKteqc4IkgIrjpcpStsxYAhb3MqQAAAIEA+SfIKuTr7QPcinsZQDdmZOXqcg+u9TLzHA4c47y0Kns3T3BVPr9rWdmuh6eImzLO4wMLxLvcg3ecrqFuiCp1IHvXENkGlpB17S+uOXlVDY+sTdXyvYKRKirg5IZefIAP/m08c0QGkhFDbo4ysr9D5gXgH3LB2rMPIAbvMWm/HZQAAACBAKWtAE3hXRQX5KtI4AoIWVTly/6T4JNBt4u24ZRqV7X//CZEZ0cS5YpR/frlpUDI3WKoMtS+VmT3cBFZINashIxZyfBF8+0UX3s34HwNfp0hDW3ZdgZJU56GC2eclMantYGeVrMxgTQd80pxZFgByEhoXGeZaAwUzN8ULo9jHQqM",
+        InvalidTypeError, "key_type_mismatch", ["loose", "strict"]
+    ],
+    [
+        "ssh-dss AAAAB3NzaC1yc2EAAAADAQABAAAEAgDGrGaNv7i+sGSelzf+7JsCECa9a0sqSg8q4foGkjeV6RkS2tWvKXoT9rICjEdXXodj0CCVhe/V7dmAO0AK8KM0mcvPfTSC8zH1ZBsqaFFTWwmBD01fbH9axrrg3hM0f+AL4bMMWUdxdNrVo90s8PKU6k/HmUNLVx4gC6uQ4A6YczvOVZkuJ4f7HDYK/v1LNTRNeAkw94YpSIZVAoTOZN943+fRCE9cm155pwmFsS+wfzK9+jjhGXNEK0xooiVBRwQM7qetN076vV5FiiM0LO1qYi5JrIqK/70ske86x2mMhMkOe6jqQQbt32PFVmYqYJWcAYXz+bhcQw6oru0c6gNq53aGOnuqI0uh/zV2XH+cN4c8ABcOplzH5YQEUepNVzxylkvpWxdg/ZzR1pvyu5C8RkJWrE3AlCwpix1ak2xTDzgc3rwTTggNSYqvzmYq0mYJhZk2VWsLVxUgdxfwC3LvIHMXSTU9iU2Aqrlhy7bJAqxQFKWy05wsIOI6raPBLqZnPmJ76Ld9aXTrhBFfIDiigr9ZVsVAdOvmyAGCIj4x3Xnlol/3lN0M2+OSV1SU/5ZrS6dIlXPZDak/OXHU0iIFIODhYU5r8EI1M6BI/jsgQ8HatXmOJkfnIkVP0HxD1KvoAFKjVG5sM9KG12LqsnzfD1KL6PzxpOOgoVgznpOjSzVmPKAkU8N/r6R4VIAmZqxpF8Hlzqg/Gfh5kf6CJXXx8OQt1Z/DAsfnl3LvHFNuE8GgXgrUE022W9pV4oONgojc97JSgBXaFkK885UnJKTceAdGQvChEhsU1j3TiyKPox6ICGpoC2nGONJoDE8VQ8dE/YiZmqkZ1lJWX07EwevrIcnz1UBHFaR72aiAADRYClsitLA5+1mnydVstkQ8XQuuKNOFT7miaWUzRHwj9BYGb7oGhNd9oi1VTVjH/5Yq1UiHHESGaIjeLi5uG2KguDFpcvy2ngtUy3ZbvDj+DVOLL+3vAlycRPjN0nBE4e/J6UqdpLg0DbG56zNj86aU0ZgL8kL8NRkFHyV+5zG5iLFkGklbm4nwCxSW/bVT0PFD1is6JbtIk5i+liS+hiuzSF6NGouSuxDy95yWSG8/84fgPDFtvXtOD7Kl4P7EpEAL+VBZnremT9I8tRl1wOHxJKe7jbEcWC2zkuHNlju0Nv5SFijF9c+krRbHDYEzsxPpdqlI4gPtDFdkKwaKN6BrsxBsz9u+PhS1AloUYcxKRqWbqHuDBrKmxnhOgFqJ9ITX0RajtrApt1LfkSBXcFrVEx2nhQkGa6VwjcX/zw2I2iuJFOCQmc9udHIlyaCCSe1PqOIbOlOk5h/Gl1QvRNwSIgf9dZ05lZr6dc+VX8YGdyHsjQ==",
+        InvalidTypeError, "rsa_key_no_match", ["loose", "strict"]
+    ],
+    [
+        "ssh-dss AAAAB3NzaC1kc3MAAACAwQBAoKCAoECggSAgAOAAwOCg4AEAIMBAgMBAYSBg4GBggKAgwOBAwEDBAMCgwECg4GCBAAEhAABhIOCBIIEAQECg4GEAoQEgQQBgAGEAYQEAgCDAoCDgoIDBICAAAOCgwGDhAAAAwQEBIKCAYEBA4ODg4EDggSAgAGEgAQCAAOAAAAAgAAAAAAAAAAAAAAAAAACEAYKAgICCAIMAAYCBAYICAoAAAACAgKEgQCEhIKDgISCAAIDgwGEgASEg4GAgwQDAoCEAAEDBICDhAAABACCgIACBAIBAwOEgQEAA4KBBAOAAIIDAIQAgoGBgYGCgYCCAYEEgoEEgAABAIACAIAChAKCgoKAhIMDAgMEBIIDgAQEgwCDAAMBA4KAgACBAgCCgIGBAoGAAAACAwKAgAIBgIIBhAIBgQSAAgMAAQICggQDg4SCgoACgASCAwKCAYSAAoMCAYAEAoKBgoQEBIAAgICBAoMDBAMEgYIAgYKDggSDAoQDgQEAgAOBgQAAggQCAoCAgwAEBIEDgYABAgOEAwECAQECAAQDAAECBIGBAgEBA4AAgQSEBAKA=",
+        InvalidKeyError, "invalid_q_for_dsa", ["loose", "strict"]
+    ],
+    [
+        "ssh-dss AAAAB3NzaC1kc3MAAACAgIBAAIBgQJAwgJCAQCBwICAwYFAwcEBQMBBwUHAgcCAAkEAQQECQkBAgkGAwcEAAkIAAMAAwAJAAcABQQCAwIHAwIIAwYAAwICCQkAAAUHAwIBCAMBBQcCAQAFBggEBAQDAgIHAwUJAwkFCQUDBwkIAQEGAwICAQADAwcJAAEJAAAAAgAAAAAAAAAAAAAAAAhIIAggODBAAEgwIAhIGChIICBAAAAACAwQJBAcECQQBAQIGBAEHBQEGBgYCAAQGCAIECQMHBwAIAAIDBAMIBgEEAQADBwIDAgcABAYHBwMDAgcABQgABwAHAAkBBwYAAwYJBwgAAwQFCQICAQgFAQICAgAIAwQHBQYJBQADAgAIAgMHBwkJAQEFBAMGAQAGBQQHAggBAQIA=",
+        MalformedDataError, "missing_y_from_dsa", ["loose", "strict"]
+    ],
+    [
+        'ssh-dss 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',
+        InvalidKeyLengthError, "too_long_dsa_4096", ["loose", "strict"]
+    ],
+    [
+        'ssh-dss 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',
+        InvalidKeyLengthError, "too_long_dsa_16384", ["loose", "strict"]
+    ],
+    [
+        "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAEAgDGrGaNv7i+sGSelzf+7JsCECa9a0sqSg8q4foGkjeV6RkS2tWvKXoT9rICjEdXXodj0CCVhe/V7dmAO0AK8KM0mcvPfTSC8zH1ZBsqaFFTWwmBD01fbH9axrrg3hM0f+AL4bMMWUdxdNrVo90s8PKU6k/HmUNLVx4gC6uQ4A6YczvOVZkuJ4f7HDYK/v1LNTRNeAkw94YpSIZVAoTOZN943+fRCE9cm155pwmFsS+wfzK9+jjhGXNEK0xooiVBRwQM7qetN076vV5FiiM0LO1qYi5JrIqK/70ske86x2mMhMkOe6jqQQbt32PFVmYqYJWcAYXz+bhcQw6oru0c6gNq53aGOnuqI0uh/zV2XH+cN4c8ABcOplzH5YQEUepNVzxylkvpWxdg/ZzR1pvyu5C8RkJWrE3AlCwpix1ak2xTDzgc3rwTTggNSYqvzmYq0mYJhZk2VWsLVxUgdxfwC3LvIHMXSTU9iU2Aqrlhy7bJAqxQFKWy05wsIOI6raPBLqZnPmJ76Ld9aXTrhBFfIDiigr9ZVsVAdOvmyAGCIj4x3Xnlol/3lN0M2+OSV1SU/5ZrS6dIlXPZDak/OXHU0iIFIODhYU5r8EI1M6BI/jsgQ8HatXmOJkfnIkVP0HxD1KvoAFKjVG5sM9KG12LqsnzfD1KL6PzxpOOgoVgznpOjSzVmPKAkU8N/r6R4VIAmZqxpF8Hlzqg/Gfh5kf6CJXXx8OQt1Z/DAsfnl3LvHFNuE8GgXgrUE022W9pV4oONgojc97JSgBXaFkK885UnJKTceAdGQvChEhsU1j3TiyKPox6ICGpoC2nGONJoDE8VQ8dE/YiZmqkZ1lJWX07EwevrIcnz1UBHFaR72aiAADRYClsitLA5+1mnydVstkQ8XQuuKNOFT7miaWUzRHwj9BYGb7oGhNd9oi1VTVjH/5Yq1UiHHESGaIjeLi5uG2KguDFpcvy2ngtUy3ZbvDj+DVOLL+3vAlycRPjN0nBE4e/J6UqdpLg0DbG56zNj86aU0ZgL8kL8NRkFHyV+5zG5iLFkGklbm4nwCxSW/bVT0PFD1is6JbtIk5i+liS+hiuzSF6NGouSuxDy95yWSG8/84fgPDFtvXtOD7Kl4P7EpEAL+VBZnremT9I8tRl1wOHxJKe7jbEcWC2zkuHNlju0Nv5SFijF9c+krRbHDYEzsxPpdqlI4gPtDFdkKwaKN6BrsxBsz9u+PhS1AloUYcxKRqWbqHuDBrKmxnhOgFqJ9ITX0RajtrApt1LfkSBXcFrVEx2nhQkGa6VwjcX/zw2I2iuJFOCQmc9udHIlyaCCSe1PqOIbOlOk5h/Gl1QvRNwSIgf9dZ05lZr6dc+VX8YGdyHsjQ=",
+        InvalidKeyError, "broken_rsa_base64", ["loose", "strict"]
+    ],
+    [
+        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAH0GODBKRjsFB/1v3pDRGpA6xR+QpOJg9vat0brlbUNA=", InvalidKeyLengthError,
+        "too_short_ed25519", ["loose", "strict"]
+    ],
+    [
+        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIUGODBKRjsFB/1v3pDRGpA6xR+QpOJg9vat0brlbUNDDpA==", InvalidKeyLengthError,
+        "too_long_ed25519", ["loose", "strict"]
+    ],
+    [
+        "ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBE2gqbAChP2h3fTPx3Jy2KdOJUiBGEiqBUwoosfzllw+KrqmGiDEWlufSxdiSOFuLd4a8PSwhoWbdQgRVFrZAvFE=",
+        InvalidKeyError, "invalid_ecdsa_key", ["loose", "strict"]
+    ],
+    [
+        "ecdsa-sha2-nistp255 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTUAAAAIbmlzdHAyNTUAAABBBE2gqbAChP2h3fTPx3Jy2KdOJUiBGEiqBUwoosfzllw+KrqmGiDEWlufSxdiSOFuLd4a8PSwhoWbdQRVFrZAvFE=",
+        NotImplementedError, "invalid_nist_curve", ["loose", "strict"]
+    ],
+    ["", InvalidKeyError, "empty_key", ["loose", "strict"]],
+    ["- -", InvalidKeyError, "no_content", ["loose", "strict"]],
+    [
+        "ssh-invalid-key-type AAAAFHNzaC1pbnZhbGlkLWtleS10eXBlAAAAgMEgAGDgAKEBAMAgoECggSCAQIEAoIAhASEhAKDAAOAAwGCBIKAAYGCgYKDhAEBAwICAoIDgIADAYKAAYGAAYAEgwGBBIGDhIOBg4CAAoQDAIEAgIEEggEDgQGCAIGAhAQDgoKAhIAAggSBA4CBggOEBIEDgoMDAwKBg4MDAYIDgAAAAIAAAAAAAAAAAAAAAAIAggEEggSBAIIBgAMDAQADAIQEgAAAAgJAQABBgICBQUABQcFAAcJBgUIAAIHAAkJBQEIAQMEAgIHBQEFCAUBBQUHAQMGBgQBCAEEAgICBQYDBwIJBAYFCQYDBwIAAQIHCQMEBwYCBAICAAEFBQAHAgAIBQAJBwgEBwYGCAEHBgkBAwEBAQcHAQMGCQMCBQIABAUJAgEIAgAAAAgIGAAYIDgoSBA4ABAgAEAIEEAoEAg4IDAgQCAwCDgQMAgQABgoGAAgMCgoOCA4QABAGBAQQDgoKABASBhAQDgoIBgIQEgAQEAQSBg4IEBICEggKBAAABgYKDAgGDgYAAgoGCAoODgYGEAwIBAoACgQADBAGDgASCgQMDgAABAISA",
+        NotImplementedError, "not_implemented_key_type", ["loose", "strict"]
+    ],
+
+    # 512 bit ed25519 keys are not yet supported by OpenSSH
+    [
+        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAQIMcGCUjHYKD/rfvSGiNSB1ij8hScTB7e1bo3XK2oaGGAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=",
+        InvalidKeyLengthError, "512bit_ed25519", ["loose", "strict"]
+    ],
+    [
+        "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAQIBBAIDAICBAgEABACAggGCgAABAwOEAwGBAgEEg4SBAAKBBIGEAgSEgAIEgoMCgICAgYMCgYQDgoKBgIIDgwCA=",
+        InvalidKeyLengthError, "512bit_ed25519", ["loose", "strict"]
+    ],
+    [
+        'command="dump /home,no-pty,no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABADR9kolU4uiD26LMrbakQlNf4QWB2xrdY3nASf6CJdQYzTMjNmbt6sJ4A4pGnCupFrzL04EYDvbVmT4GEZm6CU4BsY61yosnpGSqqcVCdw5xW1k4bCSDPW75WHLCVmYyROhZ+yyo8uAcIy5UIyBZXF/PO7taJrrIi5RwdqIPwtCrJ3dJkcFWa3qZWJykLAFQD5A/lta/egS/u/nyCap2e16WGnvSluz9CyYtGFNS9axzOwHxLFEv2ocOsJjYgzV+Jfpiao94A4VzLKbUDHlfV57KS0tJaT8FKKsg34vN3bsD0zUftLUPpUFgJfMwje0C2rCJkCzwgya2vxLqj2fg0Q0= ojarva@ojar-laptop.local',
+        MalformedDataError, "missing_quote", ["loose", "strict"]
+    ],
+    [
+        'ssh-dss AAAAB3NzaC1kc3MAAAEBAM4SvSD+Gpu4L5TvkroBbAcVPeQID1gdZTpr5fEuOCwTVxMyuPwfHH6txh4Nq0K7MRee5zuVKHNkxj84EMF/+g4eJISmE87wzfYNJQhGNOmXO3yYGCmFaDgrlsWH9OhGglWTxz768gJy4IUP2hqvsbotdpjhRvTFCIep12r4L16rFQJeVVti6Xml3UZHXvoMbwJC+BulwU8hnosXvH4mYikgoaSmDUfJkkLB1nD/g48vo172iu2mfEYqAbn9lX46vnetmpz87IHxbCHmIuJxhMfH+vMY5zvF7vUy018XUPrAcqDkmszhJOFuMhB2SQ6IT8nQZnZ+aGGnoQ2kgjCrrusAAAAVAN/iBeqRO1CPAuNIec08Y9VP+MFTAAABAGDVzqw4i64Fd1mLi6BRKYZdbMI56gx+Cu+EfAjH7dx6AqEW7PiSB2yQrXl1dbCbLYhQhEXIaJW+8epTCsm9o22+KZ5yIyyNc5SxPad7W4W/gvSzqMZC+NMBYia8hrq3BHk9OYxFUZfCx47adbs9sKFi1GhgCbXiDsrb8EvzMWMyyKyAl1AaCaMYWVXnDRBtJnASK2GyiR4GWHA+4z9syrEHknM0RonP2B24552cYq3gxCxRvZ6XJBRQaRnS9RjIaziDImXoLa5X/82ZT6cVzwdZa9S9LGJusfBLrE12O8nis1iI1CliukGtOmWvogFqYABtkzGizrnajCpU4doiuoUAAAEAchR3IrCbXnDekPQGt+uM4cSdZ9OIt2wROlxJODV/Z57OOGMm7RFJkuC4olN1h032dhHM6hsKzsMoRkin0zLuZgsInKs2LnmaL27wwB5wcriLnZm1HK9PUEH5A/wqR4Vc2SHUa1Zzvjddqe0fk2rRzYhaACctSii8CH68nmECZDgn0xePz8n4p4CoZalkQvcjEW/O6nzgrudW3VahxEl4YijuWocQ+y0vWIa6OByuYbDAxST971RF84Q0M8I1jnEwteGcYnLV8CVZQaZ5fmI3t4Z8CcRN339rKpvakVgNYYATJcTc402TIhyRHMLew63et11xkIVGocLaaYaI2gzavA==',
+        TooLongKeyError, "dsa_2048", ["strict"]
+    ],
+    [
+        'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQbdtLTII+vP98NSDlK2LXxVARELRYO0NODFYQ0imYxsmBMB7BrfljFppLJyjU6cziOT6YFj6rVd8MmCogdCR32u63EV11uT6RCFfJMQJtIi+B1JJipTxLzURsiUOOgAHJc= ojarva@ojar-laptop.local',
+        TooShortKeyError, "rsa_771", ["strict"]
+    ],
+    [
+        'sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIJ+CG2daFaeUC2GMvxGe5bTXRxforrL3MNOcsxbMbQeHAAAABGludjo=',
+        InvalidKeyError, 'invalid_appid_sk-ssh-ed25519', ["loose", "strict"]
+    ],
+    [
+        'sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAIHIoT5FA++PiJ4g4cORu3DBK4HWBO8mMjbp1Jtp4twl4AAAAB3NzaDovL1s=',
+        InvalidKeyError, 'invalid_url_sk-ssh-ed25519', ["loose", "strict"]
+    ],
+]
diff --git a/tests/invalid_options.py b/tests/invalid_options.py
new file mode 100644
index 0000000..8d79c61
--- /dev/null
+++ b/tests/invalid_options.py
@@ -0,0 +1,19 @@
+from sshpubkeys.exceptions import (
+    InvalidOptionNameError, InvalidOptionsError, MissingMandatoryOptionValueError, UnknownOptionNameError
+)
+
+options = [
+    ["includes_space", "no-user-rc ", InvalidOptionsError],
+    ["includes_space_multiple", "no-user-rc, port-forwarding", InvalidOptionsError],
+    ["includes_space_before_comma", "no-user-rc ,port-forwarding", InvalidOptionsError],
+    ["empty_option_end", "no-user-rc,", InvalidOptionsError],
+    ["empty_option_beginning", ",no-user-rc", InvalidOptionsError],
+    ["empty_option_middle", "no-user-rc,,port-forwarding", InvalidOptionsError],
+    ["unbalanced_quotes", 'from="asdf', InvalidOptionsError],
+    ["invalid_characters_in_key_percent", 'from%', InvalidOptionNameError],
+    ["invalid_characters_in_key_parenthesis", 'from)', InvalidOptionNameError],
+    ["invalid_characters_in_key_space", 'fr om', InvalidOptionNameError],
+    ["unknown_option_name", "random-option-name", UnknownOptionNameError],
+    ["unbalanced_quotes_complex", 'from="asdf",no-user-rc"', InvalidOptionsError],
+    ["parameter_missing", 'from,no-user-rc"', MissingMandatoryOptionValueError],
+]
diff --git a/tests/test_dsa_keys_failing.py b/tests/test_dsa_keys_failing.py
new file mode 100644
index 0000000..1d53468
--- /dev/null
+++ b/tests/test_dsa_keys_failing.py
@@ -0,0 +1,12 @@
+from sshpubkeys.exceptions import MalformedDataError
+
+keys = [
+    [
+        "ssh-dss AAAAB3NzaC1kc3MAAACBAPlHIP5sD+T8/Sx1DGEiCzCXqpl7ww40jBg7wTkxu44OH6pNog5PjJt5M4NBULhKva/i+bhIM3ba+H1Or+aHWWFHACV6W2FCGk/k37ApRF8sIa4hsnN0P9qn6VfhbJKee+DBxa21WjjY/MZiljmJz7IQHx5RTxX9I/hJ7cL+aNmrAAAAFQCKteqc4IkgIrjpcpStsxYAhb3MqQAAAIEA+SfIKuTr7QPcinsZQDdmZOXqcg+u9TLzHA4c47y0Kns3T3BVPr9rWdmuh6eImzLO4wMLxLvcg3ecrqFuiCp1IHvXENkGlpB17S+uOXlVDY+sTdXyvYKRKirg5IZefIAP/m08c0QGkhFDbo4ysr9D5gXgH3LB2rMPIAbvMWm/HZQAAACBAKWtAE3hXRQX5KtI4AoIWVTly/6T4JNBt4u24ZRqV7X//CZEZ0cS5YpR/frlpUDI3WKoMtS+VmT3cBFZINashIxZyfBF8+0UX3s34HwNfp0hDW3ZdgZJU56GC2eclMantYGeVrMxgTQd80pxZFgByEhoXGeZaAwUzN8ULo9jHQo=",
+        MalformedDataError, "too_short_data"
+    ],
+    [
+        "ssh-dss AAAAB3NzaC1kc3MAAACBAPlHIP5sD+T8/Sx1DGEiCzCXqpl7ww40jBg7wTkxu44OH6pNog5PjJt5M4NBULhKva/i+bhIM3ba+H1Or+aHWWFHACV6W2FCGk/k37ApRF8sIa4hsnN0P9qn6VfhbJKee+DBxa21WjjY/MZiljmJz7IQHx5RTxX9I/hJ7cL+aNmrAAAAFQCKteqc4IkgIrjpcpStsxYAhb3MqQAAAIEA+SfIKuTr7QPcinsZQDdmZOXqcg+u9TLzHA4c47y0Kns3T3BVPr9rWdmuh6eImzLO4wMLxLvcg3ecrqFuiCp1IHvXENkGlpB17S+uOXlVDY+sTdXyvYKRKirg5IZefIAP/m08c0QGkhFDbo4ysr9D5gXgH3LB2rMPIAbvMWm/HZQAAACBAKWtAE3hXRQX5KtI4AoIWVTly/6T4JNBt4u24ZRqV7X//CZEZ0cS5YpR/frlpUDI3WKoMtS+VmT3cBFZINashIxZyfBF8+0UX3s34HwNfp0hDW3ZdgZJU56GC2eclMantYGeVrMxgTQd80pxZFgByEhoXGeZaAwUzN8ULo9jHQqMjA==",
+        MalformedDataError, "too_long_data"
+    ],
+]
diff --git a/tests/valid_keys.py b/tests/valid_keys.py
new file mode 100644
index 0000000..77a9fba
--- /dev/null
+++ b/tests/valid_keys.py
@@ -0,0 +1,229 @@
+keys = [[
+    'ssh-dss AAAAB3NzaC1kc3MAAACBAPlHIP5sD+T8/Sx1DGEiCzCXqpl7ww40jBg7wTkxu44OH6pNog5PjJt5M4NBULhKva/i+bhIM3ba+H1Or+aHWWFHACV6W2FCGk/k37ApRF8sIa4hsnN0P9qn6VfhbJKee+DBxa21WjjY/MZiljmJz7IQHx5RTxX9I/hJ7cL+aNmrAAAAFQCKteqc4IkgIrjpcpStsxYAhb3MqQAAAIEA+SfIKuTr7QPcinsZQDdmZOXqcg+u9TLzHA4c47y0Kns3T3BVPr9rWdmuh6eImzLO4wMLxLvcg3ecrqFuiCp1IHvXENkGlpB17S+uOXlVDY+sTdXyvYKRKirg5IZefIAP/m08c0QGkhFDbo4ysr9D5gXgH3LB2rMPIAbvMWm/HZQAAACBAKWtAE3hXRQX5KtI4AoIWVTly/6T4JNBt4u24ZRqV7X//CZEZ0cS5YpR/frlpUDI3WKoMtS+VmT3cBFZINashIxZyfBF8+0UX3s34HwNfp0hDW3ZdgZJU56GC2eclMantYGeVrMxgTQd80pxZFgByEhoXGeZaAwUzN8ULo9jHQqM ojarva@ojar-laptop.local',
+    1024, 'MD5:76:66:08:8c:86:81:7e:f0:7b:cd:fa:c3:8c:8b:83:c0', 'SHA256:9zzceH55d0MTpjCTR8aJwWSLBlEKnj2elHisq7Idx9Y', None,
+    'ojarva@ojar-laptop.local', 'dsa_basic_1', ["strict", "loose"]
+], [
+    'ssh-dss AAAAB3NzaC1kc3MAAACBAJKa9kgpSUBLgPwgkRvYDayXIjigt36VZShchgKSNxjOXfuJpNP7BUZFJSqE1ZKvMcmMKah2V15a+aV8H5TnFYSUT+aq5BH2lSxx5cHQ/xrSMBobqjxQHQJshrHugnrBmXvhadWHZ8T/kV0agddRTuC/nY28RA2OOLFukEc2C/O7AAAAFQDMCEXIHwdtyxv0HDBHhN+N9pzedwAAAIB7zE3EQ8tHvEhoHZ3lc53qMCfow64rv5L0eim6hqC/cwzWHGFk9PXAHgXOZBMB9P2gCdiL1Vydru/6ib3EbzAGR21xhvxlrZQqtJ7jKql0ZbVCqzYijBwJCU2OAvaxjyTZwg5o87h1LqxU9RRFJTJerMCcnEy4X7iIIF2S8TLeswAAAIAxQ9/DLm7l3X438VFgdTKSOrrfgx5q5/sKXgauNTxaYfDEBlmWdFZme3+lB1gR0td9NMxH/ffntXd8ilB+9O8E87+K0Fi7aDWlToVbsvtyK/gLTwzg+qEjeHkbjN7yUltvhzzvLkJN7NodWx4ECNP9Kuxzxq711uoFOiC+pFjJhQ==',
+    1024, 'MD5:ff:eb:5b:a2:31:26:4a:2f:90:60:93:1d:1c:e5:ac:40', 'SHA256:nqEdmFPW2hBVUeLzzYWZKGvahG7xeSb98AkKVmSfO70',
+    'dsa_basic_2', ["strict", "loose"]
+], [
+    'ssh-dss AAAAB3NzaC1kc3MAAAEBAM4SvSD+Gpu4L5TvkroBbAcVPeQID1gdZTpr5fEuOCwTVxMyuPwfHH6txh4Nq0K7MRee5zuVKHNkxj84EMF/+g4eJISmE87wzfYNJQhGNOmXO3yYGCmFaDgrlsWH9OhGglWTxz768gJy4IUP2hqvsbotdpjhRvTFCIep12r4L16rFQJeVVti6Xml3UZHXvoMbwJC+BulwU8hnosXvH4mYikgoaSmDUfJkkLB1nD/g48vo172iu2mfEYqAbn9lX46vnetmpz87IHxbCHmIuJxhMfH+vMY5zvF7vUy018XUPrAcqDkmszhJOFuMhB2SQ6IT8nQZnZ+aGGnoQ2kgjCrrusAAAAVAN/iBeqRO1CPAuNIec08Y9VP+MFTAAABAGDVzqw4i64Fd1mLi6BRKYZdbMI56gx+Cu+EfAjH7dx6AqEW7PiSB2yQrXl1dbCbLYhQhEXIaJW+8epTCsm9o22+KZ5yIyyNc5SxPad7W4W/gvSzqMZC+NMBYia8hrq3BHk9OYxFUZfCx47adbs9sKFi1GhgCbXiDsrb8EvzMWMyyKyAl1AaCaMYWVXnDRBtJnASK2GyiR4GWHA+4z9syrEHknM0RonP2B24552cYq3gxCxRvZ6XJBRQaRnS9RjIaziDImXoLa5X/82ZT6cVzwdZa9S9LGJusfBLrE12O8nis1iI1CliukGtOmWvogFqYABtkzGizrnajCpU4doiuoUAAAEAchR3IrCbXnDekPQGt+uM4cSdZ9OIt2wROlxJODV/Z57OOGMm7RFJkuC4olN1h032dhHM6hsKzsMoRkin0zLuZgsInKs2LnmaL27wwB5wcriLnZm1HK9PUEH5A/wqR4Vc2SHUa1Zzvjddqe0fk2rRzYhaACctSii8CH68nmECZDgn0xePz8n4p4CoZalkQvcjEW/O6nzgrudW3VahxEl4YijuWocQ+y0vWIa6OByuYbDAxST971RF84Q0M8I1jnEwteGcYnLV8CVZQaZ5fmI3t4Z8CcRN339rKpvakVgNYYATJcTc402TIhyRHMLew63et11xkIVGocLaaYaI2gzavA==',
+    2048, 'MD5:17:3d:f6:aa:3c:05:f0:4a:38:89:ac:b8:d4:96:00:45', 'SHA256:wCp2uM6uN/HF1gK3k9ZMkeZLhGG+LVf3ZpISU0I3mdE',
+    'dsa_2048', ["loose"]
+], [
+    'ssh-dss AAAAB3NzaC1kc3MAAAGBALJx5S6+ZFUpFMjehnCX4QpR2WKwe5Or2+ZYH2U3K4wCalJiX4vujhBg1UZ5CTvy3xg7T2vTHaXOco/jss7xewCGyz4ULA8VHWmVp+3bt81wQsBDg3GwPwFpqwrQEmBtkJ43crCKR+hw1f2lae6hgvqlrxYVaPJ3YWCeGHxYWrZZihR1UCx3YE0Y7DiTzzN9gmbk8l59V756tb0novFJ11ZILzzAAzRw8Eg1KDnzhZ89pw4TWgkR/I3TwxbvZz1tFY74VEYthvwvETxMYxjJ0FW4GqC8o836n4K46qz1Mw8doeFbXRaXMMmWc9a6Kvni/sPQ2JbAR6aTFoHziSj2EoIFvWUBYBR5KA8rhrPnTdmsvAD2p72C3lh8qHX6V/4A6wISKrSJ0iqpUoeX1OK4GbtPraKOYV7EBy6rH0u1lxZi0k+Y/TaxwUpickJ+0Polw4GEg8eaJfkZmY2+e1Hey7Edl9EaieTZMJEREO+4vVW/YZogB7Oz31M50oDYMf3AyQAAABUAvSFaC0HW+kypTW2d57SBGw9+7OkAAAGAN1tD6eCTYGak+eWzYAICbbD9YYITJL3Gz1NKeTyJtDw/48tNm14aFwvTVq6y8muMuvFsAUprBr9CIvp0vo8NaD/WcOaxBbjVpzRGkMfMOzv9KnK4K5uC0HasFXobhq9KtXcs1GTXGcbRxkL37knzFdJ3yICIP8L+CbzA8VUTLiljVIFwGSeSGgL+Tt+SRjfNEB0XN8wQHfdQgAiUbkF/+Vwxm0rOpkWRuVCtRqqc3xPPg2RidIC1juenpbfQwJLw/Tt8fXxwNj6VP7yWt7QvKSllP5HT4W3KQeC9s9GyUt1jh5+imXiwY5dXlAfB6gziKbjWedv90+2PdvhFJAO9hoCC3l+Yrh0UBI0rUaLCnk4f8yD7CA2w1qD4fn9BIjj6SrQvudz24Np2AX13nyLa8oVrQWo+nWhQxw9Q0o0UAEsseE7VPXlXSw9vQAkwyat7dwwuBN7Hf3339UUaTA7T6SRgXwDIGEWeYOITRiSw+RU/IOy3c3h5dSvgtNE6kHHYAAABgQCGDxW3YFWhofXJ53Z9QWKgyRIJRi7reeOHASw4L0pG5a7WJ3EL2dwCVn2eJXsxuRNJ17oJqM9U/Gmz5tdZ6QIolH85DE3SzI/OrKRnC9j12ECqDigdg/FWXOOEY/2swJXGdbM97KQ7aKo37EodlF6j0wQvHRArouraCLAQCUoEDcVaC3mQ2JIcg+/qdc7tXV489jiMDf/3adNgoKb33p7YeQNUjO6Y4S2x1h4jqm7KLkEZRRcxt9PqIasj6Lw5X6160yM56zZfnVexLfzU4x+IwI1rYbEQIaRlYOn8JjqTWY6ntGr/kSQQ63CF0rYT2cQSw+MisIID3GVkdgta6WG8sh60jh9ZXCFivI8m8JNAVwLhxMDKvo8vVnT2F1V3Ht0TdnCOwHxztU3n8VYaLytg30L1HVmSSx8mKhDCH7BvsACCQbVYu8M6Pb50gKdGJcc1stSIeZDjOEXyt48TLjIH6Kz8uzjiP7Fvqn4OWDAR8YPvzErk+/QEguWV4VQ43k8=',
+    3072, 'MD5:44:dd:3c:df:ef:39:09:b8:cb:5f:31:59:ad:70:56:24', 'SHA256:sgF5bepZnGBURoJcg+ON18F1LwvAmnUYlHoJUgYZVKs',
+    'dsa_3072', ["loose"]
+], [
+    'ssh-rsa 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 ojarva@ojar-laptop.local',
+    16383, 'MD5:b6:ff:d9:90:61:a7:73:77:49:cc:b1:41:ca:c1:3b:a5', 'SHA256:BhGf0v8ER/5mRKFhfuwYXG7iXnRYQsYbPd+2HV+x45A', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_16383', ["strict", "loose"]
+], [
+    'ssh-rsa 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 ojarva@ojar-laptop.local',
+    16384, 'MD5:0e:e0:bd:c7:2d:1f:69:49:94:44:91:f1:19:fd:35:f3', 'SHA256:Vtcs0O8BR234Gy/i/9jwZpT5/topRSHphHWg+HvEmP8', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_16384', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQCxO38tKAJXIs9ivPxt7AYdfybgtAR1ow3Qkb9GPQ6wkFHQqcFDe6faKCxH6iDRteo4D8L8BxwzN42uZSB0nfmjkIxFTcEU3mFSXEbWByg78aoddMrAAjatyrhH1pON6P0= ojarva@ojar-laptop.local',
+    768, 'MD5:56:84:1e:90:08:3b:60:c7:29:70:5f:5e:25:a6:3b:86', 'SHA256:xk3IEJIdIoR9MmSRXTP98rjDdZocmXJje/28ohMQEwM', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_768', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQbdtLTII+vP98NSDlK2LXxVARELRYO0NODFYQ0imYxsmBMB7BrfljFppLJyjU6cziOT6YFj6rVd8MmCogdCR32u63EV11uT6RCFfJMQJtIi+B1JJipTxLzURsiUOOgAHJc= ojarva@ojar-laptop.local',
+    771, 'MD5:29:01:ab:68:09:69:02:57:86:ea:f2:76:4b:2f:ef:f8', 'SHA256:qGHEQTrH8gXZx/NXyyLKluovmx4rptCkt24l3ie7hv0', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_771', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYgpPyLrc+NDQJjf4B1jVA/eTaOzpDqmjM/oFKQEq+HeSFxqFS3Fe7kLIfvdClVyYshg3qz1OfH+mCkcqLX5CPhdZZZbDxAbowAfPmBF77qeQqOsqNhIO0tQ6NX00PNmp5sLL ojarva@ojar-laptop.local',
+    780, 'MD5:86:0a:3f:a5:aa:3b:c1:6c:50:86:dd:4c:86:d9:6f:18', 'SHA256:WVfqr5XIE3Z0Fyk/8MOnhqYVteUhCtbe4rTa9/f7ap8', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_780', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYnE55Aie+1J73DhvqOgyOf+hRMRI9+qoCRhIX6/xGijmrWBKhax0CKQ/E4HDyoviUbd/Q4jPNnpjA9lJWLDh23auSUPQMl4xBuUxzaJh1G+HFYJH0HA9/ONFb6oQd0J8StuJ ojarva@ojar-laptop.local',
+    783, 'MD5:b6:6f:95:a1:f2:e4:de:ac:9d:22:e9:70:40:80:3d:22', 'SHA256:C4yjTC1xaMy/tgkfcp+Y1FtXlHFDEUFejUXjpXSyPNo', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_783', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYwNgeGM0y1gmTC5yGLpiL2TF56l+ynG+9OcoonNsXt/mnAOpH7KbVnA7utELLidfS6oenKBWMJlbMmMeM+/7mEcKoF0TUAtdaJvtawLmUKHdAZNv0qZhrKN0L/OZAvkn5u2urw== ojarva@ojar-laptop.local',
+    786, 'MD5:d2:e4:db:9f:c1:3f:7f:ab:09:a8:ef:b8:0d:0e:4c:e9', 'SHA256:jkb3hdIXdSv4HqPTQZpTTpR8Vjm3IAc+3hGVrVLHZP8', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_786', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYx1UtgIDIf1tpk4ro2r7ethUFwrL94KhffPD6E0Z5U5dC8ZCjblTauZSmhztVYMh/8nhU/ArP/zy208d32mMxTklxnx/tFulwtDXaH13A8EdCNdBzUG+wQ75O0kQVUMpp/rVnQ== ojarva@ojar-laptop.local',
+    789, 'MD5:ef:32:28:eb:3f:2a:a1:bf:34:d1:26:bd:8c:6f:c0:c2', 'SHA256:DOgGb/62Z0oh0pJ0PRqaf6zKfSje2l03cTctBTP7QAo', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_789', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAZADu5iFbDQWHggy7d1kKkc6RVkNkiRjOwT1dbghPz1lWX3HK/iGFoMySTB1iviwoufHNAPS75WJeC1nfZBEkrIW16SrwsfLtuKMwjz+8Sb2ENtC7tyLB8IG77/ewRDEwOGiu8pc= ojarva@ojar-laptop.local',
+    792, 'MD5:b1:aa:90:f3:76:8b:46:a9:0e:3b:e7:e6:1f:dd:30:e8', 'SHA256:s42+72Sm52ztIABQzcbcl4Msk0t8W8p3H2f1jBBVgh8', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_792', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAZQ8rZh7qsWG7dcZ+Gs6yg0AAJyjJhkzYG4qmG5HkS6im0D5H1jk9FZCAdZpJdQc8oBUGBDRe1xtorY4GsxS+Bdk5BoiGMwr7yWKjFy0Ert6MUG7QUAknM3nLZKWm4MZvPRToHGjr ojarva@ojar-laptop.local',
+    804, 'MD5:22:09:eb:fe:94:a5:3d:58:b0:23:ea:42:0b:a2:3b:6c', 'SHA256:xV3QfhZ125TV0CV3C9xn9010X7YscSyMWWHSB1aSlQI', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_804', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAZW0CyFwCSXjZ/FJ1RuqkgBeLgTBJ3hk/OTn0pI8g9cr9r5EFlYT8/ZXd1ilP5rSknba1g9FudG8eCH7Ah+cnbFbzPJNH6Aofga9hh4fewKo+KI0S65H+XgBJsp+xEZnLPCIqhzkF ojarva@ojar-laptop.local',
+    807, 'MD5:28:ce:cf:1c:54:2d:c2:26:d6:b4:9c:7a:9f:fa:d8:1a', 'SHA256:v8A6fhyXzQQiRlkwrX5LTFJoaMhh0X+523RInq7l8Mw', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_807', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAZgKVmEp6e8BmGxLrfBE+bzMog35mZ70vTurSwKZ+PE2eo4/h2xLXC0/O6tFItgukF2oG75Hkx0CrLwbSBYeaYVtYCp7dWiDQpS8Ribq5zRHl0tz+9DBioHSIAkNJ6Xesy6y+5oZHiQ== ojarva@ojar-laptop.local',
+    810, 'MD5:d1:21:8b:4d:84:6b:cd:8c:4e:d8:b5:92:ef:75:76:d0', 'SHA256:KcC8EQgBniHrxHF0zJXCDELzj0sAy8ouJBodfrsPtMM', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_810', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAZhnHxufkUNVz7fITzsow1EFbxdCH7GB8BaT5fUESJD3TYKaCbHefxrDU6UYAgaEKnXVmd5tE3D2qZ8Z33ECEuQHHIoSicB5VIG+zNwOLve8/ftFjippwnSe89g/1Lu/qXVzsGCCvTw== ojarva@ojar-laptop.local',
+    813, 'MD5:7e:9a:26:2b:77:54:d1:24:54:a7:e7:05:41:be:bb:7e', 'SHA256:JIXIk1tvKi1FV2X8XZ+Vo4/04dkTHTPUx1iSuQQ7cGg', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_813', ["loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAowYV74xpHjU/esNFWOAZvh3JiHlPgmeIFPBeKiZsP2OS/yxulMs/MbM6Cc0Q0GFhF3ycNu6rsjQHuoLbFxcrRA4reBDU+BFA9YeG9ptdpBW2rjl+/MjPML2cmIiF9VOuwia8WWLH/gro/AECoEiAbKUJcbD8PdGfZpb/QZyGl+5WpoKW3OD9PTDJmI6to2lp+NNx2bvV08sb2z8zVJXLgBrQ0Vc= ojarva@ojar-laptop.local',
+    1299, 'MD5:40:fa:26:65:60:fd:62:ee:03:70:bf:db:15:53:78:bf', 'SHA256:9tZeGLlPhxkDeWea/HjYWdJEmTaVXr2inEDG+8CthwQ', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1299', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAoyx+ox9qPgBMrRireysGh3SOuMj9rPXgPIgTRCH4YgHJavaIKNE3l+FPYT2r4ri2Ej5kIN351muDMaaiT8dqWWcOSoFFNPv1DZ75iVBBvQBhAgP2kllbzI4/e0qqc0BGBW2c19rTIQK2uSfFCTcVaIJQooM6knKYUPWNUJWc4C+/NYD7hRp9s1MXgMO6F1ajJKD+z51zoFXcMZKb3yODguWSU90= ojarva@ojar-laptop.local',
+    1302, 'MD5:96:b3:a5:61:3d:8d:86:2b:ee:94:dd:e8:e3:6a:26:03', 'SHA256:eADVvWSOiujFPIGqryg9kLypum3EJTzeyFmeKDwrsV0', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1302', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAApAGFxZYSi3pcajPO4+bBOc0lKv9NzuIB2CcY8HdZEQe0QGbbu/saDgFuMLirBlZrkldSRdFgCVpTVScxbABvX0Cx7sPNwPag8QTsgI/phQivCGx2U7/2jsJDcfCj1uHGnTKWh8b4wNto0lpaeo0aSMZfymgjDEkgxpWBhJMgkWwlOP3hWSXl43mO0bcfHoyuDHccbmwztExuQ2ImpkJaDOVrom9f ojarva@ojar-laptop.local',
+    1305, 'MD5:12:a1:ab:e8:fc:ca:e1:21:a7:06:86:e7:7a:fd:10:ca', 'SHA256:YnEsK89NlP8RuI2ZmN1ucblm+iEGjpxYA8X144JYq7A', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1305', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAApAxM2gGIaiwCkuzBjFsmgh0GEmwmf/5+dxm9HWz2PUsG8utJN1mCyLWkuWhwBiOnttvKIvfKbmr8KAIvwGUOQyMjE8Xi2JuMl4Vc3HvVGbeNQXhwgyXsE7ykjHZioddaOwv87j+SzDlP1As2hq9VOtTByIrqo7Qn/OCDJI0z6fBhtbtjFTjdBB7ViSfKw8TEgexSyIPxTe74RQjmalA9UEXyUHlx ojarva@ojar-laptop.local',
+    1308, 'MD5:ef:51:09:9b:4e:b5:3a:15:05:19:15:68:66:c3:bb:16', 'SHA256:tXiRkvNuTa6kstauAzTGXss/Wv0Gu4o2tuSvF7K2KPQ', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1308', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAApFgBPZxYXC1JXtkOO6irCMCmoz+jzWg5GLqd0V2rZApdQ16JrsX/DTO9V5NTCiLQbN1UqW8EuJXLKNyzZefh9EdzwciOzIPIyFqPsklNKWhWeX311jMUmbCS7M9+Pxi/wQ3FG2uxycb8ZX8THI7T5L1QvyJivxGPxZAQXpVZvD9j0zalCyVdkFDRJCE3jkK2jGyu2RFZT6NZEo9qpqo8H7f1L6q5 ojarva@ojar-laptop.local',
+    1311, 'MD5:fb:ff:40:35:e5:78:e9:03:f8:d2:c1:71:39:82:3b:fc', 'SHA256:n8Q3oAYssCmpIDhio43bp/PCXqN2wGO9ZKHfo+n+frY', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1311', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAApQOZtuX6wLBkB2f9hm4iCbJwhteR1+o3+dfxb5lWE8f3GOld2b/up8vd+GLMM6kHhkfUhpPNdJ0PfSu8L/p51MPq0PfrD1IhO9u7d/U4Tebyy6UzRPsPo6j38cU7rcIqHZwDiGCon9VO4x3WF58l2WJ0P/UcnLYVjC/jXioQBF1la7IPs3H4g++jy/9oQNn4/NH8/Lk5oTUF9aHOtsauCxrqzGGCQQ== ojarva@ojar-laptop.local',
+    1314, 'MD5:7b:49:e3:c5:53:89:b5:30:5f:0a:f0:5f:12:9d:92:95', 'SHA256:xkyPhi5uP1YUo2Kolm/xlB7zGlrWXDtQnGyH1IlYgsI', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1314', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAApRS5H4cONMXNAgn+CmPJXaTyZI+R9jai89ATYSUuBJVVI5MOVBoRTYzZISi/nMDdsH0D14zlOsmc+5+aHCAkFlBOSag23xHj3gfPsLcs6AjX/irvhjBoj7bOSI1Tzxggc+S1sOd4WmZo9jLpxXQ0H1Md7ic5rFg/oU2qA8TuCm1jBUpviTL3xM/fNraLnIUcPWG8o4LJL71YZc6quWXjNEmK7u0kYQ== ojarva@ojar-laptop.local',
+    1317, 'MD5:41:6d:91:da:82:7f:b3:5b:e3:b1:6d:4a:23:8e:7d:b7', 'SHA256:jjKRQVNrjrtK3SG/ReEZFm0C0wgiCVajifnhOqVJXjM', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1317', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAApgDURQ01EZNnjdCKce3/28LbXfLwQtaS+k7TK/jRikonejiiN7MXaayqahhNry/Edzf2/WJSOnBbBdhgLxhBgPJy8Yk/koaD6DmjnJ0Hrl+s1RBUAGsW2Da9/b9VIYkPbPJ6UwiTDB1SPF6jINqW7mLvOxt9onJwz95uct1udwk8XHp709vv6bRn5xpq26BukOvBxhu3KX8h68txqSDFmH6haEzjXoU= ojarva@ojar-laptop.local',
+    1320, 'MD5:27:33:d2:ae:58:fc:b8:4f:41:36:de:24:ba:2d:3f:c9', 'SHA256:TnAmMC+F+CCknV3lspZFoEt6NubiQZBnBsr/R44y9qM', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1320', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAApgYP1GJHBP+AnJiU4AQITNotMWbxM41bTVwrYC4UAWmgm/v8F8U5R+HHWcwyPahNt7vVJ4fw8MshVLNVcGf598F1vEJuKvKMuPQjetJcGxfSA/g5by/aPIdzstUUp8afsFOyEJOAf23pdw5k6QmyPPbAg8/zGoZkZ3lbnnr9gAOK5iSuwW4Zju/LTPDuu89cBrvlFr05xpxVArh6H0gRo18T2xjz/z8= ojarva@ojar-laptop.local',
+    1323, 'MD5:c1:82:87:db:76:e4:2b:b1:b0:7a:c3:a2:a4:da:75:45', 'SHA256:0cHaIqfy8Wg++td+HlYJqg0PERTk/uJ4JLP7Vmh0yhk', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1323', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAApic5f0WgrxUGHUSG1he6A6CVjBbjWrckrMliNhHo5m38Q+TmALI+4ktbtDG61Y58SGVXaBvFnlkba6PsBfq0dudJn6zhcWohOCX2jwJAdUOhPuVfL6e4fNLfJmnyeIGS9vtXSkk/PYXshkEPq/UerOlpAS+jxZnXPZnnpIHrX/NvMarLKLA/f6uaDfF3jIl7TxT4I1Bhn9KtlBZOzrC2sTsnnkcWiVE= ojarva@ojar-laptop.local',
+    1326, 'MD5:f9:3d:7a:eb:a8:b5:0b:f3:f1:1d:c0:fa:3e:c2:0e:8e', 'SHA256:/Uf6IdQVVpSnmRBmxu9ZrZppUb5T7QOTFwbyCrMCFFA', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1326', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAApwGHoGv4qz/U0A5j/wuDQzq9GtQEQv6Z0cs03/cBb8JLmj+xnZIlM7dgzvxfSmutjR0m5E+rbUuRYNoYpeVZtaD8r5h3Dj2bvWnmf2U0vReHZhH9juEdOrVDuZtXU4SkRo1P3f5HuVeo6D5U1gkSg2YUpYpGE3Y+nhEWmiZrBcns8Yw1z72rvaeCjRwzyZgSpyVRQOXygmiOP/3GIfb8zNChd3qWJtlP ojarva@ojar-laptop.local',
+    1329, 'MD5:89:2c:f6:06:f8:5e:f3:bb:cd:28:33:4b:0a:6d:10:ed', 'SHA256:7Iovw7UeQ/f6k7P2bpxIloEXg8ifRKfySBezSIyHR44', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1329', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAApwraDBOJz0St0svlhB7cN7Cy67vH5/X9jvyMMIeHH/zNAR89TyWRLWkARidtqOIqgyPzRj2nCSm5ISu2T+/DHNZcP0shhcRoKLh52otz+gJatyvsYL1w4ZW6P1h8U6Faf2DbxsUcfIYVx3K2O4V1m/8+aDQjFIW4a0bARU9liu3Z1LB9f6NwS6ZEcHb8dlo+3lsnkjVFR6Xl1zzs86pPBGJRA0HYf2yB ojarva@ojar-laptop.local',
+    1332, 'MD5:16:69:3d:b8:cd:a0:78:8d:7b:0b:0e:99:24:c1:d1:4e', 'SHA256:UCnT7bzZo+SeYX2lHxD09vSmCAhUTcdErwwnlCwwRO8', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1332', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAygXJwDBDbv4+4J+zx90C9wUmXaXKiCvQf4LG08Rp6NXjWPCGFEclp3MP1apbEVzrSYwEFHFtEODwAdT6SdZWzrOu0pi/ee4E+5oBNoxsRq7Ggk7q/YH7I/rPv/av3nz3M7he6AC1Urn9iDtgg2kRrG93iD5bBngq9mBa2XRWykF3LfSIR6UcCWlhvNMlhQ6HX+h5jwe2Ali+zCArVYK4OwIDDRRN1vQpFa41wnadwz7jYRtUU6rb0HOpknzVVLLEMA9hesdv7IfmA/k= ojarva@ojar-laptop.local',
+    1611, 'MD5:ff:ac:71:02:fe:38:a0:c8:58:4c:06:6d:cc:ee:e7:0d', 'SHA256:q4rb9bst+6DMDhB6HQy4ftbzEdC/h/Y14SyUNGSrErE', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_1611', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA/Bg4DNQh1RFnvgCi0Q3vCrUYBB6oZufUK7AXrtFRD+8n/QRvQnQPE59tQHlQ8FvLbVq/uqj/HzO9iRWlqP05/GB4byZWwk1vDfGFqOL/5rTUdcdokRcy2zzGIWWzbhUbnoKNWpr7f/nRBzTvvcUVlAJTTITjd+87cb/Gr74GQIhM7Ao7tv7qE+qVtCWj9G4i4ojmfAMoWIGMRRbAkr7MdnAIV7UVwC8AN/gz8zIYhutHX3p9SxWy5V0UgQjVwJh5Vb72pndUmJXmjUyzuZXqxAOFtfXge0WwCMRd/bDcBPILaa33KxlHc48IpS351pVekaS1KsheVBzus00S6w== ojarva@ojar-laptop.local',
+    2013, 'MD5:a8:9c:d3:a5:97:65:61:39:a8:98:e6:59:bc:f8:f2:06', 'SHA256:kPydMF7eCNCsWKMIOQiJDWh8Yap06WPNFPY6IyUBTOw', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2013', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA/QD1WMI5FCXEgGSYPVJkDexjZMU9OqokStDg8LL5guY+b9EECEJ4xWMnGFC8CbyMDHmUQiYRpbh8bUzU8uLt0wLrEn15yc5R3F3BCX1kdjlKcLpoQryHvL2aJNNv02atgJ2os9QSsY8O6yOoPlSC/vmGurHPrtoL7sRVUPcHtPU5QlqvkbdFAm0dQ0BrGE6SH9Ia7cv3f9ky0WexFrdmxTiMK8gT1ZkhIlM2iQVct/pz1R4VL+GXU2ia5CHpl8Ag4NrIw+O0Y1VfakOtXMfr2RhbS8DZDKvVaJVveoqv9LQe8Nq+uPu0A+KY1KVHbZyvlSsoH7NKkbF4SRYzK9U= ojarva@ojar-laptop.local',
+    2016, 'MD5:e2:33:6d:69:a8:4e:fd:52:15:7a:6b:a9:8a:3e:63:00', 'SHA256:7uPBXfA+aDmi5xH+EgAMkjq9qgwmmSUsrdn6VQT8ETc', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2016', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA/QYQGpPpfnSgFbyZx3klNz4FyTCdDY7bq1fwRsP7wrg7yfX7IimAdDcTcoVyd6JEaYqlNCtK9ClTwSmuVVpmS6p/834DQtzOhvxs7u3cti4buYX7mLfnmAfLI80eeFGXGr1K2owsFEHbEAJTG007BvcezM4V7l54iniTGCoxrvbHrp3Puc46gmGEo6J2bDDYXKD9xmuVL0XrUYqvR34fVswMABSlNN9ROdxCI5jxKhuOrL0sZg/faf+973CfJWPfFGPkOaINSpUgBDKVTRwWL86IjIEnDdiIyNAxAnbZOyGAMO0+0iyWOBso7QxFt7UoYi/C803I1BCGbXqCAGs= ojarva@ojar-laptop.local',
+    2019, 'MD5:e4:a5:13:0a:bb:06:02:34:68:1d:2a:69:6e:b2:82:0d', 'SHA256:LNEo4ZwfuV8PBD9HQeVQ4IREh7AQS1P4Q1Um9kVHHR0', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2019', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA/TDTpJy8OjtlM9F+UClxMF4XFN/LRh63c2JgBVquLm9pevlsRRsN3MUk+N5b6hDcluKYOI5loOyXTuPkuGYdxowuTOkS3sdp7zZAhkeRW/g8ChnOeiNWkGwR6vCbJh2Kbhvn3QG/fZgG5E0hRfqn8hfShNsWZeH5m7eiurwL30a7Mx+m9OsdEEea91wQckGAskA7nz2nLzEL5J7eVK4c+gMKsyLDB8R9w1oYsbsUPfbv+7tDNwg+Ur03nXJ231oHog3LLLSixvC24272ZJ14v8DFQnDcDzQDrrmoXdkRNrMsXIGaf/J9VFk49oJ7NHJzGvhNUeuGwuhrx7bs2aU= ojarva@ojar-laptop.local',
+    2022, 'MD5:20:94:06:c0:3a:81:02:c1:bf:39:a8:1c:07:4d:db:3c', 'SHA256:RErqVMXsmCfn6UCJ2zI057GuGGQpCB/gbxQ1C1VSOKM', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2022', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA/gFaVjuZJF8V5h/F3aJ/fs2MINAuoJH+VfqJb1rhsXljXV0XOEyHo7XyiZX7KVQ2AFB7ZWmtVjDu5wGgU6zKfvfoytbPPlYwaGf7RikRGdCWvsJnwB9PChAV9WsDqe4NODzaFIv/tiAUsy5CChkESIJeNLK2K/KQtEWSmu57hsr8terigCufSYt2YjKcKErIbRNVwu2SqfHSjPKRXzmjTbDpUpvCY3nU3kWJmhsZHPNz5J8z7xV5NSJPgjWMToKi+st9XJI/t7zYWrdwx4DCEjvKdGBKf3BklYrqx1c+vWhwclNyUd+zquGmhUTvsReI0A0e1o5mPM/n/uU0fyJ/ ojarva@ojar-laptop.local',
+    2025, 'MD5:60:95:d4:ec:69:ff:a6:1d:c7:dc:fa:fc:9c:45:b1:23', 'SHA256:A7YUPfEYKalQgeT4Xga1Xz+K4J3hSoBFtCmKSlvQCuw', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2025', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA/g1KS2Amcx2dKUY/AaDl+S9Nl5T8fqinfhurFuom2GAzcq30DtqAK5FVHXCKiYH9l4v+GDe7fi5nYX7teajgThPLUUPd0KSUa2xFcMZqDVOzv5jnB9lFVPZiQmRh4uP0dycxwtdYYGsOjkbriKfpTD/nlqzNPtaGInFRzGRPsaHSr2qYI8IHugG/A3SDxaJiNsNH4dg2QKQK0q4OxIn+tsFuiVJCessDpoKS0C4NzZYxKvsc0+2Ke7Qk1yXFDCyDlAagNGkjQLldsVWavdffv9u71ZnWi1jqyMEmG0nbtHJLasaiS+JKppN3drgxD5eheuhewJjMDzC3iBRRmhin ojarva@ojar-laptop.local',
+    2028, 'MD5:46:6d:20:95:d9:ba:4f:73:2b:dc:16:ae:c6:50:68:33', 'SHA256:IfjPLNMwVfbMen1BcAA/7wbwtZR5vQC9r9kfVO0RlXA', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2028', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA/mNcgBv75NCxkdwWznRWS9j4lBiE3kt+u/CmQl2UxEyDm6C5w42WCG6iHObmrOisUOC+FA7GqcanPw5FBPiXNGNFdPbFmOiHplkE6fe9LZeWSZWxseZKc0ShjQZ1MaUWDZeSlFoy1s71PO84eFFpn7yE6wt/KlhEoCIpdXai2wpJdTVp7gOQ4xYNRVYScWdj8nfAHM9mj7YM0AGymEI3nU4yDokAzktWDp/Y5u64+l0bTu4irA/NIP8ctBkDVZMwOyRbIcJkWYlGnJnyxR4JOefR8GhOH0z/YIE42KqJoHHL299JMFOT7HaBBm7YHFoq/KtKUZrSKlHTCLRfiA59 ojarva@ojar-laptop.local',
+    2031, 'MD5:6e:7c:f6:0b:e3:6e:2d:a7:e1:e9:4c:68:d3:89:ba:d6', 'SHA256:H3wLc55YJucBCWszMtadHVAzxbwaWMP9QZr0mpdsNvg', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2031', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA/wPaxCp9EthdCMUBIZMPfmpk4UHQV5IENsAagu6krzafIWJNpH1tdZGLJ7KWCS9tzXYLuPux2ZbHkDpAc6zXPY722WtWZsV81t/+WPdQcxoY0/nCPR6CK6XUgzYyrZbZvwu2yx5u20aSLsrDYunKmkZkz11rjBSQPrL9SikanpaDHibzlpTPa/Xvb8Mv9ty15dYWlP/Kwgo1VN+xXai2BchwQ/rGdhhc5nEotRxFByc9onkJJA3jQrtzKw6PYmkAYcX5yftPfUkcgC3qaFP4FR8zIcZICgoJKClaevimv6Om1lkAKaOJbYxkFtKciuufF2Uw61t1FiAanbKc+5U0sw== ojarva@ojar-laptop.local',
+    2034, 'MD5:dd:49:3c:ba:e5:dc:e2:f1:ef:ed:80:c5:0a:ed:7f:aa', 'SHA256:5nXxxQLKjqIWDRTv9iBVYQ3NVKmqQ1Hnql8tTU9D/vs', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2034', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAA/xW3UoBjiOoneRlPJn2vCyg8iUJqTx5JSUJcrbpr5xcUXVUykVDMI7VnPqsQbX0PUwU47z2Qp7KBUfslSh6CkBOLZRxxHGf/EAj2Or86K4ZxJJx3T/Zrq7yzThAGOOKq+QzTBmsfQTCdgy4XDs0Axcpbohk6lIhscq86Lc4V2hL/JJUdlmt3NxfeBuoq+7jD/HLV2VFRs62pBJQCePM/9m4rWPApbfdNlq7V03ncFx1hsVWMcmBrlLUxgW+ku8bt74kyZnNcWYflOkxMH8IsZH73xkpF5E5uHtnxClZ2rrzrBWDyHco7wGJNrG/cTKPOASn3VoomdBAJ+ea24lGlkw== ojarva@ojar-laptop.local',
+    2037, 'MD5:2f:71:47:7f:51:99:97:b7:00:74:76:43:35:a6:9e:5d', 'SHA256:JoMtS5x26nKfL4RdhePhMAQApmWpqjqu/2zPou1VWN8', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2037', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAAC8AOpsr/bye5kOvXynQanwbDwusCLkFA1B/UmYVpB4lGlp7p/RKcOZ9uiwsnPP0JQ7OrZ5O+oDIW2WdHPfjfzlGCyoMuL3+PwHzqB+L8A8/9hRXLJAulufUvi/vFRfxUc05q/BWwGE6RsIzadvpdm9XtdXoG9eElpn7J+k4WE+5V9rR2c7TzoOt5TP/4emAwcHAxQIaIygijdHISS3CYIAWmIM33U5HbEbQBRrAE6I6y0gQxvhHCEat0c5RJ/zSqXJpplAtE7n0DUqC9kmnJsDAB9Cq7hxiRrttrMvl1ERoK0XW3wWwqi6mvVv3HHOfVj1lxLEwpeLEHRTQdS5sy0= ojarva@ojar-laptop.local',
+    2040, 'MD5:99:6b:1d:c1:2b:d3:83:63:4e:a1:ea:51:c6:4e:25:17', 'SHA256:SMP5WahEoW2wx/b5C5mTVdVvvz5WiSOarVdWDZguRe8', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2040', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAAXo4IUS1bJYWrydi8B+t68xzH97cpUcKEWgWqQvy6ebRw/Y/G5kHVOHD9vGBLX2j4dseB+71meNxeaTkQCDPmck4FFFe8LlfJgcJupAwVnEu/YSne55MHa9fO1hiZsg/oiZabS/DKoyOHLE7Usa/JQXJzGaRtLWAP1vWuCigfX/yfLA+CXxA6Fh6VVaEhlUAdOoVZ/aFBrwsG19Yp5sU23HSIHAmkFMApb5jvlQbjQrLzQr9qmiRgsylFPi5OHp2tvbQeRKA9XzKVjpof4tSd0JDq5XgUHtlRI9CsIrVxjUJS8WkdDWW/uNWFQhQ5CS332Jvet9xP6ZZpsYxS5KpQU= ojarva@ojar-laptop.local',
+    2043, 'MD5:af:82:da:e7:04:5d:a0:38:30:b4:5f:ae:e2:87:63:f2', 'SHA256:p+DmMctQW7COEpdHxrGHYc1TMTXUmpUcGnEozR6F4uk', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2043', ["strict", "loose"]
+], [
+    'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABADR9kolU4uiD26LMrbakQlNf4QWB2xrdY3nASf6CJdQYzTMjNmbt6sJ4A4pGnCupFrzL04EYDvbVmT4GEZm6CU4BsY61yosnpGSqqcVCdw5xW1k4bCSDPW75WHLCVmYyROhZ+yyo8uAcIy5UIyBZXF/PO7taJrrIi5RwdqIPwtCrJ3dJkcFWa3qZWJykLAFQD5A/lta/egS/u/nyCap2e16WGnvSluz9CyYtGFNS9axzOwHxLFEv2ocOsJjYgzV+Jfpiao94A4VzLKbUDHlfV57KS0tJaT8FKKsg34vN3bsD0zUftLUPpUFgJfMwje0C2rCJkCzwgya2vxLqj2fg0Q0= ojarva@ojar-laptop.local',
+    2046, 'MD5:27:24:34:50:5b:39:2d:34:f9:60:d5:4e:7a:c7:11:51', 'SHA256:CTHLYlbVhVDoxwvSTkRAvp512KgFbfWP1KKov9/GofY', None,
+    'ojarva@ojar-laptop.local', 'valid_rsa_2046', ["strict", "loose"]
+], [
+    'from="*.sales.example.net,!pc.sales.example.net" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABADR9kolU4uiD26LMrbakQlNf4QWB2xrdY3nASf6CJdQYzTMjNmbt6sJ4A4pGnCupFrzL04EYDvbVmT4GEZm6CU4BsY61yosnpGSqqcVCdw5xW1k4bCSDPW75WHLCVmYyROhZ+yyo8uAcIy5UIyBZXF/PO7taJrrIi5RwdqIPwtCrJ3dJkcFWa3qZWJykLAFQD5A/lta/egS/u/nyCap2e16WGnvSluz9CyYtGFNS9axzOwHxLFEv2ocOsJjYgzV+Jfpiao94A4VzLKbUDHlfV57KS0tJaT8FKKsg34vN3bsD0zUftLUPpUFgJfMwje0C2rCJkCzwgya2vxLqj2fg0Q0= ojarva@ojar-laptop.local',
+    2046, 'MD5:27:24:34:50:5b:39:2d:34:f9:60:d5:4e:7a:c7:11:51', 'SHA256:CTHLYlbVhVDoxwvSTkRAvp512KgFbfWP1KKov9/GofY',
+    'from="*.sales.example.net,!pc.sales.example.net"', 'ojarva@ojar-laptop.local', 'valid_rsa_2046_with_options_1',
+    ["strict", "loose"]
+], [
+    'command="dump /home",no-pty,no-port-forwarding ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABADR9kolU4uiD26LMrbakQlNf4QWB2xrdY3nASf6CJdQYzTMjNmbt6sJ4A4pGnCupFrzL04EYDvbVmT4GEZm6CU4BsY61yosnpGSqqcVCdw5xW1k4bCSDPW75WHLCVmYyROhZ+yyo8uAcIy5UIyBZXF/PO7taJrrIi5RwdqIPwtCrJ3dJkcFWa3qZWJykLAFQD5A/lta/egS/u/nyCap2e16WGnvSluz9CyYtGFNS9axzOwHxLFEv2ocOsJjYgzV+Jfpiao94A4VzLKbUDHlfV57KS0tJaT8FKKsg34vN3bsD0zUftLUPpUFgJfMwje0C2rCJkCzwgya2vxLqj2fg0Q0= ojarva@ojar-laptop.local',
+    2046, 'MD5:27:24:34:50:5b:39:2d:34:f9:60:d5:4e:7a:c7:11:51', 'SHA256:CTHLYlbVhVDoxwvSTkRAvp512KgFbfWP1KKov9/GofY',
+    'command="dump /home",no-pty,no-port-forwarding', 'ojarva@ojar-laptop.local', 'valid_rsa_2046_with_options_2',
+    ["strict", "loose"]
+], [
+    'restrict,pty ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABADR9kolU4uiD26LMrbakQlNf4QWB2xrdY3nASf6CJdQYzTMjNmbt6sJ4A4pGnCupFrzL04EYDvbVmT4GEZm6CU4BsY61yosnpGSqqcVCdw5xW1k4bCSDPW75WHLCVmYyROhZ+yyo8uAcIy5UIyBZXF/PO7taJrrIi5RwdqIPwtCrJ3dJkcFWa3qZWJykLAFQD5A/lta/egS/u/nyCap2e16WGnvSluz9CyYtGFNS9axzOwHxLFEv2ocOsJjYgzV+Jfpiao94A4VzLKbUDHlfV57KS0tJaT8FKKsg34vN3bsD0zUftLUPpUFgJfMwje0C2rCJkCzwgya2vxLqj2fg0Q0= ojarva@ojar-laptop.local',
+    2046, 'MD5:27:24:34:50:5b:39:2d:34:f9:60:d5:4e:7a:c7:11:51', 'SHA256:CTHLYlbVhVDoxwvSTkRAvp512KgFbfWP1KKov9/GofY',
+    'restrict,pty', 'ojarva@ojar-laptop.local', 'valid_rsa_2046_with_options_3', ["strict", "loose"]
+], [
+    'command="echo ssh-rsa asdf" ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABADR9kolU4uiD26LMrbakQlNf4QWB2xrdY3nASf6CJdQYzTMjNmbt6sJ4A4pGnCupFrzL04EYDvbVmT4GEZm6CU4BsY61yosnpGSqqcVCdw5xW1k4bCSDPW75WHLCVmYyROhZ+yyo8uAcIy5UIyBZXF/PO7taJrrIi5RwdqIPwtCrJ3dJkcFWa3qZWJykLAFQD5A/lta/egS/u/nyCap2e16WGnvSluz9CyYtGFNS9axzOwHxLFEv2ocOsJjYgzV+Jfpiao94A4VzLKbUDHlfV57KS0tJaT8FKKsg34vN3bsD0zUftLUPpUFgJfMwje0C2rCJkCzwgya2vxLqj2fg0Q0= ojarva@ojar-laptop.local ssh-rsa key',
+    2046, 'MD5:27:24:34:50:5b:39:2d:34:f9:60:d5:4e:7a:c7:11:51', 'SHA256:CTHLYlbVhVDoxwvSTkRAvp512KgFbfWP1KKov9/GofY',
+    'command="echo ssh-rsa asdf"', 'ojarva@ojar-laptop.local ssh-rsa key', 'valid_rsa_2046_with_options_4',
+    ["strict", "loose"]
+], [
+    'ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBE2gqbAChP2h3fTPx3Jy2KdOJUiBGEiqBUwoosfzllw+KrqmGiDEWlufSxdiSOFuLd4a8PSwhoWbdQRVFrZAvFE= joku@vps91201',
+    256, 'MD5:7a:16:d1:e9:9d:11:45:a7:7e:64:a0:f0:9b:f1:2e:f3', 'SHA256:hgoZTVDLEngUPKCctfIEvdTilxAVj+ixEvYkurvpuKM', None,
+    'joku@vps91201', 'ecdsa_sha2_nistp256_1', ["strict", "loose"]
+], [
+    'ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBCCfGmR4U8uiCQ6atu74i19/R3We8vQzcKpvSw/T54lJhIZov3NNLJNnB+BvOV+HvgIwHHjzC95UwWm+YgEsQdZxT2eZOLvPQNw5lOZ4OKjbRmROxyDnF2BptAS/og+rZg== joku@vps91201',
+    384, 'MD5:19:f6:7e:f9:da:68:88:4a:bf:1d:4b:07:8a:70:65:f7', 'SHA256:VW3Ma39vuI2jngObd2KRAV8H9sLwcjJUV+lA1U2smiI', None,
+    'joku@vps91201', 'ecdsa_sha2_nistp384', ["strict", "loose"]
+], [
+    'ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAF9QpvUneTvt8lu0ePSuzr7iLE9ZMPu2DFTmqh7BVn89IHuQ5dfg9pArxfHZWgu9lMdlOykVx0I6OXkE35A/mFqwwApyiPmiwnojmRnN//pApl6QQFINHzV/PGOSi599F1Y2tHQwcdb44CPOhkUmHtC9wKazSvw/ivbxNjcMzhhHsWGnA== joku@vps91201',
+    521, 'MD5:c2:c0:14:36:ad:f8:7e:f1:b3:7f:ad:f2:cd:2a:30:3f', 'SHA256:BnSGjtQ/Vd4cUi7Nmi379fpN4oShJEB1NPnR1yy6mJs', None,
+    'joku@vps91201', 'ecdsa_sha2_nistp521', ["strict", "loose"]
+], [
+    'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEGODBKRjsFB/1v3pDRGpA6xR+QpOJg9vat0brlbUNDD', 256,
+    'MD5:76:85:77:0d:24:6c:1e:d3:23:c4:29:92:80:f9:fb:94', 'SHA256:uG85B9hYCFenm0DxEo3PRzypYRY3kSa7veE/KbSSau0', 'ed25519_1',
+    ["strict", "loose"]
+], [
+    'command="/bin/ls",no-agent-forwarding,no-user-rc ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEGODBKRjsFB/1v3pDRGpA6xR+QpOJg9vat0brlbUNDD',
+    256, 'MD5:76:85:77:0d:24:6c:1e:d3:23:c4:29:92:80:f9:fb:94', 'SHA256:uG85B9hYCFenm0DxEo3PRzypYRY3kSa7veE/KbSSau0',
+    'command="/bin/ls",no-agent-forwarding,no-user-rc', None, 'ed25519_with_command_1', ["strict", "loose"]
+], [
+    'command="/bin/ls",no-agent-forwarding,no-user-rc ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEGODBKRjsFB/1v3pDRGpA6xR+QpOJg9vat0brlbUNDD random comment for this key',
+    256, 'MD5:76:85:77:0d:24:6c:1e:d3:23:c4:29:92:80:f9:fb:94', 'SHA256:uG85B9hYCFenm0DxEo3PRzypYRY3kSa7veE/KbSSau0',
+    'command="/bin/ls",no-agent-forwarding,no-user-rc', 'random comment for this key', 'ed25519_with_command_2',
+    ["strict", "loose"]
+], [
+    'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIEGODBKRjsFB/1v3pDRGpA6xR+QpOJg9vat0brlbUNDD random comment for this key', 256,
+    'MD5:76:85:77:0d:24:6c:1e:d3:23:c4:29:92:80:f9:fb:94', 'SHA256:uG85B9hYCFenm0DxEo3PRzypYRY3kSa7veE/KbSSau0', None,
+    "random comment for this key", 'ed25519_with_command_3', ["strict", "loose"]
+], [
+    'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIL5x8+1ucT6+AKQIW8u5W/FOuBvWx2fCQlSLkUakry89', 256,
+    'MD5:0c:4e:13:0f:f3:ab:20:58:85:2e:79:9b:0f:2b:43:c8', 'SHA256:2ao9ds3IIkmXiLPRMs/47HIkHIV/qxzEHKW8p9lhRYA', "ed25519_2",
+    ["strict", "loose"]
+], [
+    'sk-ecdsa-sha2-nistp256@openssh.com AAAAInNrLWVjZHNhLXNoYTItbmlzdHAyNTZAb3BlbnNzaC5jb20AAAAIbmlzdHAyNTYAAABBBGdtNJ7nNTVW3kXvrWpvTENCfetzI2yUb8m5WLB2kcOVqF+3orTmloZsQEt1K386hlaqNzm7MVB+xcAiNoqhiI4AAAAEc3NoOg==',
+    256, 'MD5:ea:34:1c:a3:8b:8e:fe:07:0c:b0:36:fa:db:ce:b4:58', 'SHA256:HGA+EGN7vROCadhXckS5/hwCluETf1cPA92A9+RTgxw',
+    'sk-ecdsa-sha2-nistp256_1', ["strict", "loose"]
+], [
+    'sk-ssh-ed25519@openssh.com AAAAGnNrLXNzaC1lZDI1NTE5QG9wZW5zc2guY29tAAAAID92A9iaZ6WS0dcc4qsxuUfMgwFuFeh48faLjYlaYXswAAAABHNzaDo=',
+    256, 'MD5:0b:87:18:2a:09:e7:a9:77:73:cd:3d:83:83:77:ea:83', 'SHA256:Uz5X82+UKm4CiOdqnfAtV/5JfnysqPHt1Is0iGnD70g',
+    'sk-ssh-ed25519_1', ["strict", "loose"]
+]]
diff --git a/tests/valid_keys_rfc4716.py b/tests/valid_keys_rfc4716.py
new file mode 100644
index 0000000..ab90811
--- /dev/null
+++ b/tests/valid_keys_rfc4716.py
@@ -0,0 +1,121 @@
+keys = [[
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1024-bit DSA, converted by ojarva from Ope"\nAAAAB3NzaC1kc3MAAACBAPlHIP5sD+T8/Sx1DGEiCzCXqpl7ww40jBg7wTkxu44OH6pNog\n5PjJt5M4NBULhKva/i+bhIM3ba+H1Or+aHWWFHACV6W2FCGk/k37ApRF8sIa4hsnN0P9qn\n6VfhbJKee+DBxa21WjjY/MZiljmJz7IQHx5RTxX9I/hJ7cL+aNmrAAAAFQCKteqc4IkgIr\njpcpStsxYAhb3MqQAAAIEA+SfIKuTr7QPcinsZQDdmZOXqcg+u9TLzHA4c47y0Kns3T3BV\nPr9rWdmuh6eImzLO4wMLxLvcg3ecrqFuiCp1IHvXENkGlpB17S+uOXlVDY+sTdXyvYKRKi\nrg5IZefIAP/m08c0QGkhFDbo4ysr9D5gXgH3LB2rMPIAbvMWm/HZQAAACBAKWtAE3hXRQX\n5KtI4AoIWVTly/6T4JNBt4u24ZRqV7X//CZEZ0cS5YpR/frlpUDI3WKoMtS+VmT3cBFZIN\nashIxZyfBF8+0UX3s34HwNfp0hDW3ZdgZJU56GC2eclMantYGeVrMxgTQd80pxZFgByEho\nXGeZaAwUzN8ULo9jHQqM\n---- END SSH2 PUBLIC KEY ----\n',
+    1024, 'MD5:76:66:08:8c:86:81:7e:f0:7b:cd:fa:c3:8c:8b:83:c0', None, 'dsa_basic_1_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1024-bit DSA, converted by ojarva from Ope"\nAAAAB3NzaC1kc3MAAACBAJKa9kgpSUBLgPwgkRvYDayXIjigt36VZShchgKSNxjOXfuJpN\nP7BUZFJSqE1ZKvMcmMKah2V15a+aV8H5TnFYSUT+aq5BH2lSxx5cHQ/xrSMBobqjxQHQJs\nhrHugnrBmXvhadWHZ8T/kV0agddRTuC/nY28RA2OOLFukEc2C/O7AAAAFQDMCEXIHwdtyx\nv0HDBHhN+N9pzedwAAAIB7zE3EQ8tHvEhoHZ3lc53qMCfow64rv5L0eim6hqC/cwzWHGFk\n9PXAHgXOZBMB9P2gCdiL1Vydru/6ib3EbzAGR21xhvxlrZQqtJ7jKql0ZbVCqzYijBwJCU\n2OAvaxjyTZwg5o87h1LqxU9RRFJTJerMCcnEy4X7iIIF2S8TLeswAAAIAxQ9/DLm7l3X43\n8VFgdTKSOrrfgx5q5/sKXgauNTxaYfDEBlmWdFZme3+lB1gR0td9NMxH/ffntXd8ilB+9O\n8E87+K0Fi7aDWlToVbsvtyK/gLTwzg+qEjeHkbjN7yUltvhzzvLkJN7NodWx4ECNP9Kuxz\nxq711uoFOiC+pFjJhQ==\n---- END SSH2 PUBLIC KEY ----\n',
+    1024, 'MD5:ff:eb:5b:a2:31:26:4a:2f:90:60:93:1d:1c:e5:ac:40', None, 'dsa_basic_2_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "16383-bit RSA, converted by ojarva from Op"\n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\nOhtK358XF1YOxzIGyFPTvEODhe0Zv9\n---- END SSH2 PUBLIC KEY ----\n',
+    16383, 'MD5:b6:ff:d9:90:61:a7:73:77:49:cc:b1:41:ca:c1:3b:a5', None, 'valid_rsa_16383_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "16384-bit RSA, converted by ojarva from Op"\n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\nkl5ZEGBbiRf3+EQZgBpYhQiyZ6Oq7hlQ==\n---- END SSH2 PUBLIC KEY ----\n',
+    16384, 'MD5:0e:e0:bd:c7:2d:1f:69:49:94:44:91:f1:19:fd:35:f3', None, 'valid_rsa_16384_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "768-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAYQCxO38tKAJXIs9ivPxt7AYdfybgtAR1ow3Qkb9GPQ\n6wkFHQqcFDe6faKCxH6iDRteo4D8L8BxwzN42uZSB0nfmjkIxFTcEU3mFSXEbWByg78aod\ndMrAAjatyrhH1pON6P0=\n---- END SSH2 PUBLIC KEY ----\n',
+    768, 'MD5:56:84:1e:90:08:3b:60:c7:29:70:5f:5e:25:a6:3b:86', None, 'valid_rsa_768_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "771-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAYQbdtLTII+vP98NSDlK2LXxVARELRYO0NODFYQ0imY\nxsmBMB7BrfljFppLJyjU6cziOT6YFj6rVd8MmCogdCR32u63EV11uT6RCFfJMQJtIi+B1J\nJipTxLzURsiUOOgAHJc=\n---- END SSH2 PUBLIC KEY ----\n',
+    771, 'MD5:29:01:ab:68:09:69:02:57:86:ea:f2:76:4b:2f:ef:f8', None, 'valid_rsa_771_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "780-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAYgpPyLrc+NDQJjf4B1jVA/eTaOzpDqmjM/oFKQEq+H\neSFxqFS3Fe7kLIfvdClVyYshg3qz1OfH+mCkcqLX5CPhdZZZbDxAbowAfPmBF77qeQqOsq\nNhIO0tQ6NX00PNmp5sLL\n---- END SSH2 PUBLIC KEY ----\n',
+    780, 'MD5:86:0a:3f:a5:aa:3b:c1:6c:50:86:dd:4c:86:d9:6f:18', None, 'valid_rsa_780_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "783-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAYnE55Aie+1J73DhvqOgyOf+hRMRI9+qoCRhIX6/xGi\njmrWBKhax0CKQ/E4HDyoviUbd/Q4jPNnpjA9lJWLDh23auSUPQMl4xBuUxzaJh1G+HFYJH\n0HA9/ONFb6oQd0J8StuJ\n---- END SSH2 PUBLIC KEY ----\n',
+    783, 'MD5:b6:6f:95:a1:f2:e4:de:ac:9d:22:e9:70:40:80:3d:22', None, 'valid_rsa_783_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "786-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAYwNgeGM0y1gmTC5yGLpiL2TF56l+ynG+9OcoonNsXt\n/mnAOpH7KbVnA7utELLidfS6oenKBWMJlbMmMeM+/7mEcKoF0TUAtdaJvtawLmUKHdAZNv\n0qZhrKN0L/OZAvkn5u2urw==\n---- END SSH2 PUBLIC KEY ----\n',
+    786, 'MD5:d2:e4:db:9f:c1:3f:7f:ab:09:a8:ef:b8:0d:0e:4c:e9', None, 'valid_rsa_786_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "789-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAYx1UtgIDIf1tpk4ro2r7ethUFwrL94KhffPD6E0Z5U\n5dC8ZCjblTauZSmhztVYMh/8nhU/ArP/zy208d32mMxTklxnx/tFulwtDXaH13A8EdCNdB\nzUG+wQ75O0kQVUMpp/rVnQ==\n---- END SSH2 PUBLIC KEY ----\n',
+    789, 'MD5:ef:32:28:eb:3f:2a:a1:bf:34:d1:26:bd:8c:6f:c0:c2', None, 'valid_rsa_789_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "792-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAZADu5iFbDQWHggy7d1kKkc6RVkNkiRjOwT1dbghPz1\nlWX3HK/iGFoMySTB1iviwoufHNAPS75WJeC1nfZBEkrIW16SrwsfLtuKMwjz+8Sb2ENtC7\ntyLB8IG77/ewRDEwOGiu8pc=\n---- END SSH2 PUBLIC KEY ----\n',
+    792, 'MD5:b1:aa:90:f3:76:8b:46:a9:0e:3b:e7:e6:1f:dd:30:e8', None, 'valid_rsa_792_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "804-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAZQ8rZh7qsWG7dcZ+Gs6yg0AAJyjJhkzYG4qmG5HkS6\nim0D5H1jk9FZCAdZpJdQc8oBUGBDRe1xtorY4GsxS+Bdk5BoiGMwr7yWKjFy0Ert6MUG7Q\nUAknM3nLZKWm4MZvPRToHGjr\n---- END SSH2 PUBLIC KEY ----\n',
+    804, 'MD5:22:09:eb:fe:94:a5:3d:58:b0:23:ea:42:0b:a2:3b:6c', None, 'valid_rsa_804_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "807-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAZW0CyFwCSXjZ/FJ1RuqkgBeLgTBJ3hk/OTn0pI8g9c\nr9r5EFlYT8/ZXd1ilP5rSknba1g9FudG8eCH7Ah+cnbFbzPJNH6Aofga9hh4fewKo+KI0S\n65H+XgBJsp+xEZnLPCIqhzkF\n---- END SSH2 PUBLIC KEY ----\n',
+    807, 'MD5:28:ce:cf:1c:54:2d:c2:26:d6:b4:9c:7a:9f:fa:d8:1a', None, 'valid_rsa_807_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "810-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAZgKVmEp6e8BmGxLrfBE+bzMog35mZ70vTurSwKZ+PE\n2eo4/h2xLXC0/O6tFItgukF2oG75Hkx0CrLwbSBYeaYVtYCp7dWiDQpS8Ribq5zRHl0tz+\n9DBioHSIAkNJ6Xesy6y+5oZHiQ==\n---- END SSH2 PUBLIC KEY ----\n',
+    810, 'MD5:d1:21:8b:4d:84:6b:cd:8c:4e:d8:b5:92:ef:75:76:d0', None, 'valid_rsa_810_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "813-bit RSA, converted by ojarva from Open"\nAAAAB3NzaC1yc2EAAAADAQABAAAAZhnHxufkUNVz7fITzsow1EFbxdCH7GB8BaT5fUESJD\n3TYKaCbHefxrDU6UYAgaEKnXVmd5tE3D2qZ8Z33ECEuQHHIoSicB5VIG+zNwOLve8/ftFj\nippwnSe89g/1Lu/qXVzsGCCvTw==\n---- END SSH2 PUBLIC KEY ----\n',
+    813, 'MD5:7e:9a:26:2b:77:54:d1:24:54:a7:e7:05:41:be:bb:7e', None, 'valid_rsa_813_rfc4716', ["loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1299-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAAowYV74xpHjU/esNFWOAZvh3JiHlPgmeIFPBeKiZsP2\nOS/yxulMs/MbM6Cc0Q0GFhF3ycNu6rsjQHuoLbFxcrRA4reBDU+BFA9YeG9ptdpBW2rjl+\n/MjPML2cmIiF9VOuwia8WWLH/gro/AECoEiAbKUJcbD8PdGfZpb/QZyGl+5WpoKW3OD9PT\nDJmI6to2lp+NNx2bvV08sb2z8zVJXLgBrQ0Vc=\n---- END SSH2 PUBLIC KEY ----\n',
+    1299, 'MD5:40:fa:26:65:60:fd:62:ee:03:70:bf:db:15:53:78:bf', None, 'valid_rsa_1299_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1302-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAAoyx+ox9qPgBMrRireysGh3SOuMj9rPXgPIgTRCH4Yg\nHJavaIKNE3l+FPYT2r4ri2Ej5kIN351muDMaaiT8dqWWcOSoFFNPv1DZ75iVBBvQBhAgP2\nkllbzI4/e0qqc0BGBW2c19rTIQK2uSfFCTcVaIJQooM6knKYUPWNUJWc4C+/NYD7hRp9s1\nMXgMO6F1ajJKD+z51zoFXcMZKb3yODguWSU90=\n---- END SSH2 PUBLIC KEY ----\n',
+    1302, 'MD5:96:b3:a5:61:3d:8d:86:2b:ee:94:dd:e8:e3:6a:26:03', None, 'valid_rsa_1302_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1305-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAApAGFxZYSi3pcajPO4+bBOc0lKv9NzuIB2CcY8HdZEQ\ne0QGbbu/saDgFuMLirBlZrkldSRdFgCVpTVScxbABvX0Cx7sPNwPag8QTsgI/phQivCGx2\nU7/2jsJDcfCj1uHGnTKWh8b4wNto0lpaeo0aSMZfymgjDEkgxpWBhJMgkWwlOP3hWSXl43\nmO0bcfHoyuDHccbmwztExuQ2ImpkJaDOVrom9f\n---- END SSH2 PUBLIC KEY ----\n',
+    1305, 'MD5:12:a1:ab:e8:fc:ca:e1:21:a7:06:86:e7:7a:fd:10:ca', None, 'valid_rsa_1305_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1308-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAApAxM2gGIaiwCkuzBjFsmgh0GEmwmf/5+dxm9HWz2PU\nsG8utJN1mCyLWkuWhwBiOnttvKIvfKbmr8KAIvwGUOQyMjE8Xi2JuMl4Vc3HvVGbeNQXhw\ngyXsE7ykjHZioddaOwv87j+SzDlP1As2hq9VOtTByIrqo7Qn/OCDJI0z6fBhtbtjFTjdBB\n7ViSfKw8TEgexSyIPxTe74RQjmalA9UEXyUHlx\n---- END SSH2 PUBLIC KEY ----\n',
+    1308, 'MD5:ef:51:09:9b:4e:b5:3a:15:05:19:15:68:66:c3:bb:16', None, 'valid_rsa_1308_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1311-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAApFgBPZxYXC1JXtkOO6irCMCmoz+jzWg5GLqd0V2rZA\npdQ16JrsX/DTO9V5NTCiLQbN1UqW8EuJXLKNyzZefh9EdzwciOzIPIyFqPsklNKWhWeX31\n1jMUmbCS7M9+Pxi/wQ3FG2uxycb8ZX8THI7T5L1QvyJivxGPxZAQXpVZvD9j0zalCyVdkF\nDRJCE3jkK2jGyu2RFZT6NZEo9qpqo8H7f1L6q5\n---- END SSH2 PUBLIC KEY ----\n',
+    1311, 'MD5:fb:ff:40:35:e5:78:e9:03:f8:d2:c1:71:39:82:3b:fc', None, 'valid_rsa_1311_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1314-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAApQOZtuX6wLBkB2f9hm4iCbJwhteR1+o3+dfxb5lWE8\nf3GOld2b/up8vd+GLMM6kHhkfUhpPNdJ0PfSu8L/p51MPq0PfrD1IhO9u7d/U4Tebyy6Uz\nRPsPo6j38cU7rcIqHZwDiGCon9VO4x3WF58l2WJ0P/UcnLYVjC/jXioQBF1la7IPs3H4g+\n+jy/9oQNn4/NH8/Lk5oTUF9aHOtsauCxrqzGGCQQ==\n---- END SSH2 PUBLIC KEY ----\n',
+    1314, 'MD5:7b:49:e3:c5:53:89:b5:30:5f:0a:f0:5f:12:9d:92:95', None, 'valid_rsa_1314_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1317-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAApRS5H4cONMXNAgn+CmPJXaTyZI+R9jai89ATYSUuBJ\nVVI5MOVBoRTYzZISi/nMDdsH0D14zlOsmc+5+aHCAkFlBOSag23xHj3gfPsLcs6AjX/irv\nhjBoj7bOSI1Tzxggc+S1sOd4WmZo9jLpxXQ0H1Md7ic5rFg/oU2qA8TuCm1jBUpviTL3xM\n/fNraLnIUcPWG8o4LJL71YZc6quWXjNEmK7u0kYQ==\n---- END SSH2 PUBLIC KEY ----\n',
+    1317, 'MD5:41:6d:91:da:82:7f:b3:5b:e3:b1:6d:4a:23:8e:7d:b7', None, 'valid_rsa_1317_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1320-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAApgDURQ01EZNnjdCKce3/28LbXfLwQtaS+k7TK/jRik\nonejiiN7MXaayqahhNry/Edzf2/WJSOnBbBdhgLxhBgPJy8Yk/koaD6DmjnJ0Hrl+s1RBU\nAGsW2Da9/b9VIYkPbPJ6UwiTDB1SPF6jINqW7mLvOxt9onJwz95uct1udwk8XHp709vv6b\nRn5xpq26BukOvBxhu3KX8h68txqSDFmH6haEzjXoU=\n---- END SSH2 PUBLIC KEY ----\n',
+    1320, 'MD5:27:33:d2:ae:58:fc:b8:4f:41:36:de:24:ba:2d:3f:c9', None, 'valid_rsa_1320_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1323-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAApgYP1GJHBP+AnJiU4AQITNotMWbxM41bTVwrYC4UAW\nmgm/v8F8U5R+HHWcwyPahNt7vVJ4fw8MshVLNVcGf598F1vEJuKvKMuPQjetJcGxfSA/g5\nby/aPIdzstUUp8afsFOyEJOAf23pdw5k6QmyPPbAg8/zGoZkZ3lbnnr9gAOK5iSuwW4Zju\n/LTPDuu89cBrvlFr05xpxVArh6H0gRo18T2xjz/z8=\n---- END SSH2 PUBLIC KEY ----\n',
+    1323, 'MD5:c1:82:87:db:76:e4:2b:b1:b0:7a:c3:a2:a4:da:75:45', None, 'valid_rsa_1323_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1326-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAApic5f0WgrxUGHUSG1he6A6CVjBbjWrckrMliNhHo5m\n38Q+TmALI+4ktbtDG61Y58SGVXaBvFnlkba6PsBfq0dudJn6zhcWohOCX2jwJAdUOhPuVf\nL6e4fNLfJmnyeIGS9vtXSkk/PYXshkEPq/UerOlpAS+jxZnXPZnnpIHrX/NvMarLKLA/f6\nuaDfF3jIl7TxT4I1Bhn9KtlBZOzrC2sTsnnkcWiVE=\n---- END SSH2 PUBLIC KEY ----\n',
+    1326, 'MD5:f9:3d:7a:eb:a8:b5:0b:f3:f1:1d:c0:fa:3e:c2:0e:8e', None, 'valid_rsa_1326_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1329-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAApwGHoGv4qz/U0A5j/wuDQzq9GtQEQv6Z0cs03/cBb8\nJLmj+xnZIlM7dgzvxfSmutjR0m5E+rbUuRYNoYpeVZtaD8r5h3Dj2bvWnmf2U0vReHZhH9\njuEdOrVDuZtXU4SkRo1P3f5HuVeo6D5U1gkSg2YUpYpGE3Y+nhEWmiZrBcns8Yw1z72rva\neCjRwzyZgSpyVRQOXygmiOP/3GIfb8zNChd3qWJtlP\n---- END SSH2 PUBLIC KEY ----\n',
+    1329, 'MD5:89:2c:f6:06:f8:5e:f3:bb:cd:28:33:4b:0a:6d:10:ed', None, 'valid_rsa_1329_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1332-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAApwraDBOJz0St0svlhB7cN7Cy67vH5/X9jvyMMIeHH/\nzNAR89TyWRLWkARidtqOIqgyPzRj2nCSm5ISu2T+/DHNZcP0shhcRoKLh52otz+gJatyvs\nYL1w4ZW6P1h8U6Faf2DbxsUcfIYVx3K2O4V1m/8+aDQjFIW4a0bARU9liu3Z1LB9f6NwS6\nZEcHb8dlo+3lsnkjVFR6Xl1zzs86pPBGJRA0HYf2yB\n---- END SSH2 PUBLIC KEY ----\n',
+    1332, 'MD5:16:69:3d:b8:cd:a0:78:8d:7b:0b:0e:99:24:c1:d1:4e', None, 'valid_rsa_1332_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "1611-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAAygXJwDBDbv4+4J+zx90C9wUmXaXKiCvQf4LG08Rp6N\nXjWPCGFEclp3MP1apbEVzrSYwEFHFtEODwAdT6SdZWzrOu0pi/ee4E+5oBNoxsRq7Ggk7q\n/YH7I/rPv/av3nz3M7he6AC1Urn9iDtgg2kRrG93iD5bBngq9mBa2XRWykF3LfSIR6UcCW\nlhvNMlhQ6HX+h5jwe2Ali+zCArVYK4OwIDDRRN1vQpFa41wnadwz7jYRtUU6rb0HOpknzV\nVLLEMA9hesdv7IfmA/k=\n---- END SSH2 PUBLIC KEY ----\n',
+    1611, 'MD5:ff:ac:71:02:fe:38:a0:c8:58:4c:06:6d:cc:ee:e7:0d', None, 'valid_rsa_1611_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2013-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAA/Bg4DNQh1RFnvgCi0Q3vCrUYBB6oZufUK7AXrtFRD+\n8n/QRvQnQPE59tQHlQ8FvLbVq/uqj/HzO9iRWlqP05/GB4byZWwk1vDfGFqOL/5rTUdcdo\nkRcy2zzGIWWzbhUbnoKNWpr7f/nRBzTvvcUVlAJTTITjd+87cb/Gr74GQIhM7Ao7tv7qE+\nqVtCWj9G4i4ojmfAMoWIGMRRbAkr7MdnAIV7UVwC8AN/gz8zIYhutHX3p9SxWy5V0UgQjV\nwJh5Vb72pndUmJXmjUyzuZXqxAOFtfXge0WwCMRd/bDcBPILaa33KxlHc48IpS351pVeka\nS1KsheVBzus00S6w==\n---- END SSH2 PUBLIC KEY ----\n',
+    2013, 'MD5:a8:9c:d3:a5:97:65:61:39:a8:98:e6:59:bc:f8:f2:06', None, 'valid_rsa_2013_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2016-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAA/QD1WMI5FCXEgGSYPVJkDexjZMU9OqokStDg8LL5gu\nY+b9EECEJ4xWMnGFC8CbyMDHmUQiYRpbh8bUzU8uLt0wLrEn15yc5R3F3BCX1kdjlKcLpo\nQryHvL2aJNNv02atgJ2os9QSsY8O6yOoPlSC/vmGurHPrtoL7sRVUPcHtPU5QlqvkbdFAm\n0dQ0BrGE6SH9Ia7cv3f9ky0WexFrdmxTiMK8gT1ZkhIlM2iQVct/pz1R4VL+GXU2ia5CHp\nl8Ag4NrIw+O0Y1VfakOtXMfr2RhbS8DZDKvVaJVveoqv9LQe8Nq+uPu0A+KY1KVHbZyvlS\nsoH7NKkbF4SRYzK9U=\n---- END SSH2 PUBLIC KEY ----\n',
+    2016, 'MD5:e2:33:6d:69:a8:4e:fd:52:15:7a:6b:a9:8a:3e:63:00', None, 'valid_rsa_2016_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2019-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAA/QYQGpPpfnSgFbyZx3klNz4FyTCdDY7bq1fwRsP7wr\ng7yfX7IimAdDcTcoVyd6JEaYqlNCtK9ClTwSmuVVpmS6p/834DQtzOhvxs7u3cti4buYX7\nmLfnmAfLI80eeFGXGr1K2owsFEHbEAJTG007BvcezM4V7l54iniTGCoxrvbHrp3Puc46gm\nGEo6J2bDDYXKD9xmuVL0XrUYqvR34fVswMABSlNN9ROdxCI5jxKhuOrL0sZg/faf+973Cf\nJWPfFGPkOaINSpUgBDKVTRwWL86IjIEnDdiIyNAxAnbZOyGAMO0+0iyWOBso7QxFt7UoYi\n/C803I1BCGbXqCAGs=\n---- END SSH2 PUBLIC KEY ----\n',
+    2019, 'MD5:e4:a5:13:0a:bb:06:02:34:68:1d:2a:69:6e:b2:82:0d', None, 'valid_rsa_2019_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2022-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAA/TDTpJy8OjtlM9F+UClxMF4XFN/LRh63c2JgBVquLm\n9pevlsRRsN3MUk+N5b6hDcluKYOI5loOyXTuPkuGYdxowuTOkS3sdp7zZAhkeRW/g8ChnO\neiNWkGwR6vCbJh2Kbhvn3QG/fZgG5E0hRfqn8hfShNsWZeH5m7eiurwL30a7Mx+m9OsdEE\nea91wQckGAskA7nz2nLzEL5J7eVK4c+gMKsyLDB8R9w1oYsbsUPfbv+7tDNwg+Ur03nXJ2\n31oHog3LLLSixvC24272ZJ14v8DFQnDcDzQDrrmoXdkRNrMsXIGaf/J9VFk49oJ7NHJzGv\nhNUeuGwuhrx7bs2aU=\n---- END SSH2 PUBLIC KEY ----\n',
+    2022, 'MD5:20:94:06:c0:3a:81:02:c1:bf:39:a8:1c:07:4d:db:3c', None, 'valid_rsa_2022_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2025-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAA/gFaVjuZJF8V5h/F3aJ/fs2MINAuoJH+VfqJb1rhsX\nljXV0XOEyHo7XyiZX7KVQ2AFB7ZWmtVjDu5wGgU6zKfvfoytbPPlYwaGf7RikRGdCWvsJn\nwB9PChAV9WsDqe4NODzaFIv/tiAUsy5CChkESIJeNLK2K/KQtEWSmu57hsr8terigCufSY\nt2YjKcKErIbRNVwu2SqfHSjPKRXzmjTbDpUpvCY3nU3kWJmhsZHPNz5J8z7xV5NSJPgjWM\nToKi+st9XJI/t7zYWrdwx4DCEjvKdGBKf3BklYrqx1c+vWhwclNyUd+zquGmhUTvsReI0A\n0e1o5mPM/n/uU0fyJ/\n---- END SSH2 PUBLIC KEY ----\n',
+    2025, 'MD5:60:95:d4:ec:69:ff:a6:1d:c7:dc:fa:fc:9c:45:b1:23', None, 'valid_rsa_2025_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2028-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAA/g1KS2Amcx2dKUY/AaDl+S9Nl5T8fqinfhurFuom2G\nAzcq30DtqAK5FVHXCKiYH9l4v+GDe7fi5nYX7teajgThPLUUPd0KSUa2xFcMZqDVOzv5jn\nB9lFVPZiQmRh4uP0dycxwtdYYGsOjkbriKfpTD/nlqzNPtaGInFRzGRPsaHSr2qYI8IHug\nG/A3SDxaJiNsNH4dg2QKQK0q4OxIn+tsFuiVJCessDpoKS0C4NzZYxKvsc0+2Ke7Qk1yXF\nDCyDlAagNGkjQLldsVWavdffv9u71ZnWi1jqyMEmG0nbtHJLasaiS+JKppN3drgxD5eheu\nhewJjMDzC3iBRRmhin\n---- END SSH2 PUBLIC KEY ----\n',
+    2028, 'MD5:46:6d:20:95:d9:ba:4f:73:2b:dc:16:ae:c6:50:68:33', None, 'valid_rsa_2028_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2031-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAA/mNcgBv75NCxkdwWznRWS9j4lBiE3kt+u/CmQl2UxE\nyDm6C5w42WCG6iHObmrOisUOC+FA7GqcanPw5FBPiXNGNFdPbFmOiHplkE6fe9LZeWSZWx\nseZKc0ShjQZ1MaUWDZeSlFoy1s71PO84eFFpn7yE6wt/KlhEoCIpdXai2wpJdTVp7gOQ4x\nYNRVYScWdj8nfAHM9mj7YM0AGymEI3nU4yDokAzktWDp/Y5u64+l0bTu4irA/NIP8ctBkD\nVZMwOyRbIcJkWYlGnJnyxR4JOefR8GhOH0z/YIE42KqJoHHL299JMFOT7HaBBm7YHFoq/K\ntKUZrSKlHTCLRfiA59\n---- END SSH2 PUBLIC KEY ----\n',
+    2031, 'MD5:6e:7c:f6:0b:e3:6e:2d:a7:e1:e9:4c:68:d3:89:ba:d6', None, 'valid_rsa_2031_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2034-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAA/wPaxCp9EthdCMUBIZMPfmpk4UHQV5IENsAagu6krz\nafIWJNpH1tdZGLJ7KWCS9tzXYLuPux2ZbHkDpAc6zXPY722WtWZsV81t/+WPdQcxoY0/nC\nPR6CK6XUgzYyrZbZvwu2yx5u20aSLsrDYunKmkZkz11rjBSQPrL9SikanpaDHibzlpTPa/\nXvb8Mv9ty15dYWlP/Kwgo1VN+xXai2BchwQ/rGdhhc5nEotRxFByc9onkJJA3jQrtzKw6P\nYmkAYcX5yftPfUkcgC3qaFP4FR8zIcZICgoJKClaevimv6Om1lkAKaOJbYxkFtKciuufF2\nUw61t1FiAanbKc+5U0sw==\n---- END SSH2 PUBLIC KEY ----\n',
+    2034, 'MD5:dd:49:3c:ba:e5:dc:e2:f1:ef:ed:80:c5:0a:ed:7f:aa', None, 'valid_rsa_2034_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2037-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAAA/xW3UoBjiOoneRlPJn2vCyg8iUJqTx5JSUJcrbpr5x\ncUXVUykVDMI7VnPqsQbX0PUwU47z2Qp7KBUfslSh6CkBOLZRxxHGf/EAj2Or86K4ZxJJx3\nT/Zrq7yzThAGOOKq+QzTBmsfQTCdgy4XDs0Axcpbohk6lIhscq86Lc4V2hL/JJUdlmt3Nx\nfeBuoq+7jD/HLV2VFRs62pBJQCePM/9m4rWPApbfdNlq7V03ncFx1hsVWMcmBrlLUxgW+k\nu8bt74kyZnNcWYflOkxMH8IsZH73xkpF5E5uHtnxClZ2rrzrBWDyHco7wGJNrG/cTKPOAS\nn3VoomdBAJ+ea24lGlkw==\n---- END SSH2 PUBLIC KEY ----\n',
+    2037, 'MD5:2f:71:47:7f:51:99:97:b7:00:74:76:43:35:a6:9e:5d', None, 'valid_rsa_2037_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2040-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAABAAC8AOpsr/bye5kOvXynQanwbDwusCLkFA1B/UmYVp\nB4lGlp7p/RKcOZ9uiwsnPP0JQ7OrZ5O+oDIW2WdHPfjfzlGCyoMuL3+PwHzqB+L8A8/9hR\nXLJAulufUvi/vFRfxUc05q/BWwGE6RsIzadvpdm9XtdXoG9eElpn7J+k4WE+5V9rR2c7Tz\noOt5TP/4emAwcHAxQIaIygijdHISS3CYIAWmIM33U5HbEbQBRrAE6I6y0gQxvhHCEat0c5\nRJ/zSqXJpplAtE7n0DUqC9kmnJsDAB9Cq7hxiRrttrMvl1ERoK0XW3wWwqi6mvVv3HHOfV\nj1lxLEwpeLEHRTQdS5sy0=\n---- END SSH2 PUBLIC KEY ----\n',
+    2040, 'MD5:99:6b:1d:c1:2b:d3:83:63:4e:a1:ea:51:c6:4e:25:17', None, 'valid_rsa_2040_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2043-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAABAAXo4IUS1bJYWrydi8B+t68xzH97cpUcKEWgWqQvy6\nebRw/Y/G5kHVOHD9vGBLX2j4dseB+71meNxeaTkQCDPmck4FFFe8LlfJgcJupAwVnEu/YS\nne55MHa9fO1hiZsg/oiZabS/DKoyOHLE7Usa/JQXJzGaRtLWAP1vWuCigfX/yfLA+CXxA6\nFh6VVaEhlUAdOoVZ/aFBrwsG19Yp5sU23HSIHAmkFMApb5jvlQbjQrLzQr9qmiRgsylFPi\n5OHp2tvbQeRKA9XzKVjpof4tSd0JDq5XgUHtlRI9CsIrVxjUJS8WkdDWW/uNWFQhQ5CS33\n2Jvet9xP6ZZpsYxS5KpQU=\n---- END SSH2 PUBLIC KEY ----\n',
+    2043, 'MD5:af:82:da:e7:04:5d:a0:38:30:b4:5f:ae:e2:87:63:f2', None, 'valid_rsa_2043_rfc4716', ["strict", "loose"]
+], [
+    '---- BEGIN SSH2 PUBLIC KEY ----\nComment: "2046-bit RSA, converted by ojarva from Ope"\nAAAAB3NzaC1yc2EAAAADAQABAAABADR9kolU4uiD26LMrbakQlNf4QWB2xrdY3nASf6CJd\nQYzTMjNmbt6sJ4A4pGnCupFrzL04EYDvbVmT4GEZm6CU4BsY61yosnpGSqqcVCdw5xW1k4\nbCSDPW75WHLCVmYyROhZ+yyo8uAcIy5UIyBZXF/PO7taJrrIi5RwdqIPwtCrJ3dJkcFWa3\nqZWJykLAFQD5A/lta/egS/u/nyCap2e16WGnvSluz9CyYtGFNS9axzOwHxLFEv2ocOsJjY\ngzV+Jfpiao94A4VzLKbUDHlfV57KS0tJaT8FKKsg34vN3bsD0zUftLUPpUFgJfMwje0C2r\nCJkCzwgya2vxLqj2fg0Q0=\n---- END SSH2 PUBLIC KEY ----\n',
+    2046, 'MD5:27:24:34:50:5b:39:2d:34:f9:60:d5:4e:7a:c7:11:51', None, 'valid_rsa_2046_rfc4716', ["strict", "loose"]
+]]
diff --git a/tests/valid_options.py b/tests/valid_options.py
new file mode 100644
index 0000000..7d0c0fd
--- /dev/null
+++ b/tests/valid_options.py
@@ -0,0 +1,27 @@
+options = [
+    ["empty_options", "", {}],
+    ["single_basic", "no-user-rc", {
+        "no-user-rc": [True]
+    }],
+    [
+        "single_quoted", 'from="*.sales.example.net,!pc.sales.example.net"', {
+            'from': ['*.sales.example.net,!pc.sales.example.net']
+        }
+    ],
+    ["equals_in_quotes", 'environment="NAME=value"', {
+        'environment': ['NAME=value']
+    }],
+    [
+        "multiple_quoted", 'environment="NAME=value",from="*.sales.example.net"', {
+            'environment': ['NAME=value'],
+            'from': ['*.sales.example.net']
+        }
+    ],
+    [
+        "multiple_options_combined", 'permitopen="host:port",port-forwarding,no-port-forwarding', {
+            'no-port-forwarding': [True],
+            'port-forwarding': [True],
+            'permitopen': ['host:port']
+        }
+    ],
+]

Debdiff

[The following lists of changes regard files as different if they have different names, permissions or owners.]

Files in second set of .debs but not in first

-rw-r--r--  root/root   /usr/lib/python3/dist-packages/sshpubkeys-3.3.1.egg-info/PKG-INFO
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/sshpubkeys-3.3.1.egg-info/dependency_links.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/sshpubkeys-3.3.1.egg-info/requires.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/sshpubkeys-3.3.1.egg-info/top_level.txt
-rw-r--r--  root/root   /usr/share/doc/python3-sshpubkeys/README.rst

Files in first set of .debs but not in second

-rw-r--r--  root/root   /usr/lib/python3/dist-packages/sshpubkeys-3.1.0.egg-info/PKG-INFO
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/sshpubkeys-3.1.0.egg-info/dependency_links.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/sshpubkeys-3.1.0.egg-info/requires.txt
-rw-r--r--  root/root   /usr/lib/python3/dist-packages/sshpubkeys-3.1.0.egg-info/top_level.txt
-rw-r--r--  root/root   /usr/share/doc/python3-sshpubkeys/README.rst.gz

Control files: lines which differ (wdiff format)

  • Depends: python3-cryptography (>= 2.1.4), python3-ecdsa, 2.5), python3:any

More details

Full run details