We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
jwk thumbprint is mismade
The JWK.thumbprint method isn't quite right. 

I think the problem is that the `json.dumps` the thumbprint method uses can mis-order the keys in the JSON hash. There is an order that [RFC7638](https://tools.ietf.org/html/rfc7638#section-3.3) says the keys must be in. The go-jose code does that with this line of code: https://github.com/square/go-jose/blob/4ddd71883fa547d37fbf598071f04512d8bafee3/jwk.go#L155

Going off the go-jose test vectors, this RSA public key JWK: 

```
{
    "kty": "RSA",
    "kid": "bilbo.baggins@hobbiton.example",
    "use": "sig",
    "n": "n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT-O-XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqVwGU_NsYOYL-QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj-oBHqFEHYpPe7Tpe-OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde3uhGqC0ZCuEHg8lhzwOHrtIQbS0FVbb9k3-tVTU4fg_3L_vniUFAKwuCLqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5iaiQkqgc5gHdrNP5zw",
 "e": "AQAB"
}
```

must be thumbprinted into `f63838e96077ad1fc01c3f8405774dedc0641f558ebb4b40dccf5f9b6d66a932`.

In case I fat-fingered the key or its hash, here they are in the go-jose tests: https://github.com/square/go-jose/blob/4ddd71883fa547d37fbf598071f04512d8bafee3/jwk_test.go#L331-L344 and https://github.com/square/go-jose/blob/4ddd71883fa547d37fbf598071f04512d8bafee3/jwk_test.go#L384


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `acme/acme/jose/jwk.py`
Content:
```
1 """JSON Web Key."""
2 import abc
3 import binascii
4 import json
5 import logging
6 
7 import cryptography.exceptions
8 from cryptography.hazmat.backends import default_backend
9 from cryptography.hazmat.primitives import hashes
10 from cryptography.hazmat.primitives import serialization
11 from cryptography.hazmat.primitives.asymmetric import ec
12 from cryptography.hazmat.primitives.asymmetric import rsa
13 
14 import six
15 
16 from acme.jose import errors
17 from acme.jose import json_util
18 from acme.jose import util
19 
20 
21 logger = logging.getLogger(__name__)
22 
23 
24 class JWK(json_util.TypedJSONObjectWithFields):
25     # pylint: disable=too-few-public-methods
26     """JSON Web Key."""
27     type_field_name = 'kty'
28     TYPES = {}
29     cryptography_key_types = ()
30     """Subclasses should override."""
31 
32     required = NotImplemented
33     """Required members of public key's representation as defined by JWK/JWA."""
34 
35     _thumbprint_json_dumps_params = {
36         # "no whitespace or line breaks before or after any syntactic
37         # elements"
38         'indent': 0,
39         'separators': (',', ':'),
40         # "members ordered lexicographically by the Unicode [UNICODE]
41         # code points of the member names"
42         'sort_keys': True,
43     }
44 
45     def thumbprint(self, hash_function=hashes.SHA256):
46         """Compute JWK Thumbprint.
47 
48         https://tools.ietf.org/html/rfc7638
49 
50         """
51         digest = hashes.Hash(hash_function(), backend=default_backend())
52         digest.update(json.dumps(
53             dict((k, v) for k, v in six.iteritems(self.to_json())
54                  if k in self.required),
55             **self._thumbprint_json_dumps_params).encode())
56         return digest.finalize()
57 
58     @abc.abstractmethod
59     def public_key(self):  # pragma: no cover
60         """Generate JWK with public key.
61 
62         For symmetric cryptosystems, this would return ``self``.
63 
64         """
65         raise NotImplementedError()
66 
67     @classmethod
68     def _load_cryptography_key(cls, data, password=None, backend=None):
69         backend = default_backend() if backend is None else backend
70         exceptions = {}
71 
72         # private key?
73         for loader in (serialization.load_pem_private_key,
74                        serialization.load_der_private_key):
75             try:
76                 return loader(data, password, backend)
77             except (ValueError, TypeError,
78                     cryptography.exceptions.UnsupportedAlgorithm) as error:
79                 exceptions[loader] = error
80 
81         # public key?
82         for loader in (serialization.load_pem_public_key,
83                        serialization.load_der_public_key):
84             try:
85                 return loader(data, backend)
86             except (ValueError,
87                     cryptography.exceptions.UnsupportedAlgorithm) as error:
88                 exceptions[loader] = error
89 
90         # no luck
91         raise errors.Error('Unable to deserialize key: {0}'.format(exceptions))
92 
93     @classmethod
94     def load(cls, data, password=None, backend=None):
95         """Load serialized key as JWK.
96 
97         :param str data: Public or private key serialized as PEM or DER.
98         :param str password: Optional password.
99         :param backend: A `.PEMSerializationBackend` and
100             `.DERSerializationBackend` provider.
101 
102         :raises errors.Error: if unable to deserialize, or unsupported
103             JWK algorithm
104 
105         :returns: JWK of an appropriate type.
106         :rtype: `JWK`
107 
108         """
109         try:
110             key = cls._load_cryptography_key(data, password, backend)
111         except errors.Error as error:
112             logger.debug('Loading symmetric key, assymentric failed: %s', error)
113             return JWKOct(key=data)
114 
115         if cls.typ is not NotImplemented and not isinstance(
116                 key, cls.cryptography_key_types):
117             raise errors.Error('Unable to deserialize {0} into {1}'.format(
118                 key.__class__, cls.__class__))
119         for jwk_cls in six.itervalues(cls.TYPES):
120             if isinstance(key, jwk_cls.cryptography_key_types):
121                 return jwk_cls(key=key)
122         raise errors.Error('Unsupported algorithm: {0}'.format(key.__class__))
123 
124 
125 @JWK.register
126 class JWKES(JWK):  # pragma: no cover
127     # pylint: disable=abstract-class-not-used
128     """ES JWK.
129 
130     .. warning:: This is not yet implemented!
131 
132     """
133     typ = 'ES'
134     cryptography_key_types = (
135         ec.EllipticCurvePublicKey, ec.EllipticCurvePrivateKey)
136     required = ('crv', JWK.type_field_name, 'x', 'y')
137 
138     def fields_to_partial_json(self):
139         raise NotImplementedError()
140 
141     @classmethod
142     def fields_from_json(cls, jobj):
143         raise NotImplementedError()
144 
145     def public_key(self):
146         raise NotImplementedError()
147 
148 
149 @JWK.register
150 class JWKOct(JWK):
151     """Symmetric JWK."""
152     typ = 'oct'
153     __slots__ = ('key',)
154     required = ('k', JWK.type_field_name)
155 
156     def fields_to_partial_json(self):
157         # TODO: An "alg" member SHOULD also be present to identify the
158         # algorithm intended to be used with the key, unless the
159         # application uses another means or convention to determine
160         # the algorithm used.
161         return {'k': json_util.encode_b64jose(self.key)}
162 
163     @classmethod
164     def fields_from_json(cls, jobj):
165         return cls(key=json_util.decode_b64jose(jobj['k']))
166 
167     def public_key(self):
168         return self
169 
170 
171 @JWK.register
172 class JWKRSA(JWK):
173     """RSA JWK.
174 
175     :ivar key: `cryptography.hazmat.primitives.rsa.RSAPrivateKey`
176         or `cryptography.hazmat.primitives.rsa.RSAPublicKey` wrapped
177         in `.ComparableRSAKey`
178 
179     """
180     typ = 'RSA'
181     cryptography_key_types = (rsa.RSAPublicKey, rsa.RSAPrivateKey)
182     __slots__ = ('key',)
183     required = ('e', JWK.type_field_name, 'n')
184 
185     def __init__(self, *args, **kwargs):
186         if 'key' in kwargs and not isinstance(
187                 kwargs['key'], util.ComparableRSAKey):
188             kwargs['key'] = util.ComparableRSAKey(kwargs['key'])
189         super(JWKRSA, self).__init__(*args, **kwargs)
190 
191     @classmethod
192     def _encode_param(cls, data):
193         """Encode Base64urlUInt.
194 
195         :type data: long
196         :rtype: unicode
197 
198         """
199         def _leading_zeros(arg):
200             if len(arg) % 2:
201                 return '0' + arg
202             return arg
203 
204         return json_util.encode_b64jose(binascii.unhexlify(
205             _leading_zeros(hex(data)[2:].rstrip('L'))))
206 
207     @classmethod
208     def _decode_param(cls, data):
209         """Decode Base64urlUInt."""
210         try:
211             return int(binascii.hexlify(json_util.decode_b64jose(data)), 16)
212         except ValueError:  # invalid literal for long() with base 16
213             raise errors.DeserializationError()
214 
215     def public_key(self):
216         return type(self)(key=self.key.public_key())
217 
218     @classmethod
219     def fields_from_json(cls, jobj):
220         # pylint: disable=invalid-name
221         n, e = (cls._decode_param(jobj[x]) for x in ('n', 'e'))
222         public_numbers = rsa.RSAPublicNumbers(e=e, n=n)
223         if 'd' not in jobj:  # public key
224             key = public_numbers.public_key(default_backend())
225         else:  # private key
226             d = cls._decode_param(jobj['d'])
227             if ('p' in jobj or 'q' in jobj or 'dp' in jobj or
228                     'dq' in jobj or 'qi' in jobj or 'oth' in jobj):
229                 # "If the producer includes any of the other private
230                 # key parameters, then all of the others MUST be
231                 # present, with the exception of "oth", which MUST
232                 # only be present when more than two prime factors
233                 # were used."
234                 p, q, dp, dq, qi, = all_params = tuple(
235                     jobj.get(x) for x in ('p', 'q', 'dp', 'dq', 'qi'))
236                 if tuple(param for param in all_params if param is None):
237                     raise errors.Error(
238                         'Some private parameters are missing: {0}'.format(
239                             all_params))
240                 p, q, dp, dq, qi = tuple(
241                     cls._decode_param(x) for x in all_params)
242 
243                 # TODO: check for oth
244             else:
245                 # cryptography>=0.8
246                 p, q = rsa.rsa_recover_prime_factors(n, e, d)
247                 dp = rsa.rsa_crt_dmp1(d, p)
248                 dq = rsa.rsa_crt_dmq1(d, q)
249                 qi = rsa.rsa_crt_iqmp(p, q)
250 
251             key = rsa.RSAPrivateNumbers(
252                 p, q, d, dp, dq, qi, public_numbers).private_key(
253                     default_backend())
254 
255         return cls(key=key)
256 
257     def fields_to_partial_json(self):
258         # pylint: disable=protected-access
259         if isinstance(self.key._wrapped, rsa.RSAPublicKey):
260             numbers = self.key.public_numbers()
261             params = {
262                 'n': numbers.n,
263                 'e': numbers.e,
264             }
265         else:  # rsa.RSAPrivateKey
266             private = self.key.private_numbers()
267             public = self.key.public_key().public_numbers()
268             params = {
269                 'n': public.n,
270                 'e': public.e,
271                 'd': private.d,
272                 'p': private.p,
273                 'q': private.q,
274                 'dp': private.dmp1,
275                 'dq': private.dmq1,
276                 'qi': private.iqmp,
277             }
278         return dict((key, self._encode_param(value))
279                     for key, value in six.iteritems(params))
280
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/acme/acme/jose/jwk.py b/acme/acme/jose/jwk.py
--- a/acme/acme/jose/jwk.py
+++ b/acme/acme/jose/jwk.py
@@ -35,7 +35,7 @@
     _thumbprint_json_dumps_params = {
         # "no whitespace or line breaks before or after any syntactic
         # elements"
-        'indent': 0,
+        'indent': None,
         'separators': (',', ':'),
         # "members ordered lexicographically by the Unicode [UNICODE]
         # code points of the member names"

{"golden_diff": "diff --git a/acme/acme/jose/jwk.py b/acme/acme/jose/jwk.py\n--- a/acme/acme/jose/jwk.py\n+++ b/acme/acme/jose/jwk.py\n@@ -35,7 +35,7 @@\n     _thumbprint_json_dumps_params = {\n         # \"no whitespace or line breaks before or after any syntactic\n         # elements\"\n-        'indent': 0,\n+        'indent': None,\n         'separators': (',', ':'),\n         # \"members ordered lexicographically by the Unicode [UNICODE]\n         # code points of the member names\"\n", "issue": "jwk thumbprint is mismade\nThe JWK.thumbprint method isn't quite right. \n\nI think the problem is that the `json.dumps` the thumbprint method uses can mis-order the keys in the JSON hash. There is an order that [RFC7638](https://tools.ietf.org/html/rfc7638#section-3.3) says the keys must be in. The go-jose code does that with this line of code: https://github.com/square/go-jose/blob/4ddd71883fa547d37fbf598071f04512d8bafee3/jwk.go#L155\n\nGoing off the go-jose test vectors, this RSA public key JWK: \n\n```\n{\n    \"kty\": \"RSA\",\n    \"kid\": \"bilbo.baggins@hobbiton.example\",\n    \"use\": \"sig\",\n    \"n\": \"n4EPtAOCc9AlkeQHPzHStgAbgs7bTZLwUBZdR8_KuKPEHLd4rHVTeT-O-XV2jRojdNhxJWTDvNd7nqQ0VEiZQHz_AJmSCpMaJMRBSFKrKb2wqVwGU_NsYOYL-QtiWN2lbzcEe6XC0dApr5ydQLrHqkHHig3RBordaZ6Aj-oBHqFEHYpPe7Tpe-OfVfHd1E6cS6M1FZcD1NNLYD5lFHpPI9bTwJlsde3uhGqC0ZCuEHg8lhzwOHrtIQbS0FVbb9k3-tVTU4fg_3L_vniUFAKwuCLqKnS2BYwdq_mzSnbLY7h_qixoR7jig3__kRhuaxwUkRz5iaiQkqgc5gHdrNP5zw\",\n \"e\": \"AQAB\"\n}\n```\n\nmust be thumbprinted into `f63838e96077ad1fc01c3f8405774dedc0641f558ebb4b40dccf5f9b6d66a932`.\n\nIn case I fat-fingered the key or its hash, here they are in the go-jose tests: https://github.com/square/go-jose/blob/4ddd71883fa547d37fbf598071f04512d8bafee3/jwk_test.go#L331-L344 and https://github.com/square/go-jose/blob/4ddd71883fa547d37fbf598071f04512d8bafee3/jwk_test.go#L384\n\n", "before_files": [{"content": "\"\"\"JSON Web Key.\"\"\"\nimport abc\nimport binascii\nimport json\nimport logging\n\nimport cryptography.exceptions\nfrom cryptography.hazmat.backends import default_backend\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives import serialization\nfrom cryptography.hazmat.primitives.asymmetric import ec\nfrom cryptography.hazmat.primitives.asymmetric import rsa\n\nimport six\n\nfrom acme.jose import errors\nfrom acme.jose import json_util\nfrom acme.jose import util\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass JWK(json_util.TypedJSONObjectWithFields):\n    # pylint: disable=too-few-public-methods\n    \"\"\"JSON Web Key.\"\"\"\n    type_field_name = 'kty'\n    TYPES = {}\n    cryptography_key_types = ()\n    \"\"\"Subclasses should override.\"\"\"\n\n    required = NotImplemented\n    \"\"\"Required members of public key's representation as defined by JWK/JWA.\"\"\"\n\n    _thumbprint_json_dumps_params = {\n        # \"no whitespace or line breaks before or after any syntactic\n        # elements\"\n        'indent': 0,\n        'separators': (',', ':'),\n        # \"members ordered lexicographically by the Unicode [UNICODE]\n        # code points of the member names\"\n        'sort_keys': True,\n    }\n\n    def thumbprint(self, hash_function=hashes.SHA256):\n        \"\"\"Compute JWK Thumbprint.\n\n        https://tools.ietf.org/html/rfc7638\n\n        \"\"\"\n        digest = hashes.Hash(hash_function(), backend=default_backend())\n        digest.update(json.dumps(\n            dict((k, v) for k, v in six.iteritems(self.to_json())\n                 if k in self.required),\n            **self._thumbprint_json_dumps_params).encode())\n        return digest.finalize()\n\n    @abc.abstractmethod\n    def public_key(self):  # pragma: no cover\n        \"\"\"Generate JWK with public key.\n\n        For symmetric cryptosystems, this would return ``self``.\n\n        \"\"\"\n        raise NotImplementedError()\n\n    @classmethod\n    def _load_cryptography_key(cls, data, password=None, backend=None):\n        backend = default_backend() if backend is None else backend\n        exceptions = {}\n\n        # private key?\n        for loader in (serialization.load_pem_private_key,\n                       serialization.load_der_private_key):\n            try:\n                return loader(data, password, backend)\n            except (ValueError, TypeError,\n                    cryptography.exceptions.UnsupportedAlgorithm) as error:\n                exceptions[loader] = error\n\n        # public key?\n        for loader in (serialization.load_pem_public_key,\n                       serialization.load_der_public_key):\n            try:\n                return loader(data, backend)\n            except (ValueError,\n                    cryptography.exceptions.UnsupportedAlgorithm) as error:\n                exceptions[loader] = error\n\n        # no luck\n        raise errors.Error('Unable to deserialize key: {0}'.format(exceptions))\n\n    @classmethod\n    def load(cls, data, password=None, backend=None):\n        \"\"\"Load serialized key as JWK.\n\n        :param str data: Public or private key serialized as PEM or DER.\n        :param str password: Optional password.\n        :param backend: A `.PEMSerializationBackend` and\n            `.DERSerializationBackend` provider.\n\n        :raises errors.Error: if unable to deserialize, or unsupported\n            JWK algorithm\n\n        :returns: JWK of an appropriate type.\n        :rtype: `JWK`\n\n        \"\"\"\n        try:\n            key = cls._load_cryptography_key(data, password, backend)\n        except errors.Error as error:\n            logger.debug('Loading symmetric key, assymentric failed: %s', error)\n            return JWKOct(key=data)\n\n        if cls.typ is not NotImplemented and not isinstance(\n                key, cls.cryptography_key_types):\n            raise errors.Error('Unable to deserialize {0} into {1}'.format(\n                key.__class__, cls.__class__))\n        for jwk_cls in six.itervalues(cls.TYPES):\n            if isinstance(key, jwk_cls.cryptography_key_types):\n                return jwk_cls(key=key)\n        raise errors.Error('Unsupported algorithm: {0}'.format(key.__class__))\n\n\n@JWK.register\nclass JWKES(JWK):  # pragma: no cover\n    # pylint: disable=abstract-class-not-used\n    \"\"\"ES JWK.\n\n    .. warning:: This is not yet implemented!\n\n    \"\"\"\n    typ = 'ES'\n    cryptography_key_types = (\n        ec.EllipticCurvePublicKey, ec.EllipticCurvePrivateKey)\n    required = ('crv', JWK.type_field_name, 'x', 'y')\n\n    def fields_to_partial_json(self):\n        raise NotImplementedError()\n\n    @classmethod\n    def fields_from_json(cls, jobj):\n        raise NotImplementedError()\n\n    def public_key(self):\n        raise NotImplementedError()\n\n\n@JWK.register\nclass JWKOct(JWK):\n    \"\"\"Symmetric JWK.\"\"\"\n    typ = 'oct'\n    __slots__ = ('key',)\n    required = ('k', JWK.type_field_name)\n\n    def fields_to_partial_json(self):\n        # TODO: An \"alg\" member SHOULD also be present to identify the\n        # algorithm intended to be used with the key, unless the\n        # application uses another means or convention to determine\n        # the algorithm used.\n        return {'k': json_util.encode_b64jose(self.key)}\n\n    @classmethod\n    def fields_from_json(cls, jobj):\n        return cls(key=json_util.decode_b64jose(jobj['k']))\n\n    def public_key(self):\n        return self\n\n\n@JWK.register\nclass JWKRSA(JWK):\n    \"\"\"RSA JWK.\n\n    :ivar key: `cryptography.hazmat.primitives.rsa.RSAPrivateKey`\n        or `cryptography.hazmat.primitives.rsa.RSAPublicKey` wrapped\n        in `.ComparableRSAKey`\n\n    \"\"\"\n    typ = 'RSA'\n    cryptography_key_types = (rsa.RSAPublicKey, rsa.RSAPrivateKey)\n    __slots__ = ('key',)\n    required = ('e', JWK.type_field_name, 'n')\n\n    def __init__(self, *args, **kwargs):\n        if 'key' in kwargs and not isinstance(\n                kwargs['key'], util.ComparableRSAKey):\n            kwargs['key'] = util.ComparableRSAKey(kwargs['key'])\n        super(JWKRSA, self).__init__(*args, **kwargs)\n\n    @classmethod\n    def _encode_param(cls, data):\n        \"\"\"Encode Base64urlUInt.\n\n        :type data: long\n        :rtype: unicode\n\n        \"\"\"\n        def _leading_zeros(arg):\n            if len(arg) % 2:\n                return '0' + arg\n            return arg\n\n        return json_util.encode_b64jose(binascii.unhexlify(\n            _leading_zeros(hex(data)[2:].rstrip('L'))))\n\n    @classmethod\n    def _decode_param(cls, data):\n        \"\"\"Decode Base64urlUInt.\"\"\"\n        try:\n            return int(binascii.hexlify(json_util.decode_b64jose(data)), 16)\n        except ValueError:  # invalid literal for long() with base 16\n            raise errors.DeserializationError()\n\n    def public_key(self):\n        return type(self)(key=self.key.public_key())\n\n    @classmethod\n    def fields_from_json(cls, jobj):\n        # pylint: disable=invalid-name\n        n, e = (cls._decode_param(jobj[x]) for x in ('n', 'e'))\n        public_numbers = rsa.RSAPublicNumbers(e=e, n=n)\n        if 'd' not in jobj:  # public key\n            key = public_numbers.public_key(default_backend())\n        else:  # private key\n            d = cls._decode_param(jobj['d'])\n            if ('p' in jobj or 'q' in jobj or 'dp' in jobj or\n                    'dq' in jobj or 'qi' in jobj or 'oth' in jobj):\n                # \"If the producer includes any of the other private\n                # key parameters, then all of the others MUST be\n                # present, with the exception of \"oth\", which MUST\n                # only be present when more than two prime factors\n                # were used.\"\n                p, q, dp, dq, qi, = all_params = tuple(\n                    jobj.get(x) for x in ('p', 'q', 'dp', 'dq', 'qi'))\n                if tuple(param for param in all_params if param is None):\n                    raise errors.Error(\n                        'Some private parameters are missing: {0}'.format(\n                            all_params))\n                p, q, dp, dq, qi = tuple(\n                    cls._decode_param(x) for x in all_params)\n\n                # TODO: check for oth\n            else:\n                # cryptography>=0.8\n                p, q = rsa.rsa_recover_prime_factors(n, e, d)\n                dp = rsa.rsa_crt_dmp1(d, p)\n                dq = rsa.rsa_crt_dmq1(d, q)\n                qi = rsa.rsa_crt_iqmp(p, q)\n\n            key = rsa.RSAPrivateNumbers(\n                p, q, d, dp, dq, qi, public_numbers).private_key(\n                    default_backend())\n\n        return cls(key=key)\n\n    def fields_to_partial_json(self):\n        # pylint: disable=protected-access\n        if isinstance(self.key._wrapped, rsa.RSAPublicKey):\n            numbers = self.key.public_numbers()\n            params = {\n                'n': numbers.n,\n                'e': numbers.e,\n            }\n        else:  # rsa.RSAPrivateKey\n            private = self.key.private_numbers()\n            public = self.key.public_key().public_numbers()\n            params = {\n                'n': public.n,\n                'e': public.e,\n                'd': private.d,\n                'p': private.p,\n                'q': private.q,\n                'dp': private.dmp1,\n                'dq': private.dmq1,\n                'qi': private.iqmp,\n            }\n        return dict((key, self._encode_param(value))\n                    for key, value in six.iteritems(params))\n", "path": "acme/acme/jose/jwk.py"}], "after_files": [{"content": "\"\"\"JSON Web Key.\"\"\"\nimport abc\nimport binascii\nimport json\nimport logging\n\nimport cryptography.exceptions\nfrom cryptography.hazmat.backends import default_backend\nfrom cryptography.hazmat.primitives import hashes\nfrom cryptography.hazmat.primitives import serialization\nfrom cryptography.hazmat.primitives.asymmetric import ec\nfrom cryptography.hazmat.primitives.asymmetric import rsa\n\nimport six\n\nfrom acme.jose import errors\nfrom acme.jose import json_util\nfrom acme.jose import util\n\n\nlogger = logging.getLogger(__name__)\n\n\nclass JWK(json_util.TypedJSONObjectWithFields):\n    # pylint: disable=too-few-public-methods\n    \"\"\"JSON Web Key.\"\"\"\n    type_field_name = 'kty'\n    TYPES = {}\n    cryptography_key_types = ()\n    \"\"\"Subclasses should override.\"\"\"\n\n    required = NotImplemented\n    \"\"\"Required members of public key's representation as defined by JWK/JWA.\"\"\"\n\n    _thumbprint_json_dumps_params = {\n        # \"no whitespace or line breaks before or after any syntactic\n        # elements\"\n        'indent': None,\n        'separators': (',', ':'),\n        # \"members ordered lexicographically by the Unicode [UNICODE]\n        # code points of the member names\"\n        'sort_keys': True,\n    }\n\n    def thumbprint(self, hash_function=hashes.SHA256):\n        \"\"\"Compute JWK Thumbprint.\n\n        https://tools.ietf.org/html/rfc7638\n\n        \"\"\"\n        digest = hashes.Hash(hash_function(), backend=default_backend())\n        digest.update(json.dumps(\n            dict((k, v) for k, v in six.iteritems(self.to_json())\n                 if k in self.required),\n            **self._thumbprint_json_dumps_params).encode())\n        return digest.finalize()\n\n    @abc.abstractmethod\n    def public_key(self):  # pragma: no cover\n        \"\"\"Generate JWK with public key.\n\n        For symmetric cryptosystems, this would return ``self``.\n\n        \"\"\"\n        raise NotImplementedError()\n\n    @classmethod\n    def _load_cryptography_key(cls, data, password=None, backend=None):\n        backend = default_backend() if backend is None else backend\n        exceptions = {}\n\n        # private key?\n        for loader in (serialization.load_pem_private_key,\n                       serialization.load_der_private_key):\n            try:\n                return loader(data, password, backend)\n            except (ValueError, TypeError,\n                    cryptography.exceptions.UnsupportedAlgorithm) as error:\n                exceptions[loader] = error\n\n        # public key?\n        for loader in (serialization.load_pem_public_key,\n                       serialization.load_der_public_key):\n            try:\n                return loader(data, backend)\n            except (ValueError,\n                    cryptography.exceptions.UnsupportedAlgorithm) as error:\n                exceptions[loader] = error\n\n        # no luck\n        raise errors.Error('Unable to deserialize key: {0}'.format(exceptions))\n\n    @classmethod\n    def load(cls, data, password=None, backend=None):\n        \"\"\"Load serialized key as JWK.\n\n        :param str data: Public or private key serialized as PEM or DER.\n        :param str password: Optional password.\n        :param backend: A `.PEMSerializationBackend` and\n            `.DERSerializationBackend` provider.\n\n        :raises errors.Error: if unable to deserialize, or unsupported\n            JWK algorithm\n\n        :returns: JWK of an appropriate type.\n        :rtype: `JWK`\n\n        \"\"\"\n        try:\n            key = cls._load_cryptography_key(data, password, backend)\n        except errors.Error as error:\n            logger.debug('Loading symmetric key, assymentric failed: %s', error)\n            return JWKOct(key=data)\n\n        if cls.typ is not NotImplemented and not isinstance(\n                key, cls.cryptography_key_types):\n            raise errors.Error('Unable to deserialize {0} into {1}'.format(\n                key.__class__, cls.__class__))\n        for jwk_cls in six.itervalues(cls.TYPES):\n            if isinstance(key, jwk_cls.cryptography_key_types):\n                return jwk_cls(key=key)\n        raise errors.Error('Unsupported algorithm: {0}'.format(key.__class__))\n\n\n@JWK.register\nclass JWKES(JWK):  # pragma: no cover\n    # pylint: disable=abstract-class-not-used\n    \"\"\"ES JWK.\n\n    .. warning:: This is not yet implemented!\n\n    \"\"\"\n    typ = 'ES'\n    cryptography_key_types = (\n        ec.EllipticCurvePublicKey, ec.EllipticCurvePrivateKey)\n    required = ('crv', JWK.type_field_name, 'x', 'y')\n\n    def fields_to_partial_json(self):\n        raise NotImplementedError()\n\n    @classmethod\n    def fields_from_json(cls, jobj):\n        raise NotImplementedError()\n\n    def public_key(self):\n        raise NotImplementedError()\n\n\n@JWK.register\nclass JWKOct(JWK):\n    \"\"\"Symmetric JWK.\"\"\"\n    typ = 'oct'\n    __slots__ = ('key',)\n    required = ('k', JWK.type_field_name)\n\n    def fields_to_partial_json(self):\n        # TODO: An \"alg\" member SHOULD also be present to identify the\n        # algorithm intended to be used with the key, unless the\n        # application uses another means or convention to determine\n        # the algorithm used.\n        return {'k': json_util.encode_b64jose(self.key)}\n\n    @classmethod\n    def fields_from_json(cls, jobj):\n        return cls(key=json_util.decode_b64jose(jobj['k']))\n\n    def public_key(self):\n        return self\n\n\n@JWK.register\nclass JWKRSA(JWK):\n    \"\"\"RSA JWK.\n\n    :ivar key: `cryptography.hazmat.primitives.rsa.RSAPrivateKey`\n        or `cryptography.hazmat.primitives.rsa.RSAPublicKey` wrapped\n        in `.ComparableRSAKey`\n\n    \"\"\"\n    typ = 'RSA'\n    cryptography_key_types = (rsa.RSAPublicKey, rsa.RSAPrivateKey)\n    __slots__ = ('key',)\n    required = ('e', JWK.type_field_name, 'n')\n\n    def __init__(self, *args, **kwargs):\n        if 'key' in kwargs and not isinstance(\n                kwargs['key'], util.ComparableRSAKey):\n            kwargs['key'] = util.ComparableRSAKey(kwargs['key'])\n        super(JWKRSA, self).__init__(*args, **kwargs)\n\n    @classmethod\n    def _encode_param(cls, data):\n        \"\"\"Encode Base64urlUInt.\n\n        :type data: long\n        :rtype: unicode\n\n        \"\"\"\n        def _leading_zeros(arg):\n            if len(arg) % 2:\n                return '0' + arg\n            return arg\n\n        return json_util.encode_b64jose(binascii.unhexlify(\n            _leading_zeros(hex(data)[2:].rstrip('L'))))\n\n    @classmethod\n    def _decode_param(cls, data):\n        \"\"\"Decode Base64urlUInt.\"\"\"\n        try:\n            return int(binascii.hexlify(json_util.decode_b64jose(data)), 16)\n        except ValueError:  # invalid literal for long() with base 16\n            raise errors.DeserializationError()\n\n    def public_key(self):\n        return type(self)(key=self.key.public_key())\n\n    @classmethod\n    def fields_from_json(cls, jobj):\n        # pylint: disable=invalid-name\n        n, e = (cls._decode_param(jobj[x]) for x in ('n', 'e'))\n        public_numbers = rsa.RSAPublicNumbers(e=e, n=n)\n        if 'd' not in jobj:  # public key\n            key = public_numbers.public_key(default_backend())\n        else:  # private key\n            d = cls._decode_param(jobj['d'])\n            if ('p' in jobj or 'q' in jobj or 'dp' in jobj or\n                    'dq' in jobj or 'qi' in jobj or 'oth' in jobj):\n                # \"If the producer includes any of the other private\n                # key parameters, then all of the others MUST be\n                # present, with the exception of \"oth\", which MUST\n                # only be present when more than two prime factors\n                # were used.\"\n                p, q, dp, dq, qi, = all_params = tuple(\n                    jobj.get(x) for x in ('p', 'q', 'dp', 'dq', 'qi'))\n                if tuple(param for param in all_params if param is None):\n                    raise errors.Error(\n                        'Some private parameters are missing: {0}'.format(\n                            all_params))\n                p, q, dp, dq, qi = tuple(\n                    cls._decode_param(x) for x in all_params)\n\n                # TODO: check for oth\n            else:\n                # cryptography>=0.8\n                p, q = rsa.rsa_recover_prime_factors(n, e, d)\n                dp = rsa.rsa_crt_dmp1(d, p)\n                dq = rsa.rsa_crt_dmq1(d, q)\n                qi = rsa.rsa_crt_iqmp(p, q)\n\n            key = rsa.RSAPrivateNumbers(\n                p, q, d, dp, dq, qi, public_numbers).private_key(\n                    default_backend())\n\n        return cls(key=key)\n\n    def fields_to_partial_json(self):\n        # pylint: disable=protected-access\n        if isinstance(self.key._wrapped, rsa.RSAPublicKey):\n            numbers = self.key.public_numbers()\n            params = {\n                'n': numbers.n,\n                'e': numbers.e,\n            }\n        else:  # rsa.RSAPrivateKey\n            private = self.key.private_numbers()\n            public = self.key.public_key().public_numbers()\n            params = {\n                'n': public.n,\n                'e': public.e,\n                'd': private.d,\n                'p': private.p,\n                'q': private.q,\n                'dp': private.dmp1,\n                'dq': private.dmq1,\n                'qi': private.iqmp,\n            }\n        return dict((key, self._encode_param(value))\n                    for key, value in six.iteritems(params))\n", "path": "acme/acme/jose/jwk.py"}]}