@@ -690,6 +690,68 @@ impl<T> ExternalError<T> for Result<T, pem::PemError> {
690
690
}
691
691
}
692
692
693
+ /// A public key
694
+ #[ derive( Clone , Debug , Eq , PartialEq ) ]
695
+ pub struct SubjectPublicKeyInfo {
696
+ pub ( crate ) alg : & ' static SignatureAlgorithm ,
697
+ pub ( crate ) subject_public_key : Vec < u8 > ,
698
+ }
699
+
700
+ impl SubjectPublicKeyInfo {
701
+ /// Create a `SubjectPublicKey` value from a PEM-encoded SubjectPublicKeyInfo string
702
+ #[ cfg( all( feature = "x509-parser" , feature = "pem" ) ) ]
703
+ pub fn from_pem ( pem_str : & str ) -> Result < Self , Error > {
704
+ Self :: from_der ( & pem:: parse ( pem_str) . _err ( ) ?. into_contents ( ) )
705
+ }
706
+
707
+ /// Create a `SubjectPublicKey` value from DER-encoded SubjectPublicKeyInfo bytes
708
+ #[ cfg( feature = "x509-parser" ) ]
709
+ pub fn from_der ( spki_der : & [ u8 ] ) -> Result < Self , Error > {
710
+ use x509_parser:: {
711
+ prelude:: FromDer ,
712
+ x509:: { AlgorithmIdentifier , SubjectPublicKeyInfo } ,
713
+ } ;
714
+
715
+ let ( rem, spki) =
716
+ SubjectPublicKeyInfo :: from_der ( spki_der) . map_err ( |e| Error :: X509 ( e. to_string ( ) ) ) ?;
717
+ if !rem. is_empty ( ) {
718
+ return Err ( Error :: X509 (
719
+ "trailing bytes in SubjectPublicKeyInfo" . to_string ( ) ,
720
+ ) ) ;
721
+ }
722
+
723
+ let alg = SignatureAlgorithm :: iter ( )
724
+ . find ( |alg| {
725
+ let bytes = yasna:: construct_der ( |writer| {
726
+ alg. write_oids_sign_alg ( writer) ;
727
+ } ) ;
728
+ let Ok ( ( rest, aid) ) = AlgorithmIdentifier :: from_der ( & bytes) else {
729
+ return false ;
730
+ } ;
731
+ if !rest. is_empty ( ) {
732
+ return false ;
733
+ }
734
+ aid == spki. algorithm
735
+ } )
736
+ . ok_or ( Error :: UnsupportedSignatureAlgorithm ) ?;
737
+
738
+ Ok ( Self {
739
+ alg,
740
+ subject_public_key : Vec :: from ( spki. subject_public_key . as_ref ( ) ) ,
741
+ } )
742
+ }
743
+ }
744
+
745
+ impl PublicKeyData for SubjectPublicKeyInfo {
746
+ fn der_bytes ( & self ) -> & [ u8 ] {
747
+ & self . subject_public_key
748
+ }
749
+
750
+ fn algorithm ( & self ) -> & SignatureAlgorithm {
751
+ self . alg
752
+ }
753
+ }
754
+
693
755
/// The public key data of a key pair
694
756
pub trait PublicKeyData {
695
757
/// The public key in DER format
@@ -716,6 +778,30 @@ mod test {
716
778
signature:: { EcdsaKeyPair , ECDSA_P256_SHA256_FIXED_SIGNING } ,
717
779
} ;
718
780
781
+ #[ cfg( all( feature = "x509-parser" , feature = "pem" ) ) ]
782
+ #[ test]
783
+ fn test_subject_public_key_parsing ( ) {
784
+ for alg in [
785
+ & PKCS_ED25519 ,
786
+ & PKCS_ECDSA_P256_SHA256 ,
787
+ & PKCS_ECDSA_P384_SHA384 ,
788
+ #[ cfg( feature = "aws_lc_rs" ) ]
789
+ & PKCS_ECDSA_P521_SHA512 ,
790
+ #[ cfg( feature = "aws_lc_rs" ) ]
791
+ & PKCS_RSA_SHA256 ,
792
+ ] {
793
+ let kp = KeyPair :: generate_for ( alg) . expect ( "keygen" ) ;
794
+ let pem = kp. public_key_pem ( ) ;
795
+ let der = kp. public_key_der ( ) ;
796
+
797
+ let pkd_pem = SubjectPublicKeyInfo :: from_pem ( & pem) . expect ( "from pem" ) ;
798
+ assert_eq ! ( kp. der_bytes( ) , pkd_pem. der_bytes( ) ) ;
799
+
800
+ let pkd_der = SubjectPublicKeyInfo :: from_der ( & der) . expect ( "from der" ) ;
801
+ assert_eq ! ( kp. der_bytes( ) , pkd_der. der_bytes( ) ) ;
802
+ }
803
+ }
804
+
719
805
#[ test]
720
806
fn test_algorithm ( ) {
721
807
let rng = SystemRandom :: new ( ) ;
0 commit comments