@@ -293,6 +293,88 @@ where
293293 }
294294}
295295
296+ #[ cfg( feature = "pem" ) ]
297+ #[ derive( Debug , Copy , Clone , PartialEq , Eq ) ]
298+ pub enum PemParseError {
299+ ///Indicates invalid PEM string
300+ Pem ( pem_rfc7468:: Error ) ,
301+ ///Indicates invalid pkcs8 EC key
302+ Pkcs8 ( :: pkcs8:: Error ) ,
303+ ///Indicates invalid Sec1 EC key
304+ Sec1 ( :: sec1:: Error ) ,
305+ ///Unable to recognize document label
306+ UnknownLabel ,
307+ }
308+
309+ #[ cfg( feature = "pem" ) ]
310+ impl From < pem_rfc7468:: Error > for PemParseError {
311+ #[ inline( always) ]
312+ fn from ( error : pem_rfc7468:: Error ) -> Self {
313+ Self :: Pem ( error)
314+ }
315+ }
316+
317+ #[ cfg( feature = "pem" ) ]
318+ impl From < :: pkcs8:: Error > for PemParseError {
319+ #[ inline( always) ]
320+ fn from ( error : :: pkcs8:: Error ) -> Self {
321+ Self :: Pkcs8 ( error)
322+ }
323+ }
324+
325+ #[ cfg( feature = "pem" ) ]
326+ impl From < :: sec1:: Error > for PemParseError {
327+ #[ inline( always) ]
328+ fn from ( error : :: sec1:: Error ) -> Self {
329+ Self :: Sec1 ( error)
330+ }
331+ }
332+
333+ #[ cfg( feature = "pem" ) ]
334+ impl fmt:: Display for PemParseError {
335+ fn fmt ( & self , fmt : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
336+ match self {
337+ Self :: Pem ( error) => fmt. write_fmt ( format_args ! ( "Failed to parse PEM: {error}" ) ) ,
338+ Self :: UnknownLabel => fmt. write_str ( "Unrecognized key label" ) ,
339+ Self :: Pkcs8 ( error) => fmt. write_fmt ( format_args ! ( "Faoled to parse Pkcs8 key: {error}" ) ) ,
340+ Self :: Sec1 ( error) => fmt. write_fmt ( format_args ! ( "Faoled to parse SEC1 key: {error}" ) ) ,
341+ }
342+ }
343+ }
344+
345+ #[ cfg( feature = "pem" ) ]
346+ impl core:: error:: Error for PemParseError { }
347+
348+ #[ cfg( feature = "pem" ) ]
349+ impl < C > SecretKey < C >
350+ where
351+ C : AssociatedOid + Curve + ValidatePublicKey ,
352+ FieldBytesSize < C > : ModulusSize ,
353+ {
354+ /// Parse [`SecretKey`] from PEM-encoded private key.
355+ ///
356+ /// Supported formats:
357+ /// - `SEC1` - requires feature `sec1`
358+ /// - `PKCS #8` - requires feature `pkcs8`
359+ ///
360+ /// # Errors
361+ /// - If `pem` is not valid PEM encoded private key
362+ /// - If label within `pem` is not known valid label
363+ /// - If label is valid, but unable to decode DER content of the PEM file
364+ #[ cfg( feature = "pem" ) ]
365+ pub fn from_pem ( pem : & str ) -> :: core:: result:: Result < Self , PemParseError > {
366+ let label = pem_rfc7468:: decode_label ( pem. as_bytes ( ) ) . map_err ( PemParseError :: Pem ) ?;
367+
368+ if :: pkcs8:: PrivateKeyInfoRef :: validate_pem_label ( label) . is_ok ( ) {
369+ return :: pkcs8:: DecodePrivateKey :: from_pkcs8_pem ( pem) . map_err ( PemParseError :: Pkcs8 ) ;
370+ } else if :: sec1:: EcPrivateKey :: validate_pem_label ( label) . is_ok ( ) {
371+ return :: sec1:: DecodeEcPrivateKey :: from_sec1_pem ( pem) . map_err ( PemParseError :: Sec1 ) ;
372+ }
373+
374+ Err ( PemParseError :: UnknownLabel )
375+ }
376+ }
377+
296378impl < C > ConstantTimeEq for SecretKey < C >
297379where
298380 C : Curve ,
0 commit comments