Hello community,

here is the log from the commit of package python-jwcrypto for openSUSE:Factory 
checked in at 2020-09-09 17:48:09
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-jwcrypto (Old)
 and      /work/SRC/openSUSE:Factory/.python-jwcrypto.new.3399 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-jwcrypto"

Wed Sep  9 17:48:09 2020 rev:9 rq:832630 version:0.8

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-jwcrypto/python-jwcrypto.changes  
2020-04-19 21:48:06.111916093 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-jwcrypto.new.3399/python-jwcrypto.changes    
    2020-09-09 17:48:54.806522676 +0200
@@ -1,0 +2,17 @@
+Sun Sep  6 19:25:26 UTC 2020 - Tomáš Chvátal <[email protected]>
+
+- Use constraints on the cryptography dependency
+
+-------------------------------------------------------------------
+Sun Sep  6 14:51:40 UTC 2020 - Michael Ströder <[email protected]>
+
+- update to upstream release 0.8
+  * Fix some documentation typos
+  * Rename ambiguous variable
+  * Remove cap on sphinx version
+  * Fix okp key type import
+  * Add method to export Keys ans Sets as dictionaries
+  * Typo rectified
+  * Add secp256k1 curve
+
+-------------------------------------------------------------------

Old:
----
  jwcrypto-0.7.tar.gz

New:
----
  jwcrypto-0.8.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-jwcrypto.spec ++++++
--- /var/tmp/diff_new_pack.6SMsld/_old  2020-09-09 17:48:57.482524850 +0200
+++ /var/tmp/diff_new_pack.6SMsld/_new  2020-09-09 17:48:57.486524854 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-jwcrypto
 #
-# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,19 +18,18 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-jwcrypto
-Version:        0.7
+Version:        0.8
 Release:        0
 Summary:        Python module package implementing JOSE Web standards
 License:        LGPL-3.0-only
-Group:          Development/Languages/Python
 URL:            https://github.com/latchset/jwcrypto
 Source:         
https://files.pythonhosted.org/packages/source/j/jwcrypto/jwcrypto-%{version}.tar.gz
-BuildRequires:  %{python_module cryptography}
+BuildRequires:  %{python_module cryptography >= 2.3}
 BuildRequires:  %{python_module pytest-runner}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-Requires:       python-cryptography
+Requires:       python-cryptography >= 2.3
 BuildArch:      noarch
 %python_subpackages
 
