1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00
ruby--ruby/test/openssl/test_pkey_ec.rb
rhe 609103dbb5 openssl: import v2.1.0.beta1
Import Ruby/OpenSSL 2.1.0.beta1. The full commit log since v2.0.5
(imported by r59567) can be found at:

	https://github.com/ruby/openssl/compare/v2.0.5...v2.1.0.beta1

----------------------------------------------------------------
Antonio Terceiro (1):
      test/test_ssl: explicitly accept TLS 1.1 in corresponding test

Colby Swandale (1):
      document using secure protocol to fetch git master in Bundler

Colton Jenkins (1):
      Add fips_mode_get to return fips_mode

Kazuki Yamaguchi (85):
      Start preparing for 2.1.0
      Remove support for OpenSSL 0.9.8 and 1.0.0
      bn: refine tests
      bn: implement unary {plus,minus} operators for OpenSSL::BN
      bn: implement OpenSSL::BN#negative?
      Don't define main() when built with --enable-debug
      test: let OpenSSL::TestCase include OpenSSL::TestUtils
      test: prepare test PKey instances on demand
      Add OpenSSL.print_mem_leaks
      Enable OSSL_MDEBUG on CI builds
      ssl: move default DH parameters from OpenSSL::PKey::DH
      Make exceptions with the same format regardless of OpenSSL.debug
      ssl: show reason of 'certificate verify error' in exception message
      ssl: remove OpenSSL::ExtConfig::TLS_DH_anon_WITH_AES_256_GCM_SHA384
      ssl: do not confuse different ex_data index registries
      ssl: assume SSL/SSL_CTX always have a valid reference to the Ruby object
      Fix RDoc markup
      ssl: suppress compiler warning
      ext/openssl/deprecation.rb: remove broken-apple-openssl
      extconf.rb: print informative message if OpenSSL can't be found
      Rakefile: compile the extension before test
      kdf: introduce OpenSSL::KDF module
      ossl.h: add NUM2UINT64T() macro
      kdf: add scrypt
      Expand rb_define_copy_func() macro
      Expand FPTR_TO_FD() macro
      Remove SafeGet*() macros
      cipher: rename GetCipherPtr() to ossl_evp_get_cipherbyname()
      digest: rename GetDigestPtr() to ossl_evp_get_digestbyname()
      Add ossl_str_new(), an exception-safe rb_str_new()
      bio: simplify ossl_membio2str() using ossl_str_new()
      Remove unused functions and macros
      Drop support for LibreSSL 2.3
      ocsp: add OpenSSL::OCSP::Request#signed?
      asn1: infinite length -> indefinite length
      asn1: rearrange tests
      ssl: remove a needless NULL check in SSL::SSLContext#ciphers
      ssl: return nil in SSL::SSLSocket#cipher if session is not started
      asn1: remove an unnecessary function prototype
      asn1: require tag information when instantiating generic type
      asn1: initialize 'unused_bits' attribute of BitString with 0
      asn1: check for illegal 'unused_bits' value of BitString
      asn1: disallow NULL to be passed to asn1time_to_time()
      asn1: avoid truncating OID in OpenSSL::ASN1::ObjectId#oid
      asn1: allow constructed encoding with definite length form
      asn1: prohibit indefinite length form for primitive encoding
      asn1: allow tag number to be >= 32 for universal tag class
      asn1: use ossl_asn1_tag()
      asn1: clean up OpenSSL::ASN1::Constructive#to_der
      asn1: harmonize OpenSSL::ASN1::*#to_der
      asn1: prevent EOC octets from being in the middle of the content
      asn1: do not treat EOC octets as part of content octets
      x509name: add 'loc' and 'set' kwargs to OpenSSL::X509::Name#add_entry
      ssl: do not call session_remove_cb during GC
      Backport "Merge branch 'topic/test-memory-leak'" to maint
      cipher: update the documentation for Cipher#auth_tag=
      Rakefile: let sync:to_ruby know about test/openssl/fixtures
      test: fix formatting
      test/utils: remove OpenSSL::TestUtils.silent
      test/utils: add SSLTestCase#tls12_supported?
      test/utils: have start_server yield only the port number
      test/utils: do not set ecdh_curves in start_server
      test/utils: let server_loop close socket
      test/utils: improve error handling in start_server
      test/utils: add OpenSSL::TestUtils.openssl? and .libressl?
      test/utils: do not use DSA certificates in SSL tests
      test/test_ssl: remove test_invalid_shutdown_by_gc
      test/test_ssl: move test_multibyte_read_write to test_pair
      test/test_ssl_session: rearrange tests
      test/test_pair, test/test_ssl: fix for TLS 1.3
      ssl: remove useless call to rb_thread_wait_fd()
      ssl: fix NPN support
      ssl: mark OpenSSL::SSL::SSLContext::DEFAULT_{1024,2048} as private
      ssl: use 2048-bit group in the default tmp_dh_cb
      ssl: ensure that SSL option flags are non-negative
      ssl: update OpenSSL::SSL::OP_* flags
      ssl: prefer TLS_method() over SSLv23_method()
      ssl: add SSLContext#min_version= and #max_version=
      ssl: rework SSLContext#ssl_version=
      test/test_x509name: change script encoding to ASCII-8BIT
      x509name: refactor OpenSSL::X509::Name#to_s
      x509name: add OpenSSL::X509::Name#to_utf8
      x509name: add OpenSSL::X509::Name#inspect
      x509name: update regexp in OpenSSL::X509::Name.parse
      Ruby/OpenSSL 2.1.0.beta1

