summaryrefslogtreecommitdiff
path: root/test/openssl/test_pkey_ec.rb
diff options
context:
space:
mode:
Diffstat (limited to 'test/openssl/test_pkey_ec.rb')
-rw-r--r--test/openssl/test_pkey_ec.rb180
1 files changed, 126 insertions, 54 deletions
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index 80ae9ffdf1..2cb8e287ab 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -1,34 +1,22 @@
# frozen_string_literal: true
require_relative 'utils'
-if defined?(OpenSSL) && defined?(OpenSSL::PKey::EC)
+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,19 +130,36 @@ 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_dsa_sign_verify
+ def test_sign_verify_raw
+ key = Fixtures.pkey("p256")
data1 = "foo"
data2 = "bar"
- key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
+
+ malformed_sig = "*" * 30
+
+ # Sign by #dsa_sign_asn1
sig = key.dsa_sign_asn1(data1)
assert_equal true, key.dsa_verify_asn1(data1, sig)
assert_equal false, key.dsa_verify_asn1(data2, sig)
+ assert_raise(OpenSSL::PKey::ECError) { key.dsa_verify_asn1(data1, malformed_sig) }
+ assert_equal true, key.verify_raw(nil, sig, data1)
+ assert_equal false, key.verify_raw(nil, sig, data2)
+ assert_raise(OpenSSL::PKey::PKeyError) { key.verify_raw(nil, malformed_sig, data1) }
+
+ # Sign by #sign_raw
+ sig = key.sign_raw(nil, data1)
+ assert_equal true, key.dsa_verify_asn1(data1, sig)
+ assert_equal false, key.dsa_verify_asn1(data2, sig)
+ assert_raise(OpenSSL::PKey::ECError) { key.dsa_verify_asn1(data1, malformed_sig) }
+ assert_equal true, key.verify_raw(nil, sig, data1)
+ assert_equal false, key.verify_raw(nil, sig, data2)
+ assert_raise(OpenSSL::PKey::PKeyError) { key.verify_raw(nil, malformed_sig, data1) }
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)
@@ -128,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
@@ -165,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
@@ -193,6 +258,8 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
def test_PUBKEY
p256 = Fixtures.pkey("p256")
+ p256pub = OpenSSL::PKey::EC.new(p256.public_to_der)
+
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
@@ -204,7 +271,7 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
])
key = OpenSSL::PKey::EC.new(asn1.to_der)
assert_not_predicate key, :private?
- assert_same_ec dup_public(p256), key
+ assert_same_ec p256pub, key
pem = <<~EOF
-----BEGIN PUBLIC KEY-----
@@ -213,10 +280,15 @@ class OpenSSL::TestEC < OpenSSL::PKeyTestCase
-----END PUBLIC KEY-----
EOF
key = OpenSSL::PKey::EC.new(pem)
- assert_same_ec dup_public(p256), key
+ assert_same_ec p256pub, key
+
+ assert_equal asn1.to_der, key.to_der
+ assert_equal pem, key.export
- assert_equal asn1.to_der, dup_public(p256).to_der
- assert_equal pem, dup_public(p256).export
+ assert_equal asn1.to_der, p256.public_to_der
+ assert_equal asn1.to_der, key.public_to_der
+ assert_equal pem, p256.public_to_pem
+ assert_equal pem, key.public_to_pem
end
def test_ec_group
@@ -252,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)