@@ -55,7 +54,7 @@
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check
-%python_expand py.test-%{$python_bin_suffix} jwcrypto
+%pytest jwcrypto
 
 %files %{python_files}
 %{python_sitelib}/*

++++++ jwcrypto-0.7.tar.gz -> jwcrypto-0.8.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/PKG-INFO new/jwcrypto-0.8/PKG-INFO
--- old/jwcrypto-0.7/PKG-INFO   2020-02-19 18:17:34.000000000 +0100
+++ new/jwcrypto-0.8/PKG-INFO   2020-08-20 12:48:07.538233500 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: jwcrypto
-Version: 0.7
+Version: 0.8
 Summary: Implementation of JOSE Web standards
 Home-page: https://github.com/latchset/jwcrypto
 Maintainer: JWCrypto Project Contributors
@@ -13,6 +13,7 @@
 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: Intended Audience :: Developers
 Classifier: Topic :: Security
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/README.md new/jwcrypto-0.8/README.md
--- old/jwcrypto-0.7/README.md  2018-06-27 08:24:18.000000000 +0200
+++ new/jwcrypto-0.8/README.md  2020-08-20 12:47:47.000000000 +0200
@@ -4,13 +4,13 @@
 ========
 
 An implementation of the JOSE Working Group documents:
-RFC 7515 - JSON Web Signature (JWS)
-RFC 7516 - JSON Web Encryption (JWE)
-RFC 7517 - JSON Web Key (JWK)
-RFC 7518 - JSON Web Algorithms (JWA)
-RFC 7519 - JSON Web Token (JWT)
-RFC 7520 - Examples of Protecting Content Using JSON Object Signing and
-Encryption (JOSE)
+- RFC 7515 - JSON Web Signature (JWS)
+- RFC 7516 - JSON Web Encryption (JWE)
+- RFC 7517 - JSON Web Key (JWK)
+- RFC 7518 - JSON Web Algorithms (JWA)
+- RFC 7519 - JSON Web Token (JWT)
+- RFC 7520 - Examples of Protecting Content Using JSON Object Signing and
+  Encryption (JOSE)
 
 Documentation
 =============
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/jwcrypto/common.py 
new/jwcrypto-0.8/jwcrypto/common.py
--- old/jwcrypto-0.7/jwcrypto/common.py 2020-02-19 17:12:20.000000000 +0100
+++ new/jwcrypto-0.8/jwcrypto/common.py 2020-08-20 12:47:47.000000000 +0200
@@ -91,7 +91,7 @@
     """Invalid JWE Key Type.
 
     This exception is raised when the provided JWK Key does not match
-    the type required by the sepcified algorithm.
+    the type required by the specified algorithm.
     """
 
     def __init__(self, expected, obtained):
@@ -103,7 +103,7 @@
     """Invalid JWE Key Length.
 
     This exception is raised when the provided JWK Key does not match
-    the length required by the sepcified algorithm.
+    the length required by the specified algorithm.
     """
 
     def __init__(self, expected, obtained):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/jwcrypto/jwa.py 
new/jwcrypto-0.8/jwcrypto/jwa.py
--- old/jwcrypto-0.7/jwcrypto/jwa.py    2020-02-19 17:12:20.000000000 +0100
+++ new/jwcrypto-0.8/jwcrypto/jwa.py    2020-08-20 12:47:47.000000000 +0200
@@ -249,6 +249,18 @@
         super(_ES256, self).__init__('P-256', hashes.SHA256())
 
 
+class _ES256K(_RawEC, JWAAlgorithm):
+
+    name = "ES256K"
+    description = "ECDSA using secp256k1 curve and SHA-256"
+    keysize = 256
+    algorithm_usage_location = 'alg'
+    algorithm_use = 'sig'
+
+    def __init__(self):
+        super(_ES256K, self).__init__('secp256k1', hashes.SHA256())
+
+
 class _ES384(_RawEC, JWAAlgorithm):
 
     name = "ES384"
@@ -1042,6 +1054,7 @@
         'RS384': _RS384,
         'RS512': _RS512,
         'ES256': _ES256,
+        'ES256K': _ES256K,
         'ES384': _ES384,
         'ES512': _ES512,
         'PS256': _PS256,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/jwcrypto/jwe.py 
new/jwcrypto-0.8/jwcrypto/jwe.py
--- old/jwcrypto-0.7/jwcrypto/jwe.py    2019-05-27 14:17:28.000000000 +0200
+++ new/jwcrypto-0.8/jwcrypto/jwe.py    2020-08-20 12:47:47.000000000 +0200
@@ -284,13 +284,13 @@
                         "is set" % invalid)
             if 'protected' not in self.objects:
                 raise InvalidJWEOperation(
-                    "Can't use compat encoding without protected headers")
+                    "Can't use compact encoding without protected headers")
             else:
                 ph = json_decode(self.objects['protected'])
                 for required in 'alg', 'enc':
                     if required not in ph:
                         raise InvalidJWEOperation(
-                            "Can't use compat encoding, '%s' must be in the "
+                            "Can't use compact encoding, '%s' must be in the "
                             "protected header" % required)
             if 'recipients' in self.objects:
                 if len(self.objects['recipients']) != 1:
@@ -438,7 +438,7 @@
          If a key is provided a decryption step will be attempted after
          the object is successfully deserialized.
 
-        :raises InvalidJWEData: if the raw object is an invaid JWE token.
+        :raises InvalidJWEData: if the raw object is an invalid JWE token.
         :raises InvalidJWEOperation: if the decryption fails.
         """
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/jwcrypto/jwk.py 
new/jwcrypto-0.8/jwcrypto/jwk.py
--- old/jwcrypto-0.7/jwcrypto/jwk.py    2020-02-19 17:12:20.000000000 +0100
+++ new/jwcrypto-0.8/jwcrypto/jwk.py    2020-08-20 12:47:47.000000000 +0200
@@ -148,12 +148,14 @@
     'x5t#S256': JWKParameter('X.509 Certificate SHA-256 Thumbprint',
                              True, None, None)
 }
-"""Regstry of valid key parameters"""
+"""Registry of valid key parameters"""
 
 # RFC 7518 - 7.6 , RFC 8037 - 5
+# secp256k1 - https://tools.ietf.org/html/draft-ietf-cose-webauthn-algorithms
 JWKEllipticCurveRegistry = {'P-256': 'P-256 curve',
                             'P-384': 'P-384 curve',
                             'P-521': 'P-521 curve',
+                            'secp256k1': 'SECG secp256k1 curve',
                             'Ed25519': 'Ed25519 signature algorithm key pairs',
                             'Ed448': 'Ed448 signature algorithm key pairs',
                             'X25519': 'X25519 function key pairs',
@@ -180,7 +182,8 @@
 
 JWKpycaCurveMap = {'secp256r1': 'P-256',
                    'secp384r1': 'P-384',
-                   'secp521r1': 'P-521'}
+                   'secp521r1': 'P-521',
+                   'secp256k1': 'secp256k1'}
 
 
 class InvalidJWKType(JWException):
@@ -278,7 +281,7 @@
         always be provided and its value must be a valid one as defined
         by the 'IANA JSON Web Key Types registry' and specified in the
         :data:`JWKTypesRegistry` variable. The valid key parameters per
-        key type are defined in the :data:`JWKValuesregistry` variable.
+        key type are defined in the :data:`JWKValuesRegistry` variable.
 
         To generate a new random key call the class method generate() with
         the appropriate 'kty' parameter, and other parameters as needed (key
@@ -287,13 +290,13 @@
         Valid options per type, when generating new keys:
          * oct: size(int)
          * RSA: public_exponent(int), size(int)
-         * EC: crv(str) (one of P-256, P-384, P-521)
+         * EC: crv(str) (one of P-256, P-384, P-521, secp256k1)
          * OKP: crv(str) (one of Ed25519, Ed448, X25519, X448)
 
         Deprecated:
         Alternatively if the 'generate' parameter is provided, with a
         valid key type as value then a new key will be generated according
-        to the defaults or provided key strenght options (type specific).
+        to the defaults or provided key strength options (type specific).
 
         :raises InvalidJWKType: if the key type is invalid
         :raises InvalidJWKValue: if incorrect or inconsistent parameters
@@ -401,6 +404,8 @@
             return ec.SECP384R1()
         elif name == 'P-521':
             return ec.SECP521R1()
+        elif name == 'secp256k1':
+            return ec.SECP256K1()
         elif name in _OKP_CURVES_TABLE:
             return name
         else:
@@ -450,10 +455,16 @@
                                   'OKP key type' % params['crv'])
         self._import_pyca_pri_okp(key, **params)
 
+    def _okp_curve_from_pyca_key(self, key):
+        for name, val in iteritems(_OKP_CURVES_TABLE):
+            if isinstance(key, (val.pubkey, val.privkey)):
+                return name
+        raise InvalidJWKValue('Invalid OKP Key object %r' % key)
+
     def _import_pyca_pri_okp(self, key, **params):
         params.update(
             kty='OKP',
-            crv=params['crv'],
+            crv=self._okp_curve_from_pyca_key(key),
             d=base64url_encode(key.private_bytes(
                 serialization.Encoding.Raw,
                 serialization.PrivateFormat.Raw,
@@ -467,10 +478,10 @@
     def _import_pyca_pub_okp(self, key, **params):
         params.update(
             kty='OKP',
-            crv=params['crv'],
+            crv=self._okp_curve_from_pyca_key(key),
             x=base64url_encode(key.public_bytes(
                 serialization.Encoding.Raw,
-                serialization.PrivateFormat.Raw))
+                serialization.PublicFormat.Raw))
         )
         self.import_key(**params)
 
@@ -565,10 +576,10 @@
         obj.import_key(**jkey)
         return obj
 
-    def export(self, private_key=True):
+    def export(self, private_key=True, as_dict=False):
         """Exports the key in the standard JSON format.
         Exports the key regardless of type, if private_key is False
-        and the key is_symmetric an exceptionis raised.
+        and the key is_symmetric an exception is raised.
 
         :param private_key(bool): Whether to export the private key.
                                   Defaults to True.
@@ -576,16 +587,20 @@
         if private_key is True:
             # Use _export_all for backwards compatibility, as this
             # function allows to export symmetrict keys too
-            return self._export_all()
-        else:
-            return self.export_public()
+            return self._export_all(as_dict)
 
-    def export_public(self):
+        return self.export_public(as_dict)
+
+    def export_public(self, as_dict=False):
         """Exports the public key in the standard JSON format.
         It fails if one is not available like when this function
         is called on a symmetric key.
+
+        :param as_dict(bool): If set to True export as python dict not JSON
         """
         pub = self._public_params()
+        if as_dict is True:
+            return pub
         return json_encode(pub)
 
     def _public_params(self):
@@ -603,24 +618,28 @@
                 pub[param] = self._key[param]
         return pub
 
-    def _export_all(self):
+    def _export_all(self, as_dict=False):
         d = dict()
         d.update(self._params)
         d.update(self._key)
         d.update(self._unknown)
+        if as_dict is True:
+            return d
         return json_encode(d)
 
-    def export_private(self):
+    def export_private(self, as_dict=False):
         """Export the private key in the standard JSON format.
         It fails for a JWK that has only a public key or is symmetric.
+
+        :param as_dict(bool): If set to True export as python dict not JSON
         """
         if self.has_private:
-            return self._export_all()
+            return self._export_all(as_dict)
         raise InvalidJWKType("No private key available")
 
-    def export_symmetric(self):
+    def export_symmetric(self, as_dict=False):
         if self.is_symmetric:
-            return self._export_all()
+            return self._export_all(as_dict)
         raise InvalidJWKType("Not a symmetric key")
 
     def public(self):
@@ -767,12 +786,12 @@
             raise NotImplementedError
 
     def get_op_key(self, operation=None, arg=None):
-        """Get the key object associated to the requested opration.
+        """Get the key object associated to the requested operation.
         For example the public RSA key for the 'verify' operation or
         the private EC key for the 'decrypt' operation.
 
         :param operation: The requested operation.
-         The valid set of operations is availble in the
+         The valid set of operations is available in the
          :data:`JWKOperationsRegistry` registry.
         :param arg: an optional, context specific, argument
          For example a curve name.
@@ -936,7 +955,7 @@
 class JWKSet(dict):
     """A set of JWK objects.
 
-    Inherits from the standard 'dict' bultin type.
+    Inherits from the standard 'dict' builtin type.
     Creates a special key 'keys' that is of a type derived from 'set'
     The 'keys' attribute accepts only :class:`jwcrypto.jwk.JWK` elements.
     """
@@ -964,26 +983,31 @@
     def add(self, elem):
         self['keys'].add(elem)
 
-    def export(self, private_keys=True):
-        """Exports a RFC 7517 keyset using the standard JSON format
+    def export(self, private_keys=True, as_dict=False):
+        """Exports a RFC 7517 key set.
+           Exports as json by default, or as dict if requested.
 
         :param private_key(bool): Whether to export private keys.
                                   Defaults to True.
+        :param as_dict(bool): Whether to return a dict instead of
+                              a JSON object
         """
         exp_dict = dict()
         for k, v in iteritems(self):
             if k == 'keys':
                 keys = list()
                 for jwk in v:
-                    keys.append(json_decode(jwk.export(private_keys)))
+                    keys.append(jwk.export(private_keys, as_dict=True))
                 v = keys
             exp_dict[k] = v
+        if as_dict is True:
+            return exp_dict
         return json_encode(exp_dict)
 
     def import_keyset(self, keyset):
-        """Imports a RFC 7517 keyset using the standard JSON format.
+        """Imports a RFC 7517 key set using the standard JSON format.
 
-        :param keyset: The RFC 7517 representation of a JOSE Keyset.
+        :param keyset: The RFC 7517 representation of a JOSE key set.
         """
         try:
             jwkset = json_decode(keyset)
@@ -1002,9 +1026,9 @@
 
     @classmethod
     def from_json(cls, keyset):
-        """Creates a RFC 7517 keyset from the standard JSON format.
+        """Creates a RFC 7517 key set from the standard JSON format.
 
-        :param keyset: The RFC 7517 representation of a JOSE Keyset.
+        :param keyset: The RFC 7517 representation of a JOSE key set.
         """
         obj = cls()
         obj.import_keyset(keyset)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/jwcrypto/jws.py 
new/jwcrypto-0.8/jwcrypto/jws.py
--- old/jwcrypto-0.7/jwcrypto/jws.py    2020-02-19 17:12:20.000000000 +0100
+++ new/jwcrypto-0.8/jwcrypto/jws.py    2020-08-20 12:47:47.000000000 +0200
@@ -326,7 +326,7 @@
                 except Exception as e:  # pylint: disable=broad-except
                     self.verifylog.append('Failed: [%s]' % repr(e))
         else:
-            raise InvalidJWSSignature('No signatures availble')
+            raise InvalidJWSSignature('No signatures available')
 
         if not self.is_valid:
             raise InvalidJWSSignature('Verification failed for all '
@@ -373,7 +373,7 @@
         :param alg: The signing algorithm (optional). usually the algorithm
          is known as it is provided with the JOSE Headers of the token.
 
-        :raises InvalidJWSObject: if the raw object is an invaid JWS token.
+        :raises InvalidJWSObject: if the raw object is an invalid JWS token.
         :raises InvalidJWSSignature: if the verification fails.
         """
         self.objects = dict()
@@ -480,7 +480,9 @@
         if alg is None:
             raise ValueError('"alg" not specified')
 
-        c = JWSCore(alg, key, protected, self.objects['payload'])
+        c = JWSCore(
+            alg, key, protected, self.objects['payload'], self.allowed_algs
+        )
         sig = c.sign()
 
         o = dict()
@@ -516,7 +518,7 @@
          representation, otherwise generates a standard JSON format.
 
         :raises InvalidJWSOperation: if the object cannot serialized
-         with the compact representation and `compat` is True.
+         with the compact representation and `compact` is True.
         :raises InvalidJWSSignature: if no signature has been added
          to the object, or no valid signature can be found.
         """
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/jwcrypto/jwt.py 
new/jwcrypto-0.8/jwcrypto/jwt.py
--- old/jwcrypto-0.7/jwcrypto/jwt.py    2019-05-27 14:17:28.000000000 +0200
+++ new/jwcrypto-0.8/jwcrypto/jwt.py    2020-08-20 12:47:47.000000000 +0200
@@ -162,7 +162,7 @@
          the token. A (:class:`jwcrypto.jwk.JWKSet`) can also be used.
         :param algs: An optional list of allowed algorithms
         :param default_claims: An optional dict with default values for
-         registred claims. A None value for NumericDate type claims
+         registered claims. A None value for NumericDate type claims
          will cause generation according to system time. Only the values
          from RFC 7519 - 4.1 are evaluated.
         :param check_claims: An optional dict of claims that must be
@@ -171,7 +171,7 @@
 
         Note: either the header,claims or jwt,key parameters should be
         provided as a deserialization operation (which occurs if the jwt
-        is provided will wipe any header os claim provided by setting
+        is provided) will wipe any header or claim provided by setting
         those obtained from the deserialization of the jwt token.
 
         Note: if check_claims is not provided the 'exp' and 'nbf' claims
@@ -258,8 +258,8 @@
         return self._leeway
 
     @leeway.setter
-    def leeway(self, l):
-        self._leeway = int(l)
+    def leeway(self, lwy):
+        self._leeway = int(lwy)
 
     @property
     def validity(self):
@@ -418,12 +418,14 @@
 
         Creates a JWS token with the header as the JWS protected header and
         the claims as the payload. See (:class:`jwcrypto.jws.JWS`) for
-        details on the exceptions that may be reaised.
+        details on the exceptions that may be raised.
 
         :param key: A (:class:`jwcrypto.jwk.JWK`) key.
         """
 
         t = JWS(self.claims)
+        if self._algs:
+            t.allowed_algs = self._algs
         t.add_signature(key, protected=self.header)
         self.token = t
 
@@ -432,7 +434,7 @@
 
         Creates a JWE token with the header as the JWE protected header and
         the claims as the plaintext. See (:class:`jwcrypto.jwe.JWE`) for
-        details on the exceptions that may be reaised.
+        details on the exceptions that may be raised.
 
         :param key: A (:class:`jwcrypto.jwk.JWK`) key.
         """
@@ -511,7 +513,7 @@
         Note: the compact parameter is provided for general compatibility
         with the serialize() functions of :class:`jwcrypto.jws.JWS` and
         :class:`jwcrypto.jwe.JWE` so that these objects can all be used
-        interchangeably. However the only valid JWT representtion is the
+        interchangeably. However the only valid JWT representation is the
         compact representation.
         """
         return self.token.serialize(compact)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/jwcrypto/tests.py 
new/jwcrypto-0.8/jwcrypto/tests.py
--- old/jwcrypto-0.7/jwcrypto/tests.py  2020-02-19 17:12:20.000000000 +0100
+++ new/jwcrypto-0.8/jwcrypto/tests.py  2020-08-20 12:47:47.000000000 +0200
@@ -259,6 +259,39 @@
     ]
 }
 
+PublicKeys_secp256k1 = {
+    "keys": [
+        {
+            "kty": "EC",
+            "crv": "secp256k1",
+            "x": "Ss6na3mcci8Ud4lQrjaB_T40sfKApEcl2RLIWOJdjow",
+            "y": "7l9qIKtKPW6oEiOYBt7r22Sm0mtFJU-yBkkvMvpscd8"
+        }
+    ]
+}
+
+PrivateKeys_secp256k1 = {
+    "keys": [
+        {
+            "kty": "EC",
+            "crv": "secp256k1",
+            "x": "Ss6na3mcci8Ud4lQrjaB_T40sfKApEcl2RLIWOJdjow",
+            "y": "7l9qIKtKPW6oEiOYBt7r22Sm0mtFJU-yBkkvMvpscd8",
+            "d": "GYhU2vrYGZrjLZn71Xniqm54Mi53xiYtaTLawzaf9dA"
+        },
+    ]
+}
+
+Ed25519PrivatePEM = b"""-----BEGIN PRIVATE KEY-----
+MC4CAQAwBQYDK2VwBCIEIEh4ImJiiZgSNg9J9I+Z5toHKh6LDO2MCbSYNZTkMXDU
+-----END PRIVATE KEY-----
+"""
+
+Ed25519PublicPEM = b"""-----BEGIN PUBLIC KEY-----
+MCowBQYDK2VwAyEAlsRcb1mVVIUcDjNqZU27N+iPXihH1EQDa/O3utHLtqc=
+-----END PUBLIC KEY-----
+"""
+
 
 class TestJWK(unittest.TestCase):
     def test_create_pubKeys(self):
@@ -319,6 +352,9 @@
         # New param prevails
         key = jwk.JWK.generate(kty='EC', curve='P-256', crv='P-521')
         key.get_curve('P-521')
+        # New secp256k curve
+        key = jwk.JWK.generate(kty='EC', curve='secp256k1')
+        key.get_curve('secp256k1')
 
     def test_generate_OKP_keys(self):
         for crv in jwk.ImplementedOkpCurves:
@@ -364,7 +400,7 @@
         ks3 = jwk.JWKSet.from_json(ks.export())
         self.assertEqual(len(ks), len(ks3))
 
-        # Test Keyset with mutiple keys
+        # Test key set with mutiple keys
         ksm = jwk.JWKSet.from_json(json_encode(PrivateKeys))
         num = 0
         for item in ksm:
@@ -422,6 +458,21 @@
         self.assertFalse(pubkey.has_private)
         self.assertEqual(prikey.key_id, pubkey.key_id)
 
+    def test_export_as_dict(self):
+        key = jwk.JWK(**SymmetricKeys['keys'][1])
+        k = key.export_symmetric(as_dict=True)
+        self.assertEqual(k['kid'], SymmetricKeys['keys'][1]['kid'])
+        key = jwk.JWK.from_pem(PublicCert)
+        k = key.export_public(as_dict=True)
+        self.assertEqual(k['kid'], PublicCertThumbprint)
+        key = jwk.JWK.from_pem(RSAPrivatePEM, password=RSAPrivatePassword)
+        k = key.export_private(as_dict=True)
+        self.assertEqual(k['kid'],
+                         u'x31vrbZceU2qOPLtrUwPkLa3PNakMn9tOsq_ntFVrJc')
+        keyset = jwk.JWKSet.from_json(json_encode(PrivateKeys))
+        ks = keyset.export(as_dict=True)
+        self.assertTrue('keys' in ks)
+
     def test_public(self):
         key = jwk.JWK.from_pem(RSAPrivatePEM, password=RSAPrivatePassword)
         self.assertTrue(key.has_public)
@@ -451,6 +502,16 @@
         for key in keylist:
             jwk.JWK(**key)
 
+    def test_create_pubKeys_secp256k1(self):
+        keylist = PublicKeys_secp256k1['keys']
+        for key in keylist:
+            jwk.JWK(**key)
+
+    def test_create_priKeys_secp256k1(self):
+        keylist = PrivateKeys_secp256k1['keys']
+        for key in keylist:
+            jwk.JWK(**key)
+
     def test_thumbprint_eddsa(self):
         for i in range(0, len(PublicKeys_EdDsa['keys'])):
             k = jwk.JWK(**PublicKeys_EdDsa['keys'][i])
@@ -458,6 +519,22 @@
                 k.thumbprint(),
                 PublicKeys_EdDsa['thumbprints'][i])
 
+    def test_pem_okp(self):
+        payload = b'Imported private Ed25519'
+        prikey = jwk.JWK.from_pem(Ed25519PrivatePEM)
+        self.assertTrue(prikey.has_private)
+        self.assertTrue(prikey.has_public)
+        s = jws.JWS(payload)
+        s.add_signature(prikey, None, {'alg': 'EdDSA'}, None)
+        sig = s.serialize()
+        pubkey = jwk.JWK.from_pem(Ed25519PublicPEM)
+        self.assertTrue(pubkey.has_public)
+        self.assertFalse(pubkey.has_private)
+        c = jws.JWS()
+        c.deserialize(sig, pubkey, alg="EdDSA")
+        self.assertTrue(c.objects['valid'])
+        self.assertEqual(c.payload, payload)
+
 
 # RFC 7515 - A.1
 A1_protected = \
@@ -786,6 +863,19 @@
             self.assertEqual(jws_verify.payload.decode('utf-8'),
                              curve_example['payload'])
 
+    def test_secp256k1_signing_and_verification(self):
+        key = jwk.JWK(**PrivateKeys_secp256k1['keys'][0])
+        payload = bytes(bytearray(A1_payload))
+        jws_test = jws.JWS(payload)
+        jws_test.allowed_algs = ['ES256K']
+        jws_test.add_signature(key, None, json_encode({"alg": "ES256K"}), None)
+        jws_test_serialization_compact = jws_test.serialize(compact=True)
+        jws_verify = jws.JWS()
+        jws_verify.allowed_algs = ['ES256K']
+        jws_verify.deserialize(jws_test_serialization_compact)
+        jws_verify.verify(key.public())
+        self.assertEqual(jws_verify.payload, payload)
+
 
 E_A1_plaintext = \
     [84, 104, 101, 32, 116, 114, 117, 101, 32, 115, 105, 103, 110, 32,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/jwcrypto.egg-info/PKG-INFO 
new/jwcrypto-0.8/jwcrypto.egg-info/PKG-INFO
--- old/jwcrypto-0.7/jwcrypto.egg-info/PKG-INFO 2020-02-19 18:17:34.000000000 
+0100
+++ new/jwcrypto-0.8/jwcrypto.egg-info/PKG-INFO 2020-08-20 12:48:07.000000000 
+0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: jwcrypto
-Version: 0.7
+Version: 0.8
 Summary: Implementation of JOSE Web standards
 Home-page: https://github.com/latchset/jwcrypto
 Maintainer: JWCrypto Project Contributors
@@ -13,6 +13,7 @@
 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: Intended Audience :: Developers
 Classifier: Topic :: Security
 Classifier: Topic :: Software Development :: Libraries :: Python Modules
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/jwcrypto.egg-info/requires.txt 
new/jwcrypto-0.8/jwcrypto.egg-info/requires.txt
--- old/jwcrypto-0.7/jwcrypto.egg-info/requires.txt     2020-02-19 
18:17:34.000000000 +0100
+++ new/jwcrypto-0.8/jwcrypto.egg-info/requires.txt     2020-08-20 
12:48:07.000000000 +0200
@@ -1 +1 @@
-cryptography>=1.5
+cryptography>=2.3
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/setup.py new/jwcrypto-0.8/setup.py
--- old/jwcrypto-0.7/setup.py   2020-02-19 18:15:54.000000000 +0100
+++ new/jwcrypto-0.8/setup.py   2020-08-20 12:47:47.000000000 +0200
@@ -6,7 +6,7 @@
 
 setup(
     name = 'jwcrypto',
-    version = '0.7',
+    version = '0.8',
     license = 'LGPLv3+',
     maintainer = 'JWCrypto Project Contributors',
     maintainer_email = '[email protected]',
@@ -19,12 +19,13 @@
         'Programming Language :: Python :: 3.5',
         'Programming Language :: Python :: 3.6',
         'Programming Language :: Python :: 3.7',
+        'Programming Language :: Python :: 3.8',
         'Intended Audience :: Developers',
         'Topic :: Security',
         'Topic :: Software Development :: Libraries :: Python Modules'
     ],
     data_files = [('share/doc/jwcrypto', ['LICENSE', 'README.md'])],
     install_requires = [
-        'cryptography >= 1.5',
+        'cryptography >= 2.3',
     ],
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/jwcrypto-0.7/tox.ini new/jwcrypto-0.8/tox.ini
--- old/jwcrypto-0.7/tox.ini    2020-02-19 17:12:20.000000000 +0100
+++ new/jwcrypto-0.8/tox.ini    2020-08-20 12:47:47.000000000 +0200
@@ -50,10 +50,10 @@
     markdown_py README.md -f {toxworkdir}/README.md.html
 
 [testenv:sphinx]
-basepython = python2.7
+basepython = python3
 changedir = docs/source
 deps =
-    sphinx < 1.3.0
+    sphinx
 commands =
     sphinx-build -v -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
 


Reply via email to