diff options
Diffstat (limited to 'test/openssl/test_pkey_ec.rb')
-rw-r--r-- | test/openssl/test_pkey_ec.rb | 142 |
1 files changed, 95 insertions, 47 deletions
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb index 3f5958af50..2cb8e287ab 100644 --- a/test/openssl/test_pkey_ec.rb +++ b/test/openssl/test_pkey_ec.rb @@ -5,30 +5,18 @@ if defined?(OpenSSL) class OpenSSL::TestEC < OpenSSL::PKeyTestCase def test_ec_key - builtin_curves = OpenSSL::PKey::EC.builtin_curves - assert_not_empty builtin_curves - - builtin_curves.each do |curve_name, comment| - # Oakley curves and X25519 are not suitable for signing and causes - # FIPS-selftest failure on some environment, so skip for now. - next if ["Oakley", "X25519"].any? { |n| curve_name.start_with?(n) } - - key = OpenSSL::PKey::EC.new(curve_name) - key.generate_key! - - assert_predicate key, :private? - assert_predicate key, :public? - assert_nothing_raised { key.check_key } + key1 = OpenSSL::PKey::EC.generate("prime256v1") + + # PKey is immutable in OpenSSL >= 3.0; constructing an empty EC object is + # deprecated + if !openssl?(3, 0, 0) + key2 = OpenSSL::PKey::EC.new + key2.group = key1.group + key2.private_key = key1.private_key + key2.public_key = key1.public_key + assert_equal key1.to_der, key2.to_der end - key1 = OpenSSL::PKey::EC.new("prime256v1").generate_key! - - key2 = OpenSSL::PKey::EC.new - key2.group = key1.group - key2.private_key = key1.private_key - key2.public_key = key1.public_key - assert_equal key1.to_der, key2.to_der - key3 = OpenSSL::PKey::EC.new(key1) assert_equal key1.to_der, key3.to_der @@ -37,10 +25,25 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase key5 = key1.dup assert_equal key1.to_der, key5.to_der - key_tmp = OpenSSL::PKey::EC.new("prime256v1").generate_key! - key5.private_key = key_tmp.private_key - key5.public_key = key_tmp.public_key - assert_not_equal key1.to_der, key5.to_der + + # PKey is immutable in OpenSSL >= 3.0; EC object should not be modified + if !openssl?(3, 0, 0) + key_tmp = OpenSSL::PKey::EC.generate("prime256v1") + key5.private_key = key_tmp.private_key + key5.public_key = key_tmp.public_key + assert_not_equal key1.to_der, key5.to_der + end + end + + def test_builtin_curves + builtin_curves = OpenSSL::PKey::EC.builtin_curves + assert_not_empty builtin_curves + assert_equal 2, builtin_curves[0].size + assert_kind_of String, builtin_curves[0][0] + assert_kind_of String, builtin_curves[0][1] + + builtin_curve_names = builtin_curves.map { |name, comment| name } + assert_include builtin_curve_names, "prime256v1" end def test_generate @@ -52,6 +55,15 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase assert_equal(true, ec.private?) end + def test_generate_key + ec = OpenSSL::PKey::EC.new("prime256v1") + assert_equal false, ec.private? + assert_raise(OpenSSL::PKey::ECError) { ec.to_der } + ec.generate_key! + assert_equal true, ec.private? + assert_nothing_raised { ec.to_der } + end if !openssl?(3, 0, 0) + def test_marshal key = Fixtures.pkey("p256") deserialized = Marshal.load(Marshal.dump(key)) @@ -60,31 +72,42 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase end def test_check_key - key = OpenSSL::PKey::EC.new("prime256v1").generate_key! - assert_equal(true, key.check_key) - assert_equal(true, key.private?) - assert_equal(true, key.public?) - key2 = OpenSSL::PKey::EC.new(key.group) - assert_equal(false, key2.private?) - assert_equal(false, key2.public?) - key2.public_key = key.public_key - assert_equal(false, key2.private?) - assert_equal(true, key2.public?) - key2.private_key = key.private_key + key0 = Fixtures.pkey("p256") + assert_equal(true, key0.check_key) + assert_equal(true, key0.private?) + assert_equal(true, key0.public?) + + key1 = OpenSSL::PKey.read(key0.public_to_der) + assert_equal(true, key1.check_key) + assert_equal(false, key1.private?) + assert_equal(true, key1.public?) + + key2 = OpenSSL::PKey.read(key0.private_to_der) assert_equal(true, key2.private?) assert_equal(true, key2.public?) assert_equal(true, key2.check_key) - key2.private_key += 1 - assert_raise(OpenSSL::PKey::ECError) { key2.check_key } + + # Behavior of EVP_PKEY_public_check changes between OpenSSL 1.1.1 and 3.0 + key4 = Fixtures.pkey("p256_too_large") + assert_raise(OpenSSL::PKey::ECError) { key4.check_key } + + key5 = Fixtures.pkey("p384_invalid") + assert_raise(OpenSSL::PKey::ECError) { key5.check_key } + + # EC#private_key= is deprecated in 3.0 and won't work on OpenSSL 3.0 + if !openssl?(3, 0, 0) + key2.private_key += 1 + assert_raise(OpenSSL::PKey::ECError) { key2.check_key } + end end def test_sign_verify p256 = Fixtures.pkey("p256") data = "Sign me!" - signature = p256.sign("SHA1", data) - assert_equal true, p256.verify("SHA1", signature, data) + signature = p256.sign("SHA256", data) + assert_equal true, p256.verify("SHA256", signature, data) - signature0 = (<<~'end;').unpack("m")[0] + signature0 = (<<~'end;').unpack1("m") MEQCIEOTY/hD7eI8a0qlzxkIt8LLZ8uwiaSfVbjX2dPAvN11AiAQdCYx56Fq QdBp1B4sxJoA8jvODMMklMyBKVmudboA6A== end; @@ -107,7 +130,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase assert_equal [zIUT].pack("H*"), a.derive(b) assert_equal a.derive(b), a.dh_compute_key(b.public_key) - end + end if !openssl?(3, 0, 0) # TODO: Test it without using #private_key= def test_sign_verify_raw key = Fixtures.pkey("p256") @@ -136,7 +159,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase end def test_dsa_sign_asn1_FIPS186_3 - key = OpenSSL::PKey::EC.new("prime256v1").generate_key! + key = OpenSSL::PKey::EC.generate("prime256v1") size = key.group.order.num_bits / 8 + 1 dgst = (1..size).to_a.pack('C*') sig = key.dsa_sign_asn1(dgst) @@ -145,8 +168,8 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase end def test_dh_compute_key - key_a = OpenSSL::PKey::EC.new("prime256v1").generate_key! - key_b = OpenSSL::PKey::EC.new(key_a.group).generate_key! + key_a = OpenSSL::PKey::EC.generate("prime256v1") + key_b = OpenSSL::PKey::EC.generate(key_a.group) pub_a = key_a.public_key pub_b = key_b.public_key @@ -182,7 +205,32 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase assert_equal pem, p256.export end + def test_ECPrivateKey_with_parameters + p256 = Fixtures.pkey("p256") + + # The format used by "openssl ecparam -name prime256v1 -genkey -outform PEM" + # + # "EC PARAMETERS" block should be ignored if it is followed by an + # "EC PRIVATE KEY" block + in_pem = <<~EOF + -----BEGIN EC PARAMETERS----- + BggqhkjOPQMBBw== + -----END EC PARAMETERS----- + -----BEGIN EC PRIVATE KEY----- + MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49 + AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt + CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg== + -----END EC PRIVATE KEY----- + EOF + + key = OpenSSL::PKey::EC.new(in_pem) + assert_same_ec p256, key + assert_equal p256.to_der, key.to_der + end + def test_ECPrivateKey_encrypted + omit_on_fips + p256 = Fixtures.pkey("p256") # key = abcdef pem = <<~EOF @@ -276,7 +324,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase def test_ec_point group = OpenSSL::PKey::EC::Group.new("prime256v1") - key = OpenSSL::PKey::EC.new(group).generate_key! + key = OpenSSL::PKey::EC.generate(group) point = key.public_key point2 = OpenSSL::PKey::EC::Point.new(group, point.to_bn) |