Skip to content

Commit e88715c

Browse files
authored
Merge pull request #153 from jschlyter/fully_specified_algs
Add fully specified algorithms
2 parents 7ec089f + 3253b86 commit e88715c

File tree

8 files changed

+81
-21
lines changed

8 files changed

+81
-21
lines changed

src/cryptojwt/jwk/__init__.py

+6
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,9 @@ def __init__(
7575
"PS256",
7676
"PS384",
7777
"PS512",
78+
"EdDSA",
79+
"Ed25519",
80+
"Ed448",
7881
"none",
7982
]:
8083
raise UnsupportedAlgorithm("Unknown algorithm: {}".format(alg))
@@ -93,6 +96,9 @@ def __init__(
9396
"PS256",
9497
"PS384",
9598
"PS512",
99+
"EdDSA",
100+
"Ed25519",
101+
"Ed448",
96102
"none",
97103
"RSA1_5",
98104
"RSA-OAEP",

src/cryptojwt/jws/eddsa.py

+21
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010

1111

1212
class EDDSASigner(Signer):
13+
def __init__(self, algorithm=None):
14+
self.algorithm = algorithm
15+
1316
def sign(self, msg, key):
1417
"""
1518
Create a signature over a message as defined in RFC7515 using an
@@ -20,6 +23,17 @@ def sign(self, msg, key):
2023
:return:
2124
"""
2225

26+
if self.algorithm:
27+
if self.algorithm == "Ed25519" and not isinstance(key, ed25519.Ed25519PrivateKey):
28+
raise TypeError("The private key must be an instance of Ed25519PrivateKey")
29+
if self.algorithm == "Ed448" and not isinstance(key, ed448.Ed448PrivateKey):
30+
raise TypeError("The private key must be an instance of Ed448PrivateKey")
31+
32+
if not isinstance(key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)):
33+
raise TypeError(
34+
"The private key must be an instance of Ed25519PrivateKey or Ed448PrivateKey"
35+
)
36+
2337
if not isinstance(key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)):
2438
raise TypeError(
2539
"The private key must be an instance of Ed25519PrivateKey or Ed448PrivateKey"
@@ -37,6 +51,13 @@ def verify(self, msg, sig, key):
3751
:raises: BadSignature if the signature can't be verified.
3852
:return: True
3953
"""
54+
55+
if self.algorithm:
56+
if self.algorithm == "Ed25519" and not isinstance(key, ed25519.Ed25519PublicKey):
57+
raise TypeError("The public key must be an instance of Ed25519PublicKey")
58+
if self.algorithm == "Ed448" and not isinstance(key, ed448.Ed448PublicKey):
59+
raise TypeError("The public key must be an instance of Ed448PublicKey")
60+
4061
if not isinstance(key, (ed25519.Ed25519PublicKey, ed448.Ed448PublicKey)):
4162
raise TypeError(
4263
"The public key must be an instance of Ed25519PublicKey or Ed448PublicKey"

src/cryptojwt/jws/jws.py

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@
4848
"PS384": PSSSigner("SHA384"),
4949
"PS512": PSSSigner("SHA512"),
5050
"EdDSA": EDDSASigner(),
51+
"Ed25519": EDDSASigner("Ed25519"),
52+
"Ed448": EDDSASigner("Ed448"),
5153
"none": None,
5254
}
5355

src/cryptojwt/jws/utils.py

+4
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,10 @@ def alg2keytype(alg):
4747
return "RSA"
4848
elif alg.startswith("HS") or alg.startswith("A"):
4949
return "oct"
50+
elif alg == "Ed25519":
51+
return "OKP"
52+
elif alg == "Ed448":
53+
return "OKP"
5054
elif alg.startswith("ES") or alg.startswith("ECDH-ES"):
5155
return "EC"
5256
elif alg == "EdDSA":

tests/test_03_key_bundle.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ def test_ignore_unknown_types():
225225
"-u6VtZ5rAdBo5fCjjy3LnkrsoK_QWrlKB08j_PcvwpAMfTEDHw5spepw",
226226
"use": "sig",
227227
"alg": "EdDSA",
228-
"kty": "OKP",
228+
"kty": "XXX",
229229
"crv": "Ed25519",
230230
"x": "FnbcUAXZ4ySvrmdXK1MrDuiqlqTXvGdAaE4RWZjmFIQ",
231231
}

tests/test_04_key_issuer.py

-18
Original file line numberDiff line numberDiff line change
@@ -446,24 +446,6 @@ def test_load_missing_key_parameter():
446446
"n": "68be-nJp46VLj4Ci1V36IrVGYqkuBfYNyjQTZD_7yRYcERZebowOnwr3w0DoIQpl8iL2X8OXUo7rUW_LMzLxKx2hEmdJfUn4LL2QqA3KPgjYz8hZJQPG92O14w9IZ-8bdDUgXrg9216H09yq6ZvJrn5Nwvap3MXgECEzsZ6zQLRKdb_R96KFFgCiI3bEiZKvZJRA7hM2ePyTm15D9En_Wzzfn_JLMYgE_DlVpoKR1MsTinfACOlwwdO9U5Dm-5elapovILTyVTgjN75i-wsPU2TqzdHFKA-4hJNiWGrYPiihlAFbA2eUSXuEYFkX43ahoQNpeaf0mc17Jt5kp7pM2w",
447447
"e": "AQAB",
448448
},
449-
{
450-
"kid": "q-H9y8iuh3BIKZBbK6S0mH_isBlJsk"
451-
"-u6VtZ5rAdBo5fCjjy3LnkrsoK_QWrlKB08j_PcvwpAMfTEDHw5spepw",
452-
"use": "sig",
453-
"alg": "EdDSA",
454-
"kty": "OKP",
455-
"crv": "Ed25519",
456-
"x": "FnbcUAXZ4ySvrmdXK1MrDuiqlqTXvGdAaE4RWZjmFIQ",
457-
},
458-
{
459-
"kid": "bL33HthM3fWaYkY2_pDzUd7a65FV2R2LHAKCOsye8eNmAPDgRgpHWPYpWFVmeaujUUEXRyDLHN"
460-
"-Up4QH_sFcmw",
461-
"use": "sig",
462-
"alg": "EdDSA",
463-
"kty": "OKP",
464-
"crv": "Ed25519",
465-
"x": "CS01DGXDBPV9cFmd8tgFu3E7eHn1UcP7N1UCgd_JgZo",
466-
},
467449
]
468450
}
469451

tests/test_04_key_jar.py

+31
Original file line numberDiff line numberDiff line change
@@ -538,6 +538,11 @@ def test_load_missing_key_parameter():
538538
"n": "68be-nJp46VLj4Ci1V36IrVGYqkuBfYNyjQTZD_7yRYcERZebowOnwr3w0DoIQpl8iL2X8OXUo7rUW_LMzLxKx2hEmdJfUn4LL2QqA3KPgjYz8hZJQPG92O14w9IZ-8bdDUgXrg9216H09yq6ZvJrn5Nwvap3MXgECEzsZ6zQLRKdb_R96KFFgCiI3bEiZKvZJRA7hM2ePyTm15D9En_Wzzfn_JLMYgE_DlVpoKR1MsTinfACOlwwdO9U5Dm-5elapovILTyVTgjN75i-wsPU2TqzdHFKA-4hJNiWGrYPiihlAFbA2eUSXuEYFkX43ahoQNpeaf0mc17Jt5kp7pM2w",
539539
"e": "AQAB",
540540
},
541+
]
542+
}
543+
544+
JWKS_EDDSA = {
545+
"keys": [
541546
{
542547
"kid": "q-H9y8iuh3BIKZBbK6S0mH_isBlJsk"
543548
"-u6VtZ5rAdBo5fCjjy3LnkrsoK_QWrlKB08j_PcvwpAMfTEDHw5spepw",
@@ -556,6 +561,22 @@ def test_load_missing_key_parameter():
556561
"crv": "Ed25519",
557562
"x": "CS01DGXDBPV9cFmd8tgFu3E7eHn1UcP7N1UCgd_JgZo",
558563
},
564+
{
565+
"kid": "OF9xVk9NWE5iQ2N6OGhILTVGcXg4RE1FRk5NWVVsaXZLcFNRNUxCYk9vQQ",
566+
"use": "sig",
567+
"alg": "Ed25519",
568+
"kty": "OKP",
569+
"crv": "Ed25519",
570+
"x": "M_D8nslNSecjPwiP6DwuNhWRdrgqp02U7f5xo4GhdlY",
571+
},
572+
{
573+
"kid": "RUpoaXktM1JwT0hON3lzNWNfN0RUbVpiWExwbnJnNDRfYWhZY3htaTZ1Zw",
574+
"use": "sig",
575+
"alg": "Ed448",
576+
"kty": "OKP",
577+
"crv": "Ed448",
578+
"x": "C3y5YN00IxyadHXm4NApPGAzv5w8s9e-fbGu2svYrrCuJDYDDZe-uEOPSobII6psCZCEvo2howmA",
579+
},
559580
]
560581
}
561582

@@ -580,6 +601,16 @@ def test_get_ec_wrong_alg():
580601
assert k == []
581602

582603

604+
def test_get_eddsa():
605+
kj = KeyJar()
606+
kj.import_jwks(JWKS_EDDSA, "")
607+
assert len(kj.get_issuer_keys("")) == 4
608+
k = kj.get("sig", "OKP", alg="Ed25519")
609+
assert k
610+
k = kj.get("sig", "OKP", alg="Ed448")
611+
assert k
612+
613+
583614
def test_keyjar_eq():
584615
kj1 = KeyJar()
585616
kj1.import_jwks(JWKS_SPO, "")

tests/test_06_jws.py

+16-2
Original file line numberDiff line numberDiff line change
@@ -609,6 +609,20 @@ def test_signer_ps512():
609609

610610

611611
def test_signer_eddsa():
612+
payload = "Please take a moment to register today"
613+
okp = ed25519.Ed25519PrivateKey.generate()
614+
_key = OKPKey().load_key(okp)
615+
keys = [_key]
616+
_jws = JWS(payload, alg="Ed25519")
617+
_jwt = _jws.sign_compact(keys)
618+
619+
_pubkey = OKPKey().load_key(okp.public_key())
620+
_rj = JWS(alg="Ed25519")
621+
info = _rj.verify_compact(_jwt, [_pubkey])
622+
assert info == payload
623+
624+
625+
def test_signer_eddsa_polymorphic():
612626
payload = "Please take a moment to register today"
613627
okp = ed25519.Ed25519PrivateKey.generate()
614628
_key = OKPKey().load_key(okp)
@@ -627,12 +641,12 @@ def test_signer_eddsa_fail():
627641
okp = ed25519.Ed25519PrivateKey.generate()
628642
_key = OKPKey().load_key(okp)
629643
keys = [_key]
630-
_jws = JWS(payload, alg="EdDSA")
644+
_jws = JWS(payload, alg="Ed25519")
631645
_jwt = _jws.sign_compact(keys)
632646

633647
okp2 = ed25519.Ed25519PrivateKey.generate()
634648
_pubkey = OKPKey().load_key(okp2.public_key())
635-
_rj = JWS(alg="EdDSA")
649+
_rj = JWS(alg="Ed25519")
636650
try:
637651
info = _rj.verify_compact(_jwt, [_pubkey])
638652
except BadSignature:

0 commit comments

Comments
 (0)