78
78
from . import der
79
79
from . import rfc6979
80
80
from . import ellipticcurve
81
- from .curves import NIST192p , Curve
81
+ from .curves import NIST192p , Curve , Ed25519 , Ed448
82
82
from .ecdsa import RSZeroError
83
83
from .util import string_to_number , number_to_string , randrange
84
84
from .util import sigencode_string , sigdecode_string , bit_length
@@ -437,6 +437,16 @@ def from_der(
437
437
s2 , point_str_bitstring = der .remove_sequence (s1 )
438
438
# s2 = oid_ecPublicKey,oid_curve
439
439
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 )
440
450
if not oid_pk == oid_ecPublicKey :
441
451
raise der .UnexpectedDER (
442
452
"Unexpected object identifier in DER "
@@ -647,6 +657,11 @@ def to_der(
647
657
if point_encoding == "raw" :
648
658
raise ValueError ("raw point_encoding not allowed in DER" )
649
659
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
+ )
650
665
return der .encode_sequence (
651
666
der .encode_sequence (
652
667
encoded_oid_ecPublicKey ,
@@ -1057,6 +1072,7 @@ def from_der(cls, string, hashfunc=sha1, valid_curve_encodings=None):
1057
1072
:param valid_curve_encodings: list of allowed encoding formats
1058
1073
for curve parameters. By default (``None``) all are supported:
1059
1074
``named_curve`` and ``explicit``.
1075
+ Ignored for EdDSA.
1060
1076
:type valid_curve_encodings: :term:`set-like object`
1061
1077
1062
1078
: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):
1092
1108
1093
1109
sequence , s = der .remove_sequence (s )
1094
1110
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 )
1096
1135
1097
1136
if algorithm_oid not in (oid_ecPublicKey , oid_ecDH , oid_ecMQV ):
1098
1137
raise der .UnexpectedDER (
1099
1138
"unexpected algorithm identifier '%s'" % (algorithm_oid ,)
1100
1139
)
1140
+
1141
+ curve = Curve .from_der (algorithm_identifier , valid_curve_encodings )
1142
+
1101
1143
if empty != b"" :
1102
1144
raise der .UnexpectedDER (
1103
1145
"unexpected data after algorithm identifier: %s"
@@ -1166,6 +1208,8 @@ def to_string(self):
1166
1208
:return: raw encoding of private key
1167
1209
:rtype: bytes
1168
1210
"""
1211
+ if isinstance (self .curve .curve , CurveEdTw ):
1212
+ return bytes (self .privkey .private_key )
1169
1213
secexp = self .privkey .secret_multiplier
1170
1214
s = number_to_string (secexp , self .privkey .order )
1171
1215
return s
@@ -1209,6 +1253,15 @@ def to_pem(
1209
1253
header ,
1210
1254
)
1211
1255
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
+
1212
1265
def to_der (
1213
1266
self ,
1214
1267
point_encoding = "uncompressed" ,
@@ -1224,12 +1277,15 @@ def to_der(
1224
1277
The public key will be included in the generated string.
1225
1278
1226
1279
: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``.
1228
1283
:param str curve_parameters_encoding: format of encoded curve
1229
1284
parameters, default depends on the curve, if the curve has
1230
1285
an associated OID, ``named_curve`` format will be used,
1231
1286
if no OID is associated with the curve, the fallback of
1232
1287
``explicit`` parameters will be used.
1288
+ Ignored for EdDSA.
1233
1289
1234
1290
:return: DER encoded private key
1235
1291
:rtype: bytes
@@ -1239,6 +1295,10 @@ def to_der(
1239
1295
if point_encoding == "raw" :
1240
1296
raise ValueError ("raw encoding not allowed in DER" )
1241
1297
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 ()
1242
1302
encoded_vk = self .get_verifying_key ().to_string (point_encoding )
1243
1303
priv_key_elems = [
1244
1304
der .encode_integer (1 ),
0 commit comments