Skip to content

EdDSA (Ed25519/Ed448) #142

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 15 commits into from
May 25, 2023
4 changes: 4 additions & 0 deletions src/cryptojwt/exception.py
Original file line number Diff line number Diff line change
Expand Up @@ -117,3 +117,7 @@ class HTTPException(JWKESTException):

class UnsupportedECurve(Unsupported):
pass


class UnsupportedOKPCurve(Unsupported):
pass
30 changes: 30 additions & 0 deletions src/cryptojwt/jwk/jwk.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

from cryptography.hazmat import backends
from cryptography.hazmat.primitives.asymmetric import ec
from cryptography.hazmat.primitives.asymmetric import ed448
from cryptography.hazmat.primitives.asymmetric import ed25519
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives.asymmetric.rsa import rsa_crt_dmp1
from cryptography.hazmat.primitives.asymmetric.rsa import rsa_crt_dmq1
Expand All @@ -17,6 +19,7 @@
from .ec import NIST2SEC
from .ec import ECKey
from .hmac import SYMKey
from .okp import OKPKey
from .rsa import RSAKey

EC_PUBLIC_REQUIRED = frozenset(["crv", "x", "y"])
Expand All @@ -25,6 +28,12 @@
EC_PRIVATE_OPTIONAL = frozenset()
EC_PRIVATE = EC_PRIVATE_REQUIRED | EC_PRIVATE_OPTIONAL

OKP_PUBLIC_REQUIRED = frozenset(["crv", "x"])
OKP_PUBLIC = OKP_PUBLIC_REQUIRED
OKP_PRIVATE_REQUIRED = frozenset(["d"])
OKP_PRIVATE_OPTIONAL = frozenset()
OKP_PRIVATE = OKP_PRIVATE_REQUIRED | OKP_PRIVATE_OPTIONAL

RSA_PUBLIC_REQUIRED = frozenset(["e", "n"])
RSA_PUBLIC = RSA_PUBLIC_REQUIRED
RSA_PRIVATE_REQUIRED = frozenset(["p", "q", "d"])
Expand All @@ -42,6 +51,16 @@ def ensure_ec_params(jwk_dict, private):
return ensure_params("EC", provided, required)


def ensure_okp_params(jwk_dict, private):
"""Ensure all required OKP parameters are present in dictionary"""
provided = frozenset(jwk_dict.keys())
if private is not None and private:
required = OKP_PUBLIC_REQUIRED | OKP_PRIVATE_REQUIRED
else:
required = OKP_PUBLIC_REQUIRED
return ensure_params("OKP", provided, required)


def ensure_rsa_params(jwk_dict, private):
"""Ensure all required RSA parameters are present in dictionary"""
provided = frozenset(jwk_dict.keys())
Expand Down Expand Up @@ -140,6 +159,15 @@ def key_from_jwk_dict(jwk_dict, private=None):
if _jwk_dict["kty"] != "RSA":
raise WrongKeyType('"{}" should have been "RSA"'.format(_jwk_dict["kty"]))
return RSAKey(**_jwk_dict)
elif _jwk_dict["kty"] == "OKP":
ensure_okp_params(_jwk_dict, private)

if private is not None and not private:
# remove private components
for v in OKP_PRIVATE:
_jwk_dict.pop(v, None)

return OKPKey(**_jwk_dict)
elif _jwk_dict["kty"] == "oct":
if "key" not in _jwk_dict and "k" not in _jwk_dict:
raise MissingValue('There has to be one of "k" or "key" in a symmetric key')
Expand All @@ -164,6 +192,8 @@ def jwk_wrap(key, use="", kid=""):
kspec = SYMKey(key=key, use=use, kid=kid)
elif isinstance(key, ec.EllipticCurvePublicKey):
kspec = ECKey(use=use, kid=kid).load_key(key)
elif isinstance(key, (ed25519.Ed25519PublicKey, ed448.Ed448PublicKey)):
kspec = OKPKey(use=use, kid=kid).load_key(key)
else:
raise Exception("Unknown key type:key=" + str(type(key)))

Expand Down
Loading