2121from ..util import base64_to_int , int_to_base64
2222from ..registry import KeyParameter
2323
24+ __all__ = ['ECKey' ]
25+
2426ECDictKey = t .TypedDict ("ECDictKey" , {
2527 "crv" : str ,
2628 "x" : str ,
2729 "y" : str ,
2830 "d" : str , # optional
2931}, total = False )
3032
31- DSS_CURVES : t .Dict [str , t .Type [EllipticCurve ]] = {
32- "P-256" : SECP256R1 ,
33- "P-384" : SECP384R1 ,
34- "P-521" : SECP521R1 ,
35- }
36- CURVES_DSS : t .Dict [str , str ] = {
37- SECP256R1 .name : "P-256" ,
38- SECP384R1 .name : "P-384" ,
39- SECP521R1 .name : "P-521" ,
40- }
41-
4233
4334class ECBinding (CryptographyBinding ):
4435 ssh_type = b"ecdsa-sha2-"
4536
46- @staticmethod
47- def import_private_key (obj : ECDictKey ) -> EllipticCurvePrivateKey :
48- curve = DSS_CURVES [obj ["crv" ]]()
37+ _dss_curves : t .Dict [str , t .Type [EllipticCurve ]] = {}
38+ _curves_dss : t .Dict [str , str ] = {}
39+
40+ @classmethod
41+ def register_curve (cls , name : str , curve : t .Type [EllipticCurve ]) -> None :
42+ cls ._dss_curves [name ] = curve
43+ cls ._curves_dss [str (curve .name )] = name
44+
45+ @classmethod
46+ def generate_private_key (cls , name : str ) -> EllipticCurvePrivateKey :
47+ if name not in cls ._dss_curves :
48+ raise ValueError ('Invalid crv value: "{}"' .format (name ))
49+
50+ curve = cls ._dss_curves [name ]()
51+ raw_key = generate_private_key (
52+ curve = curve ,
53+ backend = default_backend (),
54+ )
55+ return raw_key
56+
57+ @classmethod
58+ def import_private_key (cls , obj : ECDictKey ) -> EllipticCurvePrivateKey :
59+ curve = cls ._dss_curves [obj ["crv" ]]()
4960 public_numbers = EllipticCurvePublicNumbers (
5061 base64_to_int (obj ["x" ]),
5162 base64_to_int (obj ["y" ]),
@@ -55,31 +66,31 @@ def import_private_key(obj: ECDictKey) -> EllipticCurvePrivateKey:
5566 private_numbers = EllipticCurvePrivateNumbers (d , public_numbers )
5667 return private_numbers .private_key (default_backend ())
5768
58- @staticmethod
59- def export_private_key (key : EllipticCurvePrivateKey ) -> ECDictKey :
69+ @classmethod
70+ def export_private_key (cls , key : EllipticCurvePrivateKey ) -> ECDictKey :
6071 numbers = key .private_numbers ()
6172 return {
62- "crv" : CURVES_DSS [key .curve .name ],
73+ "crv" : cls . _curves_dss [key .curve .name ],
6374 "x" : int_to_base64 (numbers .public_numbers .x ),
6475 "y" : int_to_base64 (numbers .public_numbers .y ),
6576 "d" : int_to_base64 (numbers .private_value ),
6677 }
6778
68- @staticmethod
69- def import_public_key (obj : ECDictKey ) -> EllipticCurvePublicKey :
70- curve = DSS_CURVES [obj ["crv" ]]()
79+ @classmethod
80+ def import_public_key (cls , obj : ECDictKey ) -> EllipticCurvePublicKey :
81+ curve = cls . _dss_curves [obj ["crv" ]]()
7182 public_numbers = EllipticCurvePublicNumbers (
7283 base64_to_int (obj ["x" ]),
7384 base64_to_int (obj ["y" ]),
7485 curve ,
7586 )
7687 return public_numbers .public_key (default_backend ())
7788
78- @staticmethod
79- def export_public_key (key : EllipticCurvePublicKey ) -> ECDictKey :
89+ @classmethod
90+ def export_public_key (cls , key : EllipticCurvePublicKey ) -> ECDictKey :
8091 numbers = key .public_numbers ()
8192 return {
82- "crv" : CURVES_DSS [numbers .curve .name ],
93+ "crv" : cls . _curves_dss [numbers .curve .name ],
8394 "x" : int_to_base64 (numbers .x ),
8495 "y" : int_to_base64 (numbers .y ),
8596 }
@@ -121,7 +132,7 @@ def exchange_derive_key(self, key: "ECKey") -> bytes:
121132
122133 @property
123134 def curve_name (self ) -> str :
124- return CURVES_DSS [self .raw_value .curve .name ]
135+ return self . binding . _curves_dss [self .raw_value .curve .name ]
125136
126137 @property
127138 def curve_key_size (self ) -> int :
@@ -141,12 +152,7 @@ def generate_key(
141152 :param private: generate a private key or public key
142153 :param auto_kid: add ``kid`` automatically
143154 """
144- if crv not in DSS_CURVES :
145- raise ValueError ('Invalid crv value: "{}"' .format (crv ))
146- raw_key = generate_private_key (
147- curve = DSS_CURVES [crv ](),
148- backend = default_backend (),
149- )
155+ raw_key = cls .binding .generate_private_key (crv )
150156 if private :
151157 key = cls (raw_key , raw_key , parameters )
152158 else :
@@ -155,3 +161,10 @@ def generate_key(
155161 if auto_kid :
156162 key .ensure_kid ()
157163 return key
164+
165+
166+ # register default curves with their DSS (Digital Signature Standard) names
167+ # https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.186-4.pdf
168+ ECBinding .register_curve ("P-256" , SECP256R1 )
169+ ECBinding .register_curve ("P-384" , SECP384R1 )
170+ ECBinding .register_curve ("P-521" , SECP521R1 )
0 commit comments