summaryrefslogtreecommitdiff
path: root/jwt/algorithms.py
diff options
context:
space:
mode:
authorJosé Padilla <jpadilla@webapplicate.com>2020-08-24 12:21:54 -0400
committerGitHub <noreply@github.com>2020-08-24 22:21:54 +0600
commit66e39be5349f4671b9f6cca8974691070406fa92 (patch)
tree74bcbf4a5d5bb68d7ecc52da5d7754631514dc43 /jwt/algorithms.py
parentf690976596bb74221f5a81fc9afffd5609bc4e70 (diff)
downloadpyjwt-66e39be5349f4671b9f6cca8974691070406fa92.tar.gz
Implementation of ECAlgorithm.from_jwk (#500)
* ECAlgorithm.to_jwk * Fix failing linting Co-authored-by: Evert Lammerts <evert@lucipher.net>
Diffstat (limited to 'jwt/algorithms.py')
-rw-r--r--jwt/algorithms.py62
1 files changed, 62 insertions, 0 deletions
diff --git a/jwt/algorithms.py b/jwt/algorithms.py
index 5723984..e555265 100644
--- a/jwt/algorithms.py
+++ b/jwt/algorithms.py
@@ -44,6 +44,7 @@ try:
Ed25519PrivateKey,
Ed25519PublicKey,
)
+ from cryptography.utils import int_from_bytes
has_crypto = True
except ImportError:
@@ -439,6 +440,67 @@ if has_crypto: # noqa: C901
except InvalidSignature:
return False
+ @staticmethod
+ def from_jwk(jwk):
+
+ try:
+ obj = json.loads(jwk)
+ except ValueError:
+ raise InvalidKeyError("Key is not valid JSON")
+
+ if obj.get("kty") != "EC":
+ raise InvalidKeyError("Not an Elliptic curve key")
+
+ if "x" not in obj or "y" not in obj:
+ raise InvalidKeyError("Not an Elliptic curve key")
+
+ x = base64url_decode(force_bytes(obj.get("x")))
+ y = base64url_decode(force_bytes(obj.get("y")))
+
+ curve = obj.get("crv")
+ if curve == "P-256":
+ if len(x) == len(y) == 32:
+ curve_obj = ec.SECP256R1()
+ else:
+ raise InvalidKeyError(
+ "Coords should be 32 bytes for curve P-256"
+ )
+ elif curve == "P-384":
+ if len(x) == len(y) == 48:
+ curve_obj = ec.SECP384R1()
+ else:
+ raise InvalidKeyError(
+ "Coords should be 48 bytes for curve P-384"
+ )
+ elif curve == "P-521":
+ if len(x) == len(y) == 66:
+ curve_obj = ec.SECP521R1()
+ else:
+ raise InvalidKeyError(
+ "Coords should be 66 bytes for curve P-521"
+ )
+ else:
+ raise InvalidKeyError("Invalid curve: {}".format(curve))
+
+ public_numbers = ec.EllipticCurvePublicNumbers(
+ x=int_from_bytes(x, "big"),
+ y=int_from_bytes(y, "big"),
+ curve=curve_obj,
+ )
+
+ if "d" not in obj:
+ return public_numbers.public_key(default_backend())
+
+ d = base64url_decode(force_bytes(obj.get("d")))
+ if len(d) != len(x):
+ raise InvalidKeyError(
+ "D should be {} bytes for curve {}", len(x), curve
+ )
+
+ return ec.EllipticCurvePrivateNumbers(
+ int_from_bytes(d, "big"), public_numbers
+ ).private_key(default_backend())
+
class RSAPSSAlgorithm(RSAAlgorithm):
"""
Performs a signature using RSASSA-PSS with MGF1