@@ -209,3 +209,207 @@ fn test_signature_from_der_high_s_normalizes_and_flips_v() {
209209 assert_eq ! ( sig. s( ) , & expected_s_low) ;
210210 assert_eq ! ( sig. v( ) , v_initial ^ 1 ) ;
211211}
212+
213+ #[ test]
214+ fn test_public_key_from_der_success ( ) {
215+ // Build a valid SPKI DER for the compressed SEC1 point of our generated key.
216+ let mut rng = seeded_rng ( [ 9u8 ; 32 ] ) ;
217+ let secret_key = SecretKey :: with_rng ( & mut rng) ;
218+ let public_key = secret_key. public_key ( ) ;
219+ let public_key_bytes = public_key. to_bytes ( ) ; // compressed SEC1 (33 bytes).
220+
221+ // AlgorithmIdentifier: id-ecPublicKey + secp256k1
222+ let algo: [ u8 ; 18 ] = [
223+ 0x30 , 0x10 , // SEQUENCE, length 16
224+ 0x06 , 0x07 , 0x2a , 0x86 , 0x48 , 0xce , 0x3d , 0x02 , 0x01 , // OID 1.2.840.10045.2.1
225+ 0x06 , 0x05 , 0x2b , 0x81 , 0x04 , 0x00 , 0x0a , // OID 1.3.132.0.10 (secp256k1)
226+ ] ;
227+
228+ // subjectPublicKey BIT STRING: 0 unused bits + compressed SEC1.
229+ let mut spk = Vec :: with_capacity ( 2 + 1 + public_key_bytes. len ( ) ) ;
230+ spk. push ( 0x03 ) ; // BIT STRING
231+ spk. push ( ( 1 + public_key_bytes. len ( ) ) as u8 ) ; // length
232+ spk. push ( 0x00 ) ; // unused bits = 0
233+ spk. extend_from_slice ( & public_key_bytes) ;
234+
235+ // Outer SEQUENCE.
236+ let mut der = Vec :: with_capacity ( 2 + algo. len ( ) + spk. len ( ) ) ;
237+ der. push ( 0x30 ) ; // SEQUENCE
238+ der. push ( ( algo. len ( ) + spk. len ( ) ) as u8 ) ; // total length
239+ der. extend_from_slice ( & algo) ;
240+ der. extend_from_slice ( & spk) ;
241+
242+ let parsed = PublicKey :: from_der ( & der) . expect ( "should parse valid SPKI DER" ) ;
243+ assert_eq ! ( parsed, public_key) ;
244+ }
245+
246+ #[ test]
247+ fn test_public_key_from_der_invalid ( ) {
248+ // Empty DER.
249+ match PublicKey :: from_der ( & [ ] ) {
250+ Err ( super :: DeserializationError :: InvalidValue ( _) ) => { } ,
251+ other => panic ! ( "expected InvalidValue for empty DER, got {:?}" , other) ,
252+ }
253+
254+ // Malformed: SEQUENCE with zero length (missing fields).
255+ let der_bad: [ u8 ; 2 ] = [ 0x30 , 0x00 ] ;
256+ match PublicKey :: from_der ( & der_bad) {
257+ Err ( super :: DeserializationError :: InvalidValue ( _) ) => { } ,
258+ other => panic ! ( "expected InvalidValue for malformed DER, got {:?}" , other) ,
259+ }
260+ }
261+
262+ #[ test]
263+ fn test_public_key_from_der_rejects_non_canonical_long_form_length ( ) {
264+ // Build a valid SPKI structure but encode the outer SEQUENCE length using non-canonical
265+ // long-form (0x81 <len>) even though the length < 128. DER should reject this.
266+ let mut rng = seeded_rng ( [ 10u8 ; 32 ] ) ;
267+ let secret_key = SecretKey :: with_rng ( & mut rng) ;
268+ let public_key = secret_key. public_key ( ) ;
269+ let public_key_bytes = public_key. to_bytes ( ) ; // compressed SEC1 (33 bytes)
270+
271+ // AlgorithmIdentifier: id-ecPublicKey + secp256k1
272+ let algo: [ u8 ; 18 ] = [
273+ 0x30 , 0x10 , // SEQUENCE, length 16
274+ 0x06 , 0x07 , 0x2a , 0x86 , 0x48 , 0xce , 0x3d , 0x02 , 0x01 , // OID 1.2.840.10045.2.1
275+ 0x06 , 0x05 , 0x2b , 0x81 , 0x04 , 0x00 , 0x0a , // OID 1.3.132.0.10 (secp256k1)
276+ ] ;
277+
278+ // subjectPublicKey BIT STRING: 0 unused bits + compressed SEC1
279+ let mut spk = Vec :: with_capacity ( 2 + 1 + public_key_bytes. len ( ) ) ;
280+ spk. push ( 0x03 ) ; // BIT STRING
281+ spk. push ( ( 1 + public_key_bytes. len ( ) ) as u8 ) ; // length
282+ spk. push ( 0x00 ) ; // unused bits = 0
283+ spk. extend_from_slice ( & public_key_bytes) ;
284+
285+ // Outer SEQUENCE using non-canonical long-form length (0x81)
286+ let total_len = ( algo. len ( ) + spk. len ( ) ) as u8 ; // fits in one byte
287+ let mut der = Vec :: with_capacity ( 3 + algo. len ( ) + spk. len ( ) ) ;
288+ der. push ( 0x30 ) ; // SEQUENCE
289+ der. push ( 0x81 ) ; // long-form length marker with one subsequent length byte
290+ der. push ( total_len) ;
291+ der. extend_from_slice ( & algo) ;
292+ der. extend_from_slice ( & spk) ;
293+
294+ match PublicKey :: from_der ( & der) {
295+ Err ( super :: DeserializationError :: InvalidValue ( _) ) => { } ,
296+ other => {
297+ panic ! ( "expected InvalidValue for non-canonical long-form length, got {:?}" , other)
298+ } ,
299+ }
300+ }
301+
302+ #[ test]
303+ fn test_public_key_from_der_rejects_trailing_bytes ( ) {
304+ // Build a valid SPKI DER but append trailing bytes after the sequence; DER should reject.
305+ let mut rng = seeded_rng ( [ 11u8 ; 32 ] ) ;
306+ let secret_key = SecretKey :: with_rng ( & mut rng) ;
307+ let public_key = secret_key. public_key ( ) ;
308+ let public_key_bytes = public_key. to_bytes ( ) ; // compressed SEC1 (33 bytes)
309+
310+ // AlgorithmIdentifier: id-ecPublicKey + secp256k1.
311+ let algo: [ u8 ; 18 ] = [
312+ 0x30 , 0x10 , // SEQUENCE, length 16
313+ 0x06 , 0x07 , 0x2a , 0x86 , 0x48 , 0xce , 0x3d , 0x02 , 0x01 , // OID 1.2.840.10045.2.1
314+ 0x06 , 0x05 , 0x2b , 0x81 , 0x04 , 0x00 , 0x0a , // OID 1.3.132.0.10 (secp256k1)
315+ ] ;
316+
317+ // subjectPublicKey BIT STRING: 0 unused bits + compressed SEC1.
318+ let mut spk = Vec :: with_capacity ( 2 + 1 + public_key_bytes. len ( ) ) ;
319+ spk. push ( 0x03 ) ; // BIT STRING
320+ spk. push ( ( 1 + public_key_bytes. len ( ) ) as u8 ) ; // length
321+ spk. push ( 0x00 ) ; // unused bits = 0
322+ spk. extend_from_slice ( & public_key_bytes) ;
323+
324+ // Outer SEQUENCE with short-form length.
325+ let total_len = ( algo. len ( ) + spk. len ( ) ) as u8 ;
326+ let mut der = Vec :: with_capacity ( 2 + algo. len ( ) + spk. len ( ) + 2 ) ;
327+ der. push ( 0x30 ) ; // SEQUENCE
328+ der. push ( total_len) ;
329+ der. extend_from_slice ( & algo) ;
330+ der. extend_from_slice ( & spk) ;
331+
332+ // Append trailing junk.
333+ der. push ( 0x00 ) ;
334+ der. push ( 0x00 ) ;
335+
336+ match PublicKey :: from_der ( & der) {
337+ Err ( super :: DeserializationError :: InvalidValue ( _) ) => { } ,
338+ other => panic ! ( "expected InvalidValue for DER with trailing bytes, got {:?}" , other) ,
339+ }
340+ }
341+
342+ #[ test]
343+ fn test_public_key_from_der_rejects_wrong_curve_oid ( ) {
344+ // Same structure but with prime256v1 (P-256) curve OID instead of secp256k1.
345+ let mut rng = seeded_rng ( [ 12u8 ; 32 ] ) ;
346+ let secret_key = SecretKey :: with_rng ( & mut rng) ;
347+ let public_key = secret_key. public_key ( ) ;
348+ let public_key_bytes = public_key. to_bytes ( ) ; // compressed SEC1 (33 bytes)
349+
350+ // AlgorithmIdentifier: id-ecPublicKey + prime256v1 (1.2.840.10045.3.1.7).
351+ // Completed prime256v1 OID tail for correctness
352+ // Full DER OID bytes for 1.2.840.10045.3.1.7 are: 06 08 2A 86 48 CE 3D 03 01 07
353+ // We'll encode properly below with 8 length, then adjust the outer lengths accordingly.
354+
355+ // AlgorithmIdentifier with correct OID encoding but wrong curve:
356+ let algo_full: [ u8 ; 21 ] = [
357+ 0x30 , 0x12 , // SEQUENCE, length 18
358+ 0x06 , 0x07 , 0x2a , 0x86 , 0x48 , 0xce , 0x3d , 0x02 , 0x01 , // id-ecPublicKey
359+ 0x06 , 0x08 , 0x2a , 0x86 , 0x48 , 0xce , 0x3d , 0x03 , 0x01 , 0x07 , // prime256v1
360+ ] ;
361+
362+ // subjectPublicKey BIT STRING.
363+ let mut spk = Vec :: with_capacity ( 2 + 1 + public_key_bytes. len ( ) ) ;
364+ spk. push ( 0x03 ) ;
365+ spk. push ( ( 1 + public_key_bytes. len ( ) ) as u8 ) ;
366+ spk. push ( 0x00 ) ;
367+ spk. extend_from_slice ( & public_key_bytes) ;
368+
369+ let mut der = Vec :: with_capacity ( 2 + algo_full. len ( ) + spk. len ( ) ) ;
370+ der. push ( 0x30 ) ;
371+ der. push ( ( algo_full. len ( ) + spk. len ( ) ) as u8 ) ;
372+ der. extend_from_slice ( & algo_full) ;
373+ der. extend_from_slice ( & spk) ;
374+
375+ match PublicKey :: from_der ( & der) {
376+ Err ( super :: DeserializationError :: InvalidValue ( _) ) => { } ,
377+ other => panic ! ( "expected InvalidValue for wrong curve OID, got {:?}" , other) ,
378+ }
379+ }
380+
381+ #[ test]
382+ fn test_public_key_from_der_rejects_wrong_algorithm_oid ( ) {
383+ // Use rsaEncryption (1.2.840.113549.1.1.1) instead of id-ecPublicKey.
384+ let mut rng = seeded_rng ( [ 13u8 ; 32 ] ) ;
385+ let secret_key = SecretKey :: with_rng ( & mut rng) ;
386+ let public_key = secret_key. public_key ( ) ;
387+ let public_key_bytes = public_key. to_bytes ( ) ;
388+
389+ // AlgorithmIdentifier: rsaEncryption + NULL parameter.
390+ // OID bytes for 1.2.840.113549.1.1.1: 06 09 2A 86 48 86 F7 0D 01 01 01.
391+ // NULL parameter: 05 00.
392+ let algo_rsa: [ u8 ; 15 ] = [
393+ 0x30 , 0x0d , // SEQUENCE, length 13
394+ 0x06 , 0x09 , 0x2a , 0x86 , 0x48 , 0x86 , 0xf7 , 0x0d , 0x01 , 0x01 , 0x01 , // rsaEncryption
395+ 0x05 , 0x00 , // NULL
396+ ] ;
397+
398+ // subjectPublicKey BIT STRING with EC compressed point (intentionally mismatched with algo).
399+ let mut spk = Vec :: with_capacity ( 2 + 1 + public_key_bytes. len ( ) ) ;
400+ spk. push ( 0x03 ) ;
401+ spk. push ( ( 1 + public_key_bytes. len ( ) ) as u8 ) ;
402+ spk. push ( 0x00 ) ;
403+ spk. extend_from_slice ( & public_key_bytes) ;
404+
405+ let mut der = Vec :: with_capacity ( 2 + algo_rsa. len ( ) + spk. len ( ) ) ;
406+ der. push ( 0x30 ) ;
407+ der. push ( ( algo_rsa. len ( ) + spk. len ( ) ) as u8 ) ;
408+ der. extend_from_slice ( & algo_rsa) ;
409+ der. extend_from_slice ( & spk) ;
410+
411+ match PublicKey :: from_der ( & der) {
412+ Err ( super :: DeserializationError :: InvalidValue ( _) ) => { } ,
413+ other => panic ! ( "expected InvalidValue for wrong algorithm OID, got {:?}" , other) ,
414+ }
415+ }
0 commit comments