Skip to content

Commit

Permalink
Add to_jwk to Ed25519Algorithm. (jpadilla#642)
Browse files Browse the repository at this point in the history
  • Loading branch information
JohannesWill committed Apr 6, 2021
1 parent fc7a708 commit 99df961
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
45 changes: 45 additions & 0 deletions jwt/algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@
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,
Expand Down Expand Up @@ -587,6 +591,47 @@ def verify(self, msg, key, sig):
except cryptography.exceptions.InvalidSignature:
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",
"alg": "EdDSA",
"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",
"alg": "EdDSA",
"crv": "Ed25519",
}
)

raise InvalidKeyError("Not a public or private key")

@staticmethod
def from_jwk(jwk):
try:
Expand Down
19 changes: 19 additions & 0 deletions tests/test_algorithms.py
Original file line number Diff line number Diff line change
Expand Up @@ -800,3 +800,22 @@ def test_ed25519_jwk_fails_on_invalid_json(self):
v["d"] = "123"
with pytest.raises(InvalidKeyError):
algo.from_jwk(v)

def test_ed25519_jwk_public_key_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)

0 comments on commit 99df961

Please sign in to comment.