7878from . import der
7979from . import rfc6979
8080from . import ellipticcurve
81- from .curves import NIST192p , Curve
81+ from .curves import NIST192p , Curve , Ed25519 , Ed448
8282from .ecdsa import RSZeroError
8383from .util import string_to_number , number_to_string , randrange
8484from .util import sigencode_string , sigdecode_string , bit_length
@@ -437,6 +437,16 @@ def from_der(
437437 s2 , point_str_bitstring = der .remove_sequence (s1 )
438438 # s2 = oid_ecPublicKey,oid_curve
439439 oid_pk , rest = der .remove_object (s2 )
440+ if oid_pk in (Ed25519 .oid , Ed448 .oid ):
441+ if oid_pk == Ed25519 .oid :
442+ curve = Ed25519
443+ else :
444+ assert oid_pk == Ed448 .oid
445+ curve = Ed448
446+ point_str , empty = der .remove_bitstring (point_str_bitstring , 0 )
447+ if empty :
448+ raise der .UnexpectedDER ("trailing junk afer public key" )
449+ return cls .from_string (point_str , curve , None )
440450 if not oid_pk == oid_ecPublicKey :
441451 raise der .UnexpectedDER (
442452 "Unexpected object identifier in DER "
@@ -647,6 +657,11 @@ def to_der(
647657 if point_encoding == "raw" :
648658 raise ValueError ("raw point_encoding not allowed in DER" )
649659 point_str = self .to_string (point_encoding )
660+ if isinstance (self .curve .curve , CurveEdTw ):
661+ return der .encode_sequence (
662+ der .encode_sequence (der .encode_oid (* self .curve .oid )),
663+ der .encode_bitstring (bytes (point_str ), 0 ),
664+ )
650665 return der .encode_sequence (
651666 der .encode_sequence (
652667 encoded_oid_ecPublicKey ,
@@ -1057,6 +1072,7 @@ def from_der(cls, string, hashfunc=sha1, valid_curve_encodings=None):
10571072 :param valid_curve_encodings: list of allowed encoding formats
10581073 for curve parameters. By default (``None``) all are supported:
10591074 ``named_curve`` and ``explicit``.
1075+ Ignored for EdDSA.
10601076 :type valid_curve_encodings: :term:`set-like object`
10611077
10621078 :raises MalformedPointError: if the length of encoding doesn't match
@@ -1092,12 +1108,38 @@ def from_der(cls, string, hashfunc=sha1, valid_curve_encodings=None):
10921108
10931109 sequence , s = der .remove_sequence (s )
10941110 algorithm_oid , algorithm_identifier = der .remove_object (sequence )
1095- curve = Curve .from_der (algorithm_identifier , valid_curve_encodings )
1111+
1112+ if algorithm_oid in (Ed25519 .oid , Ed448 .oid ):
1113+ if algorithm_identifier :
1114+ raise der .UnexpectedDER (
1115+ "Non NULL parameters for a EdDSA key"
1116+ )
1117+ key_str_der , s = der .remove_octet_string (s )
1118+ if s :
1119+ raise der .UnexpectedDER (
1120+ "trailing junk inside the privateKey"
1121+ )
1122+ key_str , s = der .remove_octet_string (key_str_der )
1123+ if s :
1124+ raise der .UnexpectedDER (
1125+ "trailing junk after the encoded private key"
1126+ )
1127+
1128+ if algorithm_oid == Ed25519 .oid :
1129+ curve = Ed25519
1130+ else :
1131+ assert algorithm_oid == Ed448 .oid
1132+ curve = Ed448
1133+
1134+ return cls .from_string (key_str , curve , None )
10961135
10971136 if algorithm_oid not in (oid_ecPublicKey , oid_ecDH , oid_ecMQV ):
10981137 raise der .UnexpectedDER (
10991138 "unexpected algorithm identifier '%s'" % (algorithm_oid ,)
11001139 )
1140+
1141+ curve = Curve .from_der (algorithm_identifier , valid_curve_encodings )
1142+
11011143 if empty != b"" :
11021144 raise der .UnexpectedDER (
11031145 "unexpected data after algorithm identifier: %s"
@@ -1166,6 +1208,8 @@ def to_string(self):
11661208 :return: raw encoding of private key
11671209 :rtype: bytes
11681210 """
1211+ if isinstance (self .curve .curve , CurveEdTw ):
1212+ return bytes (self .privkey .private_key )
11691213 secexp = self .privkey .secret_multiplier
11701214 s = number_to_string (secexp , self .privkey .order )
11711215 return s
@@ -1209,6 +1253,15 @@ def to_pem(
12091253 header ,
12101254 )
12111255
1256+ def _encode_eddsa (self ):
1257+ """Create a PKCS#8 encoding of EdDSA keys."""
1258+ ec_private_key = der .encode_octet_string (self .to_string ())
1259+ return der .encode_sequence (
1260+ der .encode_integer (0 ),
1261+ der .encode_sequence (der .encode_oid (* self .curve .oid )),
1262+ der .encode_octet_string (ec_private_key ),
1263+ )
1264+
12121265 def to_der (
12131266 self ,
12141267 point_encoding = "uncompressed" ,
@@ -1224,12 +1277,15 @@ def to_der(
12241277 The public key will be included in the generated string.
12251278
12261279 :param str point_encoding: format to use for encoding public point
1227- :param str format: either ``ssleay`` (default) or ``pkcs8``
1280+ Ignored for EdDSA
1281+ :param str format: either ``ssleay`` (default) or ``pkcs8``.
1282+ EdDSA keys require ``pkcs8``.
12281283 :param str curve_parameters_encoding: format of encoded curve
12291284 parameters, default depends on the curve, if the curve has
12301285 an associated OID, ``named_curve`` format will be used,
12311286 if no OID is associated with the curve, the fallback of
12321287 ``explicit`` parameters will be used.
1288+ Ignored for EdDSA.
12331289
12341290 :return: DER encoded private key
12351291 :rtype: bytes
@@ -1239,6 +1295,10 @@ def to_der(
12391295 if point_encoding == "raw" :
12401296 raise ValueError ("raw encoding not allowed in DER" )
12411297 assert format in ("ssleay" , "pkcs8" )
1298+ if isinstance (self .curve .curve , CurveEdTw ):
1299+ if format != "pkcs8" :
1300+ raise ValueError ("Only PKCS#8 format supported for EdDSA keys" )
1301+ return self ._encode_eddsa ()
12421302 encoded_vk = self .get_verifying_key ().to_string (point_encoding )
12431303 priv_key_elems = [
12441304 der .encode_integer (1 ),
0 commit comments