2222 EllipticCurvePrivateKey ,
2323 EllipticCurvePublicKey ,
2424 )
25+ from cryptography .hazmat .primitives .asymmetric .ed448 import (
26+ Ed448PrivateKey ,
27+ Ed448PublicKey ,
28+ )
2529 from cryptography .hazmat .primitives .asymmetric .ed25519 import (
2630 Ed25519PrivateKey ,
2731 Ed25519PublicKey ,
@@ -93,7 +97,7 @@ def get_default_algorithms():
9397 "PS256" : RSAPSSAlgorithm (RSAPSSAlgorithm .SHA256 ),
9498 "PS384" : RSAPSSAlgorithm (RSAPSSAlgorithm .SHA384 ),
9599 "PS512" : RSAPSSAlgorithm (RSAPSSAlgorithm .SHA512 ),
96- "EdDSA" : Ed25519Algorithm (),
100+ "EdDSA" : OKPAlgorithm (),
97101 }
98102 )
99103
@@ -534,9 +538,9 @@ def verify(self, msg, key, sig):
534538 except InvalidSignature :
535539 return False
536540
537- class Ed25519Algorithm (Algorithm ):
541+ class OKPAlgorithm (Algorithm ):
538542 """
539- Performs signing and verification operations using Ed25519
543+ Performs signing and verification operations using EdDSA
540544
541545 This class requires ``cryptography>=2.6`` to be installed.
542546 """
@@ -546,7 +550,10 @@ def __init__(self, **kwargs):
546550
547551 def prepare_key (self , key ):
548552
549- if isinstance (key , (Ed25519PrivateKey , Ed25519PublicKey )):
553+ if isinstance (
554+ key ,
555+ (Ed25519PrivateKey , Ed25519PublicKey , Ed448PrivateKey , Ed448PublicKey ),
556+ ):
550557 return key
551558
552559 if isinstance (key , (bytes , str )):
@@ -565,28 +572,30 @@ def prepare_key(self, key):
565572
566573 def sign (self , msg , key ):
567574 """
568- Sign a message ``msg`` using the Ed25519 private key ``key``
575+ Sign a message ``msg`` using the EdDSA private key ``key``
569576 :param str|bytes msg: Message to sign
570- :param Ed25519PrivateKey key: A :class:`.Ed25519PrivateKey` instance
577+ :param Ed25519PrivateKey}Ed448PrivateKey key: A :class:`.Ed25519PrivateKey`
578+ or :class:`.Ed448PrivateKey` iinstance
571579 :return bytes signature: The signature, as bytes
572580 """
573581 msg = bytes (msg , "utf-8" ) if type (msg ) is not bytes else msg
574582 return key .sign (msg )
575583
576584 def verify (self , msg , key , sig ):
577585 """
578- Verify a given ``msg`` against a signature ``sig`` using the Ed25519 key ``key``
586+ Verify a given ``msg`` against a signature ``sig`` using the EdDSA key ``key``
579587
580- :param str|bytes sig: Ed25519 signature to check ``msg`` against
588+ :param str|bytes sig: EdDSA signature to check ``msg`` against
581589 :param str|bytes msg: Message to sign
582- :param Ed25519PrivateKey|Ed25519PublicKey key: A private or public Ed25519 key instance
590+ :param Ed25519PrivateKey|Ed25519PublicKey|Ed448PrivateKey|Ed448PublicKey key:
591+ A private or public EdDSA key instance
583592 :return bool verified: True if signature is valid, False if not.
584593 """
585594 try :
586595 msg = bytes (msg , "utf-8" ) if type (msg ) is not bytes else msg
587596 sig = bytes (sig , "utf-8" ) if type (sig ) is not bytes else sig
588597
589- if isinstance (key , Ed25519PrivateKey ):
598+ if isinstance (key , ( Ed25519PrivateKey , Ed448PrivateKey ) ):
590599 key = key .public_key ()
591600 key .verify (sig , msg )
592601 return True # If no exception was raised, the signature is valid.
@@ -595,21 +604,21 @@ def verify(self, msg, key, sig):
595604
596605 @staticmethod
597606 def to_jwk (key ):
598- if isinstance (key , Ed25519PublicKey ):
607+ if isinstance (key , ( Ed25519PublicKey , Ed448PublicKey ) ):
599608 x = key .public_bytes (
600609 encoding = Encoding .Raw ,
601610 format = PublicFormat .Raw ,
602611 )
603-
612+ crv = "Ed25519" if isinstance ( key , Ed25519PublicKey ) else "Ed448"
604613 return json .dumps (
605614 {
606615 "x" : base64url_encode (force_bytes (x )).decode (),
607616 "kty" : "OKP" ,
608- "crv" : "Ed25519" ,
617+ "crv" : crv ,
609618 }
610619 )
611620
612- if isinstance (key , Ed25519PrivateKey ):
621+ if isinstance (key , ( Ed25519PrivateKey , Ed448PrivateKey ) ):
613622 d = key .private_bytes (
614623 encoding = Encoding .Raw ,
615624 format = PrivateFormat .Raw ,
@@ -621,12 +630,13 @@ def to_jwk(key):
621630 format = PublicFormat .Raw ,
622631 )
623632
633+ crv = "Ed25519" if isinstance (key , Ed25519PrivateKey ) else "Ed448"
624634 return json .dumps (
625635 {
626636 "x" : base64url_encode (force_bytes (x )).decode (),
627637 "d" : base64url_encode (force_bytes (d )).decode (),
628638 "kty" : "OKP" ,
629- "crv" : "Ed25519" ,
639+ "crv" : crv ,
630640 }
631641 )
632642
@@ -648,7 +658,7 @@ def from_jwk(jwk):
648658 raise InvalidKeyError ("Not an Octet Key Pair" )
649659
650660 curve = obj .get ("crv" )
651- if curve != "Ed25519" :
661+ if curve != "Ed25519" and curve != "Ed448" :
652662 raise InvalidKeyError (f"Invalid curve: { curve } " )
653663
654664 if "x" not in obj :
@@ -657,8 +667,12 @@ def from_jwk(jwk):
657667
658668 try :
659669 if "d" not in obj :
660- return Ed25519PublicKey .from_public_bytes (x )
670+ if curve == "Ed25519" :
671+ return Ed25519PublicKey .from_public_bytes (x )
672+ return Ed448PublicKey .from_public_bytes (x )
661673 d = base64url_decode (obj .get ("d" ))
662- return Ed25519PrivateKey .from_private_bytes (d )
674+ if curve == "Ed25519" :
675+ return Ed25519PrivateKey .from_private_bytes (d )
676+ return Ed448PrivateKey .from_private_bytes (d )
663677 except ValueError as err :
664678 raise InvalidKeyError ("Invalid key parameter" ) from err
0 commit comments