aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKazuki Yamaguchi <k@rhe.jp>2016-05-13 15:36:43 +0900
committerKazuki Yamaguchi <k@rhe.jp>2016-05-13 15:36:43 +0900
commit0b8db854a4c595826eeec11aa03ab20f242f651e (patch)
tree7ac8bafede901ff77c42f4f1b5b7d03351264e3a
parented84536dd88340ea4a38f8e5f7e07b23bd68c00f (diff)
downloadruby-topic/openssl-pkey-ec.tar.gz
ext/openssl: implement OpenSSL::PKey::{DSA,RSA,EC}#public_pkeytopic/openssl-pkey-ec
Add OpenSSL::PKey::{DSA,RSA,EC}#public_pkey. They return a new instance of itself, which contains only parameters and public information. The old methods, {DSA,RSA}#public_key, are now deprecated. There are 3 types of PKey#public_key: 1) EC#public_key, which returns the actual public key (EC::Point). 2) RSA/DSA#public_key, which returns a new instance of PKey with no private information. 3) DH#public_key, which returns a new instance of DH which contains only DH params. This doesn't even contain 'private key'. This is very confusing. The new methods are intend to replace the 2).
-rw-r--r--ext/openssl/ossl_pkey_dsa.c18
-rw-r--r--ext/openssl/ossl_pkey_ec.c25
-rw-r--r--ext/openssl/ossl_pkey_rsa.c11
-rw-r--r--test/openssl/test_pkey_dh.rb7
-rw-r--r--test/openssl/test_pkey_dsa.rb5
-rw-r--r--test/openssl/test_pkey_ec.rb10
-rw-r--r--test/openssl/test_pkey_rsa.rb7
-rw-r--r--test/openssl/test_x509cert.rb24
-rw-r--r--test/openssl/utils.rb2
9 files changed, 97 insertions, 12 deletions
diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c
index 04900cc..592b03a 100644
--- a/ext/openssl/ossl_pkey_dsa.c
+++ b/ext/openssl/ossl_pkey_dsa.c
@@ -261,7 +261,8 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self)
* dsa.public? -> true | false
*
* Indicates whether this DSA instance has a public key associated with it or
- * not. The public key may be retrieved with DSA#public_key.
+ * not. An DSA instance that contains only public key may be retrieved with
+ * DSA#public_pkey.
*/
static VALUE
ossl_dsa_is_public(VALUE self)
@@ -278,7 +279,7 @@ ossl_dsa_is_public(VALUE self)
* dsa.private? -> true | false
*
* Indicates whether this DSA instance has a private key associated with it or
- * not. The private key may be retrieved with DSA#private_key.
+ * not.
*/
static VALUE
ossl_dsa_is_private(VALUE self)
@@ -436,7 +437,7 @@ ossl_dsa_to_text(VALUE self)
/*
* call-seq:
- * dsa.public_key -> aDSA
+ * dsa.public_pkey -> aDSA
*
* Returns a new DSA instance that carries just the public key information.
* If the current instance has also private key information, this will no
@@ -446,13 +447,15 @@ ossl_dsa_to_text(VALUE self)
*
* === Example
* dsa = OpenSSL::PKey::DSA.new(2048) # has public and private information
- * pub_key = dsa.public_key # has only the public part available
+ * pub_key = dsa.public_pkey # has only the public part available
* pub_key_der = pub_key.to_der # it's safe to publish this
*
- *
+ * === Note
+ * This method was renamed from OpenSSL::PKey::DSA#public_key. It remains as
+ * an alias.
*/
static VALUE
-ossl_dsa_to_public_key(VALUE self)
+ossl_dsa_to_public_pkey(VALUE self)
{
EVP_PKEY *pkey;
DSA *dsa;
@@ -603,7 +606,8 @@ Init_ossl_dsa(void)
rb_define_alias(cDSA, "to_pem", "export");
rb_define_alias(cDSA, "to_s", "export");
rb_define_method(cDSA, "to_der", ossl_dsa_to_der, 0);
- rb_define_method(cDSA, "public_key", ossl_dsa_to_public_key, 0);
+ rb_define_method(cDSA, "public_pkey", ossl_dsa_to_public_pkey, 0);
+ rb_define_alias(cDSA, "public_key", "public_pkey");
rb_define_method(cDSA, "syssign", ossl_dsa_sign, 1);
rb_define_method(cDSA, "sysverify", ossl_dsa_verify, 2);
diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c
index bbdd8a7..80c241a 100644
--- a/ext/openssl/ossl_pkey_ec.c
+++ b/ext/openssl/ossl_pkey_ec.c
@@ -632,6 +632,30 @@ static VALUE ossl_ec_key_check_key(VALUE self)
/*
* call-seq:
+ * key.public_pkey => OpenSSL::PKey::EC
+ *
+ * Returns a new EC instance that has only public information.
+ */
+static VALUE ossl_ec_key_public_pkey(VALUE self)
+{
+ EC_KEY *ec, *ec_new;
+
+ Require_EC_KEY(self, ec);
+
+ if (!EC_KEY_get0_public_key(ec))
+ ossl_raise(eECError, "public key is not set");
+
+ ec_new = EC_KEY_dup(ec);
+ if (!ec_new)
+ ossl_raise(eECError, "EC_KEY_dup");
+
+ EC_KEY_set_private_key(ec_new, NULL);
+
+ return ec_instance(cEC, ec_new);
+}
+
+/*
+ * call-seq:
* key.dh_compute_key(pubkey) => String
*
* See the OpenSSL documentation for ECDH_compute_key()
@@ -1634,6 +1658,7 @@ void Init_ossl_ec(void)
*/
rb_define_method(cEC, "generate_key", ossl_ec_key_generate_key, 0);
rb_define_method(cEC, "check_key", ossl_ec_key_check_key, 0);
+ rb_define_method(cEC, "public_pkey", ossl_ec_key_public_pkey, 0);
rb_define_method(cEC, "dh_compute_key", ossl_ec_key_dh_compute_key, 1);
rb_define_method(cEC, "dsa_sign_asn1", ossl_ec_key_dsa_sign_asn1, 1);
diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c
index 20b993a..bb51453 100644
--- a/ext/openssl/ossl_pkey_rsa.c
+++ b/ext/openssl/ossl_pkey_rsa.c
@@ -562,12 +562,16 @@ ossl_rsa_to_text(VALUE self)
/*
* call-seq:
- * rsa.public_key -> RSA
+ * rsa.public_pkey -> RSA
*
* Makes new RSA instance containing the public key from the private key.
+ *
+ * === Note
+ * This method was renamed from OpenSSL::PKey::RSA#public_key. It remains as
+ * an alias.
*/
static VALUE
-ossl_rsa_to_public_key(VALUE self)
+ossl_rsa_to_public_pkey(VALUE self)
{
EVP_PKEY *pkey;
RSA *rsa;
@@ -664,7 +668,8 @@ Init_ossl_rsa(void)
rb_define_alias(cRSA, "to_pem", "export");
rb_define_alias(cRSA, "to_s", "export");
rb_define_method(cRSA, "to_der", ossl_rsa_to_der, 0);
- rb_define_method(cRSA, "public_key", ossl_rsa_to_public_key, 0);
+ rb_define_method(cRSA, "public_pkey", ossl_rsa_to_public_pkey, 0);
+ rb_define_alias(cRSA, "public_key", "public_pkey");
rb_define_method(cRSA, "public_encrypt", ossl_rsa_public_encrypt, -1);
rb_define_method(cRSA, "public_decrypt", ossl_rsa_public_decrypt, -1);
rb_define_method(cRSA, "private_encrypt", ossl_rsa_private_encrypt, -1);
diff --git a/test/openssl/test_pkey_dh.rb b/test/openssl/test_pkey_dh.rb
index a0eca53..bca40ee 100644
--- a/test/openssl/test_pkey_dh.rb
+++ b/test/openssl/test_pkey_dh.rb
@@ -68,6 +68,13 @@ YoaOffgTf5qxiwkjnlVZQc3whgnEt9FpVMvQ9eknyeGB5KHfayAc3+hUAvI3/Cr3
assert_equal(dh.to_pem, public_key.to_pem)
end
+ def test_public_pkey
+ dh = OpenSSL::TestUtils::TEST_KEY_DH1024
+ dh_test = dh.public_pkey
+ assert(!dh_test.private?)
+ assert(dh_test.public?)
+ end
+
def test_generate_key
dh = OpenSSL::TestUtils::TEST_KEY_DH1024.public_key # creates a copy
assert_no_key(dh)
diff --git a/test/openssl/test_pkey_dsa.rb b/test/openssl/test_pkey_dsa.rb
index eb3e4f1..3537738 100644
--- a/test/openssl/test_pkey_dsa.rb
+++ b/test/openssl/test_pkey_dsa.rb
@@ -228,6 +228,11 @@ YNMbNw==
assert(pem)
end
+ def test_public_pkey
+ key = OpenSSL::TestUtils::TEST_KEY_DSA256
+ assert_equal(key.public_key.to_der, key.public_pkey.to_der)
+ end
+
private
def check_sign_verify(digest)
diff --git a/test/openssl/test_pkey_ec.rb b/test/openssl/test_pkey_ec.rb
index fe128fd..e5c4056 100644
--- a/test/openssl/test_pkey_ec.rb
+++ b/test/openssl/test_pkey_ec.rb
@@ -189,6 +189,16 @@ class OpenSSL::TestEC < Test::Unit::TestCase
assert(pem)
end
+ def test_public_pkey
+ ec = OpenSSL::TestUtils::TEST_KEY_EC_P256V1
+ ec_pub = OpenSSL::PKey::EC.new(ec.group)
+ ec_pub.public_key = ec.public_key
+ test_obj = ec.public_pkey
+ assert(!test_obj.private?)
+ assert(test_obj.public?)
+ assert_equal(ec_pub.to_der, test_obj.to_der)
+ end
+
def test_ec_point_mul
ec = OpenSSL::TestUtils::TEST_KEY_EC_P256V1
p1 = ec.public_key
diff --git a/test/openssl/test_pkey_rsa.rb b/test/openssl/test_pkey_rsa.rb
index 165b1ec..b031fdd 100644
--- a/test/openssl/test_pkey_rsa.rb
+++ b/test/openssl/test_pkey_rsa.rb
@@ -284,6 +284,13 @@ AwEAAQ==
assert(pem)
end
+ def test_public_pkey
+ key = OpenSSL::TestUtils::TEST_KEY_RSA1024
+ key_test = key.public_pkey
+ assert(!key_test.private?)
+ assert(key_test.public?)
+ end
+
private
def check_PUBKEY(asn1, key)
diff --git a/test/openssl/test_x509cert.rb b/test/openssl/test_x509cert.rb
index 72cb9e6..642a652 100644
--- a/test/openssl/test_x509cert.rb
+++ b/test/openssl/test_x509cert.rb
@@ -9,6 +9,7 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase
@rsa2048 = OpenSSL::TestUtils::TEST_KEY_RSA2048
@dsa256 = OpenSSL::TestUtils::TEST_KEY_DSA256
@dsa512 = OpenSSL::TestUtils::TEST_KEY_DSA512
+ @p256 = OpenSSL::TestUtils::TEST_KEY_EC_P256V1
@ca = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=CA")
@ee1 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE1")
@ee2 = OpenSSL::X509::Name.parse("/DC=org/DC=ruby-lang/CN=EE2")
@@ -42,7 +43,9 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase
dsa_digest = OpenSSL::TestUtils::DSA_SIGNATURE_DIGEST.new
[
- [@rsa1024, sha1], [@rsa2048, sha1], [@dsa256, dsa_digest], [@dsa512, dsa_digest]
+ [@rsa1024, sha1], [@rsa2048, sha1],
+ [@dsa256, dsa_digest], [@dsa512, dsa_digest],
+ [@p256, sha1],
].each{|pk, digest|
cert = issue_cert(@ca, pk, 1, Time.now, Time.now+3600, exts,
nil, nil, digest)
@@ -133,6 +136,7 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase
assert_equal(true, cert.verify(@rsa2048))
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) })
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) })
+ assert_equal(false, certificate_error_returns_false { cert.verify(@p256) })
cert.serial = 2
assert_equal(false, cert.verify(@rsa2048))
end
@@ -145,6 +149,7 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) })
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) })
+ assert_equal(false, certificate_error_returns_false { cert.verify(@p256) })
cert.subject = @ee1
assert_equal(false, cert.verify(@rsa2048))
rescue OpenSSL::X509::CertificateError # RHEL7 disables MD5
@@ -157,6 +162,7 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase
assert_equal(false, certificate_error_returns_false { cert.verify(@rsa2048) })
assert_equal(false, cert.verify(@dsa256))
assert_equal(true, cert.verify(@dsa512))
+ assert_equal(false, certificate_error_returns_false { cert.verify(@p256) })
cert.not_after = Time.now
assert_equal(false, cert.verify(@dsa512))
end
@@ -168,6 +174,7 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase
assert_equal(true, cert.verify(@rsa2048))
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) })
assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) })
+ assert_equal(false, certificate_error_returns_false { cert.verify(@p256) })
cert.subject = @ee1
assert_equal(false, cert.verify(@rsa2048))
rescue OpenSSL::X509::CertificateError
@@ -180,6 +187,18 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase
}
end
+ def test_sign_and_verify_ecdsa_sha1
+ cert = issue_cert(@ca, @p256, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ assert_equal(false, certificate_error_returns_false { cert.verify(@rsa1024) })
+ assert_equal(false, certificate_error_returns_false { cert.verify(@rsa2048) })
+ assert_equal(false, certificate_error_returns_false { cert.verify(@dsa256) })
+ assert_equal(false, certificate_error_returns_false { cert.verify(@dsa512) })
+ assert_equal(true, cert.verify(@p256))
+ cert.serial = 123
+ assert_equal(false, cert.verify(@p256))
+ end
+
def test_dsig_algorithm_mismatch
assert_raise(OpenSSL::X509::CertificateError) do
issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
@@ -213,6 +232,9 @@ class OpenSSL::TestX509Certificate < Test::Unit::TestCase
cert = issue_cert(@ca, @rsa2048, 1, Time.now, Time.now+3600, [],
nil, nil, OpenSSL::Digest::SHA1.new)
assert_equal(true, cert.check_private_key(@rsa2048))
+ cert = issue_cert(@ca, @p256, 1, Time.now, Time.now+3600, [],
+ nil, nil, OpenSSL::Digest::SHA1.new)
+ assert_equal(true, cert.check_private_key(@p256))
end
private
diff --git a/test/openssl/utils.rb b/test/openssl/utils.rb
index 6909854..c2a0864 100644
--- a/test/openssl/utils.rb
+++ b/test/openssl/utils.rb
@@ -122,7 +122,7 @@ AQjjxMXhwULlmuR/K+WwlaZPiLIBYalLAZQ7ZbOPeVkJ8ePao0eLAgEC
cert.serial = serial
cert.subject = dn
cert.issuer = issuer.subject
- cert.public_key = key.public_key
+ cert.public_key = key.public_pkey
cert.not_before = not_before
cert.not_after = not_after
ef = OpenSSL::X509::ExtensionFactory.new