@@ -75,22 +75,36 @@ impl EmailVerifier for DefaultEmailVerifier {
7575 let normalized = normalize_algorithm ( algorithm) ;
7676 match normalized. as_str ( ) {
7777 "ed25519" => {
78+ // Ed25519: expects raw 32-byte public key — pass through
7879 crate :: crypt:: ringwrapper:: verify_string (
7980 public_key. to_vec ( ) ,
8081 data_str,
8182 & sig_b64,
8283 )
8384 }
8485 "rsa-pss" => {
86+ // RSA-PSS: expects PEM text bytes. If we received raw DER
87+ // (from haisdk extract_public_key_bytes), re-wrap as PEM.
88+ let pem_bytes = if public_key. starts_with ( b"-----" ) {
89+ public_key. to_vec ( )
90+ } else {
91+ pem_encode_spki ( public_key)
92+ } ;
8593 crate :: crypt:: rsawrapper:: verify_string (
86- public_key . to_vec ( ) ,
94+ pem_bytes ,
8795 data_str,
8896 & sig_b64,
8997 )
9098 }
9199 "pq2025" | "ml-dsa-87" => {
100+ // PQ2025: expects raw key bytes of ML_DSA_87_PUBLIC_KEY_SIZE.
101+ // If we received SPKI-wrapped DER, strip the wrapper.
102+ let raw_key = strip_spki_wrapper_if_needed (
103+ public_key,
104+ crate :: crypt:: constants:: ML_DSA_87_PUBLIC_KEY_SIZE ,
105+ ) ;
92106 crate :: crypt:: pq2025:: verify_string (
93- public_key . to_vec ( ) ,
107+ raw_key ,
94108 data_str,
95109 & sig_b64,
96110 )
@@ -100,6 +114,35 @@ impl EmailVerifier for DefaultEmailVerifier {
100114 }
101115}
102116
117+ /// PEM-encode a DER-encoded SubjectPublicKeyInfo block.
118+ fn pem_encode_spki ( der : & [ u8 ] ) -> Vec < u8 > {
119+ let b64 = base64:: engine:: general_purpose:: STANDARD . encode ( der) ;
120+ let mut pem = String :: from ( "-----BEGIN PUBLIC KEY-----\n " ) ;
121+ for chunk in b64. as_bytes ( ) . chunks ( 64 ) {
122+ pem. push_str ( std:: str:: from_utf8 ( chunk) . unwrap_or ( "" ) ) ;
123+ pem. push ( '\n' ) ;
124+ }
125+ pem. push_str ( "-----END PUBLIC KEY-----\n " ) ;
126+ pem. into_bytes ( )
127+ }
128+
129+ /// Strip SPKI wrapper from DER-encoded public key if the key is larger than
130+ /// the expected raw size. SPKI adds an AlgorithmIdentifier prefix; the raw
131+ /// key bytes are in the trailing BIT STRING.
132+ fn strip_spki_wrapper_if_needed ( key : & [ u8 ] , expected_raw_size : usize ) -> Vec < u8 > {
133+ if key. len ( ) == expected_raw_size {
134+ return key. to_vec ( ) ;
135+ }
136+ // SPKI-wrapped key: the raw key is the last `expected_raw_size` bytes
137+ // after the AlgorithmIdentifier + BIT STRING overhead.
138+ if key. len ( ) > expected_raw_size {
139+ return key[ key. len ( ) - expected_raw_size..] . to_vec ( ) ;
140+ }
141+ // Key is smaller than expected — pass through and let the crypto
142+ // wrapper produce a descriptive error.
143+ key. to_vec ( )
144+ }
145+
103146/// Extract and validate the JACS email signature document from a raw email.
104147///
105148/// This function:
0 commit comments