summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohannesWill <johannes.will@siemens.com>2021-04-28 13:42:22 +0200
committerGitHub <noreply@github.com>2021-04-28 07:42:22 -0400
commit545931dafd9ec318e8d8acff6d5a4daeedf50863 (patch)
tree75e4217b59ba46ecf8e6a18ffde584ecb1731d91
parent7f6a2361943ffae20007eb014900060c6b21d9cc (diff)
downloadpyjwt-545931dafd9ec318e8d8acff6d5a4daeedf50863.tar.gz
Add to_jwk to Ed25519Algorithm. (#642) (#643)
* Add to_jwk to Ed25519Algorithm. (#642) * add test for invalid key * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * update CHANGELOG for #643 * remove alg from jwk Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
-rw-r--r--CHANGELOG.rst1
-rw-r--r--jwt/algorithms.py43
-rw-r--r--tests/test_algorithms.py25
3 files changed, 69 insertions, 0 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 9fb832f..624b676 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -27,6 +27,7 @@ Added
- Add missing exceptions.InvalidKeyError to jwt module __init__ imports `#620 <https://github.com/jpadilla/pyjwt/pull/620>`__
- Add support for ES256K algorithm `#629 <https://github.com/jpadilla/pyjwt/pull/629>`__
- Add `from_jwk()` to Ed25519Algorithm `#621 <https://github.com/jpadilla/pyjwt/pull/621>`__
+- Add `to_jwk()` to Ed25519Algorithm `#643 <https://github.com/jpadilla/pyjwt/pull/643>`__
`v2.0.1 <https://github.com/jpadilla/pyjwt/compare/2.0.0...2.0.1>`__
--------------------------------------------------------------------
diff --git a/jwt/algorithms.py b/jwt/algorithms.py
index bed4033..cee66a4 100644
--- a/jwt/algorithms.py
+++ b/jwt/algorithms.py
@@ -37,6 +37,10 @@ try:
rsa_recover_prime_factors,
)
from cryptography.hazmat.primitives.serialization import (
+ Encoding,
+ NoEncryption,
+ PrivateFormat,
+ PublicFormat,
load_pem_private_key,
load_pem_public_key,
load_ssh_public_key,
@@ -590,6 +594,45 @@ if has_crypto:
return False
@staticmethod
+ def to_jwk(key):
+ if isinstance(key, Ed25519PublicKey):
+ x = key.public_bytes(
+ encoding=Encoding.Raw,
+ format=PublicFormat.Raw,
+ )
+
+ return json.dumps(
+ {
+ "x": base64url_encode(force_bytes(x)).decode(),
+ "kty": "OKP",
+ "crv": "Ed25519",
+ }
+ )
+
+ if isinstance(key, Ed25519PrivateKey):
+ d = key.private_bytes(
+ encoding=Encoding.Raw,
+ format=PrivateFormat.Raw,
+ encryption_algorithm=NoEncryption(),
+ )
+
+ x = key.public_key().public_bytes(
+ encoding=Encoding.Raw,
+ format=PublicFormat.Raw,
+ )
+
+ return json.dumps(
+ {
+ "x": base64url_encode(force_bytes(x)).decode(),
+ "d": base64url_encode(force_bytes(d)).decode(),
+ "kty": "OKP",
+ "crv": "Ed25519",
+ }
+ )
+
+ raise InvalidKeyError("Not a public or private key")
+
+ @staticmethod
def from_jwk(jwk):
try:
if isinstance(jwk, str):
diff --git a/tests/test_algorithms.py b/tests/test_algorithms.py
index 982a145..417f91d 100644
--- a/tests/test_algorithms.py
+++ b/tests/test_algorithms.py
@@ -807,3 +807,28 @@ class TestEd25519Algorithms:
v["d"] = "123"
with pytest.raises(InvalidKeyError):
algo.from_jwk(v)
+
+ def test_ed25519_to_jwk_works_with_from_jwk(self):
+ algo = Ed25519Algorithm()
+
+ with open(key_path("jwk_okp_key_Ed25519.json")) as keyfile:
+ priv_key_1 = algo.from_jwk(keyfile.read())
+
+ with open(key_path("jwk_okp_pub_Ed25519.json")) as keyfile:
+ pub_key_1 = algo.from_jwk(keyfile.read())
+
+ pub = algo.to_jwk(pub_key_1)
+ pub_key_2 = algo.from_jwk(pub)
+ pri = algo.to_jwk(priv_key_1)
+ priv_key_2 = algo.from_jwk(pri)
+
+ signature_1 = algo.sign(b"Hello World!", priv_key_1)
+ signature_2 = algo.sign(b"Hello World!", priv_key_2)
+ assert algo.verify(b"Hello World!", pub_key_2, signature_1)
+ assert algo.verify(b"Hello World!", pub_key_2, signature_2)
+
+ def test_ed25519_to_jwk_raises_exception_on_invalid_key(self):
+ algo = Ed25519Algorithm()
+
+ with pytest.raises(InvalidKeyError):
+ algo.to_jwk({"not": "a valid key"})