Skip to content

Commit 19e0b1b

Browse files
committed
[test] a bunch of PKey::EC.new parsing (based on jwt gem)
1 parent 8cbe28c commit 19e0b1b

File tree

1 file changed

+118
-0
lines changed

1 file changed

+118
-0
lines changed

src/test/ruby/ec/test_ec.rb

+118
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,124 @@ def test_sign_verify_raw
370370
assert_raise(OpenSSL::PKey::ECError) { key.dsa_verify_asn1(data1, malformed_sig) }
371371
end
372372

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+
373491
# def test_dh_compute_key
374492
# for key in @keys
375493
# k = OpenSSL::PKey::EC.new(key.group)

0 commit comments

Comments
 (0)