|
| 1 | +import base64 |
| 2 | +import hashlib |
1 | 3 | import json |
| 4 | +import ssl |
2 | 5 | from typing import List |
3 | 6 |
|
| 7 | +from .utils import DIGEST_HASH |
4 | 8 | from ..exception import UnsupportedAlgorithm |
| 9 | +from ..utils import as_bytes |
5 | 10 | from ..utils import as_unicode |
6 | 11 | from ..utils import b64e |
7 | 12 | from ..utils import base64url_to_long |
8 | | -from .utils import DIGEST_HASH |
9 | 13 |
|
10 | 14 | USE = { |
11 | 15 | 'sign': 'sig', |
12 | 16 | 'decrypt': 'enc', |
13 | 17 | 'encrypt': 'enc', |
14 | 18 | 'verify': 'sig' |
15 | | - } |
| 19 | +} |
16 | 20 |
|
17 | 21 |
|
18 | 22 | class JWK(object): |
@@ -46,7 +50,7 @@ def __init__(self, kty="", alg="", use="", kid="", x5c=None, |
46 | 50 | # The list comes from https://tools.ietf.org/html/rfc7518#page-6 |
47 | 51 | # Should map against SIGNER_ALGS in cryptojwt.jws.jws |
48 | 52 | if alg not in ["HS256", "HS384", "HS512", "RS256", "RS384", |
49 | | - "RS512", "ES256", "ES384","ES512", "PS256", |
| 53 | + "RS512", "ES256", "ES384", "ES512", "PS256", |
50 | 54 | "PS384", "PS512", "none"]: |
51 | 55 | raise UnsupportedAlgorithm("Unknown algorithm: {}".format(alg)) |
52 | 56 |
|
@@ -232,3 +236,57 @@ def appropriate_for(self, usage, **kwargs): |
232 | 236 | return self.use == USE[usage] |
233 | 237 | elif self.key_ops: |
234 | 238 | return usage in self.key_ops |
| 239 | + |
| 240 | + |
| 241 | +def pems_to_x5c(cert_chain): |
| 242 | + """ |
| 243 | + Takes a list of PEM formated certificates and transforms them into a x5c attribute |
| 244 | + values as described in RFC 7517. |
| 245 | +
|
| 246 | + :param cert_pem: List of PKIX certificates |
| 247 | + :return: List of strings |
| 248 | + """ |
| 249 | + |
| 250 | + return [as_unicode(v) for v in |
| 251 | + [base64.b64encode(d) for d in [ssl.PEM_cert_to_DER_cert(c) for c in cert_chain]]] |
| 252 | + |
| 253 | + |
| 254 | +def x5c_to_pems(x5c): |
| 255 | + """ |
| 256 | + Takes a x5c value from a JWK and converts it into a list of PEM formated certificates. |
| 257 | +
|
| 258 | + :param x5c: List of strings |
| 259 | + :return: |
| 260 | + """ |
| 261 | + |
| 262 | + return [ssl.DER_cert_to_PEM_cert(d) for d in |
| 263 | + [base64.b64decode(x) for x in [as_bytes(y) for y in x5c]]] |
| 264 | + |
| 265 | + |
| 266 | +def x5c_to_ders(x5c): |
| 267 | + """ |
| 268 | + Takes a x5c value from a JWK and converts it into a list of PEM formated certificates. |
| 269 | +
|
| 270 | + :param x5c: List of strings |
| 271 | + :return: |
| 272 | + """ |
| 273 | + |
| 274 | + return [base64.b64decode(x) for x in [as_bytes(y) for y in x5c]] |
| 275 | + |
| 276 | + |
| 277 | +def certificate_fingerprint(der, hash="sha256"): |
| 278 | + """ |
| 279 | +
|
| 280 | + :param der: DER encoded certificate |
| 281 | + :return: |
| 282 | + """ |
| 283 | + if hash == "sha256": |
| 284 | + fp = hashlib.sha256(as_bytes(der)).hexdigest() |
| 285 | + elif hash == "sha1": |
| 286 | + fp = hashlib.sha1(as_bytes(der)).hexdigest() |
| 287 | + elif hash == "md5": |
| 288 | + fp = hashlib.md5(as_bytes(der)).hexdigest() |
| 289 | + else: |
| 290 | + raise UnsupportedAlgorithm(hash) |
| 291 | + |
| 292 | + return ':'.join([fp[i:i + 2] for i in range(0, len(fp), 2)]).upper() |
0 commit comments