@@ -370,6 +370,124 @@ def test_sign_verify_raw
370
370
assert_raise ( OpenSSL ::PKey ::ECError ) { key . dsa_verify_asn1 ( data1 , malformed_sig ) }
371
371
end
372
372
373
+ def test_new_from_der
374
+ priv_key_hex = '05768F097A19FFE5022D4A862CDBAE22019695D1C2F88FD41607417AD45E2F55'
375
+ pub_key_hex = '04B827833DC1BC38CE0BBE36E0357B1D08AB0BFA05DBD211F0FC677FF9913FAF0EB3A3CC562EEAE8D841B112DBFDAD494E10CFBD4964DC2D175D06F17ACC5771CF'
376
+ do_test_from_sequence ( 'prime256v1' , pub_key_hex , priv_key_hex )
377
+ do_test_from_sequence ( 'prime256v1' , pub_key_hex , nil )
378
+
379
+ priv_key_hex = 'D4E775192298037DAD55150AE76C8585CE4AD628897F5F9F02762C416F1D4A33'
380
+ pub_key_hex = '0456D3DD1587DE605D167AB037FF9856B58705970BA3AE49E68CDFA8A5D580EC506E1D6F1AEFE5621EF458322F68C59D461FC5D3633881D82BD8E4AF7924306979'
381
+ do_test_from_sequence ( 'prime256v1' , pub_key_hex , priv_key_hex )
382
+ do_test_from_sequence ( 'prime256v1' , pub_key_hex , nil )
383
+
384
+ priv_key_hex = '9174C3E24DBA2AADE34D4885371B0AEA89D44CFEC70348C9FF5EB3207550F18A'
385
+ pub_key_hex = '048344CA3520410CFD1D77FEA79AF543A2769545D6D143A12E86AC8F65D9280049FDC88A883D748C6229D9210AD0984DD4ED8F7742ECC0588409446FF6BC8830AA'
386
+ do_test_from_sequence ( 'prime256v1' , pub_key_hex , priv_key_hex )
387
+ do_test_from_sequence ( 'prime256v1' , pub_key_hex , nil )
388
+ end
389
+
390
+ def do_test_from_sequence ( curve , pub_key_hex , priv_key_hex )
391
+ group = OpenSSL ::PKey ::EC ::Group . new ( curve )
392
+ d = OpenSSL ::BN . new ( priv_key_hex , 16 ) if priv_key_hex # private_key
393
+ point = OpenSSL ::PKey ::EC ::Point . new ( group , OpenSSL ::BN . new ( pub_key_hex , 16 ) ) # public_key (x, y)
394
+
395
+ sequence = if priv_key_hex
396
+ # https://datatracker.ietf.org/doc/html/rfc5915.html
397
+ # ECPrivateKey ::= SEQUENCE {
398
+ # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
399
+ # privateKey OCTET STRING,
400
+ # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
401
+ # publicKey [1] BIT STRING OPTIONAL
402
+ # }
403
+
404
+ OpenSSL ::ASN1 ::Sequence ( [
405
+ OpenSSL ::ASN1 ::Integer ( 1 ) ,
406
+ OpenSSL ::ASN1 ::OctetString ( d . to_s ( 2 ) ) ,
407
+ OpenSSL ::ASN1 ::ObjectId ( curve , 0 , :EXPLICIT ) ,
408
+ OpenSSL ::ASN1 ::BitString ( point . to_octet_string ( :uncompressed ) , 1 , :EXPLICIT )
409
+ ] )
410
+ else
411
+ OpenSSL ::ASN1 ::Sequence ( [
412
+ OpenSSL ::ASN1 ::Sequence ( [ OpenSSL ::ASN1 ::ObjectId ( 'id-ecPublicKey' ) , OpenSSL ::ASN1 ::ObjectId ( curve ) ] ) ,
413
+ OpenSSL ::ASN1 ::BitString ( point . to_octet_string ( :uncompressed ) )
414
+ ] )
415
+ end
416
+
417
+ key = OpenSSL ::PKey ::EC . new ( sequence . to_der )
418
+ assert_equal group . curve_name , key . group . curve_name
419
+ assert_equal group , key . group
420
+ assert_equal point , key . public_key
421
+ assert_equal d , key . private_key if d
422
+ end
423
+ private :do_test_from_sequence
424
+
425
+ def test_new_from_der_jwt_style
426
+ jwk_x = "g0TKNSBBDP0dd_6nmvVDonaVRdbRQ6EuhqyPZdkoAEk"
427
+ jwk_y = "_ciKiD10jGIp2SEK0JhN1O2Pd0LswFiECURv9ryIMKo"
428
+ do_test_from_sequence_with_packed_point ( 'prime256v1' , jwk_x , jwk_y )
429
+
430
+ jwk_x = "ts5_Jv5_QkWPVkaC_Y7rGZ2gdeJSkDR3I96M2CuVNtU"
431
+ jwk_y = "fCLLRp7lX_Q8g60IRhT8sNONGTjNmoTWUny8FPe91Gs"
432
+ do_test_from_sequence_with_packed_point ( 'prime256v1' , jwk_x , jwk_y )
433
+
434
+ jwk_x = "iIv_aqVNBfTBr3C7u8E3kYrWbYXjHnH9jLzbBkl1PqA"
435
+ jwk_y = "sXueAB7o9QmrmDQGGy7hqN0bx5gOxYDJyLQAMDNMRBw"
436
+ jwk_d = "-KgbRgiVEztCTgxSZmScegXkBVNokqZlCodlpakFtFc"
437
+ do_test_from_sequence_with_packed_point ( 'prime256v1' , jwk_x , jwk_y , jwk_d )
438
+ do_test_from_sequence_with_packed_point ( 'prime256v1' , jwk_x , jwk_y )
439
+
440
+ jwk_x = "mAObq2aOmjkZwS5ruLmZITbXKTepItbnyrMm1VWGeeg"
441
+ jwk_y = "EtQDulK7N-v_0mdbFQe-bNCyc-ey1sPRa1l--_7vAiA"
442
+ do_test_from_sequence_with_packed_point ( 'prime256v1' , jwk_x , jwk_y ) # GH-318
443
+ end
444
+
445
+ def do_test_from_sequence_with_packed_point ( curve , jwk_x , jwk_y , jwk_d = nil )
446
+ group = OpenSSL ::PKey ::EC ::Group . new ( curve )
447
+ d = OpenSSL ::BN . new ( decode_octets ( jwk_d ) , 2 ) if jwk_d
448
+
449
+ x_octets = decode_octets ( jwk_x )
450
+ y_octets = decode_octets ( jwk_y )
451
+
452
+ point = OpenSSL ::PKey ::EC ::Point . new ( group , OpenSSL ::BN . new ( [ 0x04 , x_octets , y_octets ] . pack ( 'Ca*a*' ) , 2 ) )
453
+
454
+ sequence = if jwk_d
455
+ # https://datatracker.ietf.org/doc/html/rfc5915.html
456
+ # ECPrivateKey ::= SEQUENCE {
457
+ # version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1),
458
+ # privateKey OCTET STRING,
459
+ # parameters [0] ECParameters {{ NamedCurve }} OPTIONAL,
460
+ # publicKey [1] BIT STRING OPTIONAL
461
+ # }
462
+
463
+ OpenSSL ::ASN1 ::Sequence ( [
464
+ OpenSSL ::ASN1 ::Integer ( 1 ) ,
465
+ OpenSSL ::ASN1 ::OctetString ( OpenSSL ::BN . new ( decode_octets ( jwk_d ) , 2 ) . to_s ( 2 ) ) ,
466
+ OpenSSL ::ASN1 ::ObjectId ( curve , 0 , :EXPLICIT ) ,
467
+ OpenSSL ::ASN1 ::BitString ( point . to_octet_string ( :uncompressed ) , 1 , :EXPLICIT )
468
+ ] )
469
+ else
470
+ OpenSSL ::ASN1 ::Sequence ( [
471
+ OpenSSL ::ASN1 ::Sequence ( [ OpenSSL ::ASN1 ::ObjectId ( 'id-ecPublicKey' ) , OpenSSL ::ASN1 ::ObjectId ( curve ) ] ) ,
472
+ OpenSSL ::ASN1 ::BitString ( point . to_octet_string ( :uncompressed ) )
473
+ ] )
474
+ end
475
+
476
+ key = OpenSSL ::PKey ::EC . new ( sequence . to_der )
477
+ assert_equal group . curve_name , key . group . curve_name
478
+ assert_equal group , key . group
479
+ assert_equal point , key . public_key
480
+ assert_equal d , key . private_key if d
481
+ end
482
+ private :do_test_from_sequence
483
+
484
+ def decode_octets ( base64_encoded_coordinate ) ; require 'base64'
485
+ bytes = ::Base64 . urlsafe_decode64 ( base64_encoded_coordinate )
486
+ assert_false bytes . bytesize . odd?
487
+ bytes
488
+ end
489
+ private :decode_octets
490
+
373
491
# def test_dh_compute_key
374
492
# for key in @keys
375
493
# k = OpenSSL::PKey::EC.new(key.group)
0 commit comments