@@ -564,7 +564,9 @@ def to_string(self, encoding="raw"):
564564 assert encoding in ("raw" , "uncompressed" , "compressed" , "hybrid" )
565565 return self .pubkey .point .to_bytes (encoding )
566566
567- def to_pem (self , point_encoding = "uncompressed" ):
567+ def to_pem (
568+ self , point_encoding = "uncompressed" , curve_parameters_encoding = None
569+ ):
568570 """
569571 Convert the public key to the :term:`PEM` format.
570572
@@ -578,16 +580,24 @@ def to_pem(self, point_encoding="uncompressed"):
578580 of public keys. "uncompressed" is most portable, "compressed" is
579581 smallest. "hybrid" is uncommon and unsupported by most
580582 implementations, it is as big as "uncompressed".
583+ :param str curve_parameters_encoding: the encoding for curve parameters
584+ to use, by default tries to use ``named_curve`` encoding,
585+ if that is not possible, falls back to ``named_curve`` encoding.
581586
582587 :return: portable encoding of the public key
583588 :rtype: bytes
584589
585590 .. warning:: The PEM is encoded to US-ASCII, it needs to be
586591 re-encoded if the system is incompatible (e.g. uses UTF-16)
587592 """
588- return der .topem (self .to_der (point_encoding ), "PUBLIC KEY" )
593+ return der .topem (
594+ self .to_der (point_encoding , curve_parameters_encoding ),
595+ "PUBLIC KEY" ,
596+ )
589597
590- def to_der (self , point_encoding = "uncompressed" ):
598+ def to_der (
599+ self , point_encoding = "uncompressed" , curve_parameters_encoding = None
600+ ):
591601 """
592602 Convert the public key to the :term:`DER` format.
593603
@@ -599,6 +609,9 @@ def to_der(self, point_encoding="uncompressed"):
599609 of public keys. "uncompressed" is most portable, "compressed" is
600610 smallest. "hybrid" is uncommon and unsupported by most
601611 implementations, it is as big as "uncompressed".
612+ :param str curve_parameters_encoding: the encoding for curve parameters
613+ to use, by default tries to use ``named_curve`` encoding,
614+ if that is not possible, falls back to ``named_curve`` encoding.
602615
603616 :return: DER encoding of the public key
604617 :rtype: bytes
@@ -608,7 +621,8 @@ def to_der(self, point_encoding="uncompressed"):
608621 point_str = self .to_string (point_encoding )
609622 return der .encode_sequence (
610623 der .encode_sequence (
611- encoded_oid_ecPublicKey , self .curve .encoded_oid
624+ encoded_oid_ecPublicKey ,
625+ self .curve .to_der (curve_parameters_encoding ),
612626 ),
613627 # 0 is the number of unused bits in the
614628 # bit string
@@ -1078,7 +1092,12 @@ def to_string(self):
10781092 s = number_to_string (secexp , self .privkey .order )
10791093 return s
10801094
1081- def to_pem (self , point_encoding = "uncompressed" , format = "ssleay" ):
1095+ def to_pem (
1096+ self ,
1097+ point_encoding = "uncompressed" ,
1098+ format = "ssleay" ,
1099+ curve_parameters_encoding = None ,
1100+ ):
10821101 """
10831102 Convert the private key to the :term:`PEM` format.
10841103
@@ -1092,6 +1111,11 @@ def to_pem(self, point_encoding="uncompressed", format="ssleay"):
10921111
10931112 :param str point_encoding: format to use for encoding public point
10941113 :param str format: either ``ssleay`` (default) or ``pkcs8``
1114+ :param str curve_parameters_encoding: format of encoded curve
1115+ parameters, default depends on the curve, if the curve has
1116+ an associated OID, ``named_curve`` format will be used,
1117+ if no OID is associated with the curve, the fallback of
1118+ ``explicit`` parameters will be used.
10951119
10961120 :return: PEM encoded private key
10971121 :rtype: bytes
@@ -1102,9 +1126,17 @@ def to_pem(self, point_encoding="uncompressed", format="ssleay"):
11021126 # TODO: "BEGIN ECPARAMETERS"
11031127 assert format in ("ssleay" , "pkcs8" )
11041128 header = "EC PRIVATE KEY" if format == "ssleay" else "PRIVATE KEY"
1105- return der .topem (self .to_der (point_encoding , format ), header )
1129+ return der .topem (
1130+ self .to_der (point_encoding , format , curve_parameters_encoding ),
1131+ header ,
1132+ )
11061133
1107- def to_der (self , point_encoding = "uncompressed" , format = "ssleay" ):
1134+ def to_der (
1135+ self ,
1136+ point_encoding = "uncompressed" ,
1137+ format = "ssleay" ,
1138+ curve_parameters_encoding = None ,
1139+ ):
11081140 """
11091141 Convert the private key to the :term:`DER` format.
11101142
@@ -1115,6 +1147,11 @@ def to_der(self, point_encoding="uncompressed", format="ssleay"):
11151147
11161148 :param str point_encoding: format to use for encoding public point
11171149 :param str format: either ``ssleay`` (default) or ``pkcs8``
1150+ :param str curve_parameters_encoding: format of encoded curve
1151+ parameters, default depends on the curve, if the curve has
1152+ an associated OID, ``named_curve`` format will be used,
1153+ if no OID is associated with the curve, the fallback of
1154+ ``explicit`` parameters will be used.
11181155
11191156 :return: DER encoded private key
11201157 :rtype: bytes
@@ -1125,14 +1162,22 @@ def to_der(self, point_encoding="uncompressed", format="ssleay"):
11251162 raise ValueError ("raw encoding not allowed in DER" )
11261163 assert format in ("ssleay" , "pkcs8" )
11271164 encoded_vk = self .get_verifying_key ().to_string (point_encoding )
1128- # the 0 in encode_bitstring specifies the number of unused bits
1129- # in the `encoded_vk` string
1130- ec_private_key = der .encode_sequence (
1165+ priv_key_elems = [
11311166 der .encode_integer (1 ),
11321167 der .encode_octet_string (self .to_string ()),
1133- der .encode_constructed (0 , self .curve .encoded_oid ),
1134- der .encode_constructed (1 , der .encode_bitstring (encoded_vk , 0 )),
1168+ ]
1169+ if format == "ssleay" :
1170+ priv_key_elems .append (
1171+ der .encode_constructed (
1172+ 0 , self .curve .to_der (curve_parameters_encoding )
1173+ )
1174+ )
1175+ # the 0 in encode_bitstring specifies the number of unused bits
1176+ # in the `encoded_vk` string
1177+ priv_key_elems .append (
1178+ der .encode_constructed (1 , der .encode_bitstring (encoded_vk , 0 ))
11351179 )
1180+ ec_private_key = der .encode_sequence (* priv_key_elems )
11361181
11371182 if format == "ssleay" :
11381183 return ec_private_key
@@ -1142,7 +1187,8 @@ def to_der(self, point_encoding="uncompressed", format="ssleay"):
11421187 # top-level structure.
11431188 der .encode_integer (1 ),
11441189 der .encode_sequence (
1145- der .encode_oid (* oid_ecPublicKey ), self .curve .encoded_oid
1190+ der .encode_oid (* oid_ecPublicKey ),
1191+ self .curve .to_der (curve_parameters_encoding ),
11461192 ),
11471193 der .encode_octet_string (ec_private_key ),
11481194 )
0 commit comments