Marcus Stollsteimer (1):
      Fix rdoc for core Integer class

nobu (4):
      [DOC] {read,write}_nonblock with exception: false
      [DOC] keyword argument _exception_
      [DOC] mark up literals
      Revert r57690 except for read_nonblock

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59734 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
2017-09-03 12:35:27 +00:00

324 lines
11 KiB
Ruby

# frozen_string_literal: false
require_relative 'utils'
if defined?(OpenSSL) && defined?(OpenSSL::PKey::EC)
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 }
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
key4 = OpenSSL::PKey::EC.new(key1.to_der)
assert_equal key1.to_der, key4.to_der
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
end
def test_generate
assert_raise(OpenSSL::PKey::ECError) { OpenSSL::PKey::EC.generate("non-existent") }
g = OpenSSL::PKey::EC::Group.new("prime256v1")
ec = OpenSSL::PKey::EC.generate(g)
assert_equal(true, ec.private?)
ec = OpenSSL::PKey::EC.generate("prime256v1")
assert_equal(true, ec.private?)
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
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 }
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)
signature0 = (<<~'end;').unpack("m")[0]
MEQCIEOTY/hD7eI8a0qlzxkIt8LLZ8uwiaSfVbjX2dPAvN11AiAQdCYx56Fq
QdBp1B4sxJoA8jvODMMklMyBKVmudboA6A==
end;
assert_equal true, p256.verify("SHA256", signature0, data)
signature1 = signature0.succ
assert_equal false, p256.verify("SHA256", signature1, data)
end
def test_dsa_sign_verify
data1 = "foo"
data2 = "bar"
key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
sig = key.dsa_sign_asn1(data1)
assert_equal true, key.dsa_verify_asn1(data1, sig)
assert_equal false, key.dsa_verify_asn1(data2, sig)
end
def test_dsa_sign_asn1_FIPS186_3
key = OpenSSL::PKey::EC.new("prime256v1").generate_key!
size = key.group.order.num_bits / 8 + 1
dgst = (1..size).to_a.pack('C*')
sig = key.dsa_sign_asn1(dgst)
# dgst is auto-truncated according to FIPS186-3 after openssl-0.9.8m
assert(key.dsa_verify_asn1(dgst + "garbage", sig))
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!
pub_a = key_a.public_key
pub_b = key_b.public_key
a = key_a.dh_compute_key(pub_b)
b = key_b.dh_compute_key(pub_a)
assert_equal a, b
end
def test_ECPrivateKey
p256 = Fixtures.pkey("p256")
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Integer(1),
OpenSSL::ASN1::OctetString(p256.private_key.to_s(2)),
OpenSSL::ASN1::ASN1Data.new(
[OpenSSL::ASN1::ObjectId("prime256v1")],
0, :CONTEXT_SPECIFIC
),
OpenSSL::ASN1::ASN1Data.new(
[OpenSSL::ASN1::BitString(p256.public_key.to_bn.to_s(2))],
1, :CONTEXT_SPECIFIC
)
])
key = OpenSSL::PKey::EC.new(asn1.to_der)
assert_predicate key, :private?
assert_same_ec p256, key
pem = <<~EOF
-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIID49FDqcf1O1eO8saTgG70UbXQw9Fqwseliit2aWhH1oAoGCCqGSM49
AwEHoUQDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7lSZ/ArK41eGy5wAzU/0G51Xtt
CeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg==
-----END EC PRIVATE KEY-----
EOF
key = OpenSSL::PKey::EC.new(pem)
assert_same_ec p256, key
assert_equal asn1.to_der, p256.to_der
assert_equal pem, p256.export
end
def test_ECPrivateKey_encrypted
p256 = Fixtures.pkey("p256")
# key = abcdef
pem = <<~EOF
-----BEGIN EC PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-128-CBC,85743EB6FAC9EA76BF99D9328AFD1A66
nhsP1NHxb53aeZdzUe9umKKyr+OIwQq67eP0ONM6E1vFTIcjkDcFLR6PhPFufF4m
y7E2HF+9uT1KPQhlE+D63i1m1Mvez6PWfNM34iOQp2vEhaoHHKlR3c43lLyzaZDI
0/dGSU5SzFG+iT9iFXCwCvv+bxyegkBOyALFje1NAsM=
-----END EC PRIVATE KEY-----
EOF
key = OpenSSL::PKey::EC.new(pem, "abcdef")
assert_same_ec p256, key
key = OpenSSL::PKey::EC.new(pem) { "abcdef" }
assert_same_ec p256, key
cipher = OpenSSL::Cipher.new("aes-128-cbc")
exported = p256.to_pem(cipher, "abcdef\0\1")
assert_same_ec p256, OpenSSL::PKey::EC.new(exported, "abcdef\0\1")
assert_raise(OpenSSL::PKey::ECError) {
OpenSSL::PKey::EC.new(exported, "abcdef")
}
end
def test_PUBKEY
p256 = Fixtures.pkey("p256")
asn1 = OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::Sequence([
OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
OpenSSL::ASN1::ObjectId("prime256v1")
]),
OpenSSL::ASN1::BitString(
p256.public_key.to_bn.to_s(2)
)
])
key = OpenSSL::PKey::EC.new(asn1.to_der)
assert_not_predicate key, :private?
assert_same_ec dup_public(p256), key
pem = <<~EOF
-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEFglk2c+oVUIKQ64eZG9bhLNPWB7l
SZ/ArK41eGy5wAzU/0G51XttCeBUl+MahZtn9fO1JKdF4qJmS39dXnpENg==
-----END PUBLIC KEY-----
EOF
key = OpenSSL::PKey::EC.new(pem)
assert_same_ec dup_public(p256), key
assert_equal asn1.to_der, dup_public(p256).to_der
assert_equal pem, dup_public(p256).export
end
def test_ec_group
group1 = OpenSSL::PKey::EC::Group.new("prime256v1")
key1 = OpenSSL::PKey::EC.new(group1)
assert_equal group1, key1.group
group2 = OpenSSL::PKey::EC::Group.new(group1)
assert_equal group1.to_der, group2.to_der
assert_equal group1, group2
group2.asn1_flag ^=OpenSSL::PKey::EC::NAMED_CURVE
assert_not_equal group1.to_der, group2.to_der
assert_equal group1, group2
group3 = group1.dup
assert_equal group1.to_der, group3.to_der
assert group1.asn1_flag & OpenSSL::PKey::EC::NAMED_CURVE # our default
der = group1.to_der
group4 = OpenSSL::PKey::EC::Group.new(der)
group1.point_conversion_form = group4.point_conversion_form = :uncompressed
assert_equal :uncompressed, group1.point_conversion_form
assert_equal :uncompressed, group4.point_conversion_form
assert_equal group1, group4
assert_equal group1.curve_name, group4.curve_name
assert_equal group1.generator.to_bn, group4.generator.to_bn
assert_equal group1.order, group4.order
assert_equal group1.cofactor, group4.cofactor
assert_equal group1.seed, group4.seed
assert_equal group1.degree, group4.degree
end
def test_ec_point
group = OpenSSL::PKey::EC::Group.new("prime256v1")
key = OpenSSL::PKey::EC.new(group).generate_key!
point = key.public_key
point2 = OpenSSL::PKey::EC::Point.new(group, point.to_bn)
assert_equal point, point2
assert_equal point.to_bn, point2.to_bn
point2.invert!
assert_not_equal point.to_bn, point2.to_bn
begin
group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2)
group.point_conversion_form = :uncompressed
generator = OpenSSL::PKey::EC::Point.new(group, 0x040501.to_bn)
group.set_generator(generator, 19, 1)
point = OpenSSL::PKey::EC::Point.new(group, 0x040603.to_bn)
rescue OpenSSL::PKey::EC::Group::Error
pend "Patched OpenSSL rejected curve" if /unsupported field/ =~ $!.message
raise
end
assert_equal 0x040603.to_bn, point.to_bn(:uncompressed)
assert_equal 0x0306.to_bn, point.to_bn(:compressed)
assert_equal 0x070603.to_bn, point.to_bn(:hybrid)
assert_equal 0x040603.to_bn, point.to_bn
assert_equal true, point.on_curve?
point.invert! # 8.5
assert_equal 0x04060E.to_bn, point.to_bn
assert_equal true, point.on_curve?
assert_equal false, point.infinity?
point.set_to_infinity!
assert_equal true, point.infinity?
assert_equal 0.to_bn, point.to_bn
assert_equal true, point.on_curve?
end
def test_ec_point_mul
begin
# y^2 = x^3 + 2x + 2 over F_17
# generator is (5, 1)
group = OpenSSL::PKey::EC::Group.new(:GFp, 17, 2, 2)
group.point_conversion_form = :uncompressed
gen = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040501", 16))
group.set_generator(gen, 19, 1)
# 3 * (6, 3) = (16, 13)
point_a = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new("040603", 16))
result_a1 = point_a.mul(3)
assert_equal("04100D", result_a1.to_bn.to_s(16))
# 3 * (6, 3) + 3 * (5, 1) = (7, 6)
result_a2 = point_a.mul(3, 3)
assert_equal("040706", result_a2.to_bn.to_s(16))
# 3 * point_a = 3 * (6, 3) = (16, 13)
result_b1 = point_a.mul([3], [])
assert_equal("04100D", result_b1.to_bn.to_s(16))
# 3 * point_a + 2 * point_a = 3 * (6, 3) + 2 * (6, 3) = (7, 11)
result_b1 = point_a.mul([3, 2], [point_a])
assert_equal("04070B", result_b1.to_bn.to_s(16))
# 3 * point_a + 5 * point_a.group.generator = 3 * (6, 3) + 5 * (5, 1) = (13, 10)
result_b1 = point_a.mul([3], [], 5)
assert_equal("040D0A", result_b1.to_bn.to_s(16))
rescue OpenSSL::PKey::EC::Group::Error
# CentOS patches OpenSSL to reject curves defined over Fp where p < 256 bits
raise if $!.message !~ /unsupported field/
end
p256_key = Fixtures.pkey("p256")
p256_g = p256_key.group
assert_equal(p256_key.public_key, p256_g.generator.mul(p256_key.private_key))
# invalid argument
point = p256_key.public_key
assert_raise(TypeError) { point.mul(nil) }
assert_raise(ArgumentError) { point.mul([1], [point]) }
assert_raise(TypeError) { point.mul([1], nil) }
assert_raise(TypeError) { point.mul([nil], []) }
end
# test Group: asn1_flag, point_conversion
private
def assert_same_ec(expected, key)
check_component(expected, key, [:group, :public_key, :private_key])
end
end
end