Skip to content

Commit 330d273

Browse files
authored
Merge pull request #142 from jschlyter/eddsa
EdDSA (Ed25519/Ed448)
2 parents 0a5a521 + cb12605 commit 330d273

File tree

15 files changed

+724
-10
lines changed

15 files changed

+724
-10
lines changed

src/cryptojwt/exception.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,3 +117,7 @@ class HTTPException(JWKESTException):
117117

118118
class UnsupportedECurve(Unsupported):
119119
pass
120+
121+
122+
class UnsupportedOKPCurve(Unsupported):
123+
pass

src/cryptojwt/jwk/jwk.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
from cryptography.hazmat import backends
66
from cryptography.hazmat.primitives.asymmetric import ec
7+
from cryptography.hazmat.primitives.asymmetric import ed448
8+
from cryptography.hazmat.primitives.asymmetric import ed25519
79
from cryptography.hazmat.primitives.asymmetric import rsa
810
from cryptography.hazmat.primitives.asymmetric.rsa import rsa_crt_dmp1
911
from cryptography.hazmat.primitives.asymmetric.rsa import rsa_crt_dmq1
@@ -17,6 +19,7 @@
1719
from .ec import NIST2SEC
1820
from .ec import ECKey
1921
from .hmac import SYMKey
22+
from .okp import OKPKey
2023
from .rsa import RSAKey
2124

2225
EC_PUBLIC_REQUIRED = frozenset(["crv", "x", "y"])
@@ -25,6 +28,12 @@
2528
EC_PRIVATE_OPTIONAL = frozenset()
2629
EC_PRIVATE = EC_PRIVATE_REQUIRED | EC_PRIVATE_OPTIONAL
2730

31+
OKP_PUBLIC_REQUIRED = frozenset(["crv", "x"])
32+
OKP_PUBLIC = OKP_PUBLIC_REQUIRED
33+
OKP_PRIVATE_REQUIRED = frozenset(["d"])
34+
OKP_PRIVATE_OPTIONAL = frozenset()
35+
OKP_PRIVATE = OKP_PRIVATE_REQUIRED | OKP_PRIVATE_OPTIONAL
36+
2837
RSA_PUBLIC_REQUIRED = frozenset(["e", "n"])
2938
RSA_PUBLIC = RSA_PUBLIC_REQUIRED
3039
RSA_PRIVATE_REQUIRED = frozenset(["p", "q", "d"])
@@ -42,6 +51,16 @@ def ensure_ec_params(jwk_dict, private):
4251
return ensure_params("EC", provided, required)
4352

4453

54+
def ensure_okp_params(jwk_dict, private):
55+
"""Ensure all required OKP parameters are present in dictionary"""
56+
provided = frozenset(jwk_dict.keys())
57+
if private is not None and private:
58+
required = OKP_PUBLIC_REQUIRED | OKP_PRIVATE_REQUIRED
59+
else:
60+
required = OKP_PUBLIC_REQUIRED
61+
return ensure_params("OKP", provided, required)
62+
63+
4564
def ensure_rsa_params(jwk_dict, private):
4665
"""Ensure all required RSA parameters are present in dictionary"""
4766
provided = frozenset(jwk_dict.keys())
@@ -140,6 +159,15 @@ def key_from_jwk_dict(jwk_dict, private=None):
140159
if _jwk_dict["kty"] != "RSA":
141160
raise WrongKeyType('"{}" should have been "RSA"'.format(_jwk_dict["kty"]))
142161
return RSAKey(**_jwk_dict)
162+
elif _jwk_dict["kty"] == "OKP":
163+
ensure_okp_params(_jwk_dict, private)
164+
165+
if private is not None and not private:
166+
# remove private components
167+
for v in OKP_PRIVATE:
168+
_jwk_dict.pop(v, None)
169+
170+
return OKPKey(**_jwk_dict)
143171
elif _jwk_dict["kty"] == "oct":
144172
if "key" not in _jwk_dict and "k" not in _jwk_dict:
145173
raise MissingValue('There has to be one of "k" or "key" in a symmetric key')
@@ -164,6 +192,8 @@ def jwk_wrap(key, use="", kid=""):
164192
kspec = SYMKey(key=key, use=use, kid=kid)
165193
elif isinstance(key, ec.EllipticCurvePublicKey):
166194
kspec = ECKey(use=use, kid=kid).load_key(key)
195+
elif isinstance(key, (ed25519.Ed25519PublicKey, ed448.Ed448PublicKey)):
196+
kspec = OKPKey(use=use, kid=kid).load_key(key)
167197
else:
168198
raise Exception("Unknown key type:key=" + str(type(key)))
169199

0 commit comments

Comments
 (0)