diff options
author | Colton Jenkins <jenkinscolton7@gmail.com> | 2020-07-05 17:25:54 -0400 |
---|---|---|
committer | Colton Jenkins <coltjenk@cisco.com> | 2020-07-14 10:23:56 -0400 |
commit | 0bf51da6e24bbdb6f5724a87fe047ac2b521415d (patch) | |
tree | decd2450effceaa7e825dff299e07a21cc8221a4 | |
parent | b362c0a704df489452ec48379801eca5db848f78 (diff) | |
download | ruby-openssl-0bf51da6e24bbdb6f5724a87fe047ac2b521415d.tar.gz |
Add compare? method to OpenSSL::PKey that wraps EVP_PKEY_cmp.
Explicitly check for type given some conflicting statements within openssl's
documentation around EVP_PKEY_cmp and EVP_PKEY_ASN1_METHOD(3).
Add documentation with an example for compare?
-rw-r--r-- | ext/openssl/ossl_pkey.c | 39 | ||||
-rw-r--r-- | test/openssl/test_pkey.rb | 18 |
2 files changed, 57 insertions, 0 deletions
diff --git a/ext/openssl/ossl_pkey.c b/ext/openssl/ossl_pkey.c index df8b425a..d5f5a51a 100644 --- a/ext/openssl/ossl_pkey.c +++ b/ext/openssl/ossl_pkey.c @@ -734,6 +734,44 @@ ossl_pkey_public_to_pem(VALUE self) /* * call-seq: + * pkey.compare?(another_pkey) -> true | false + * + * Used primarily to check if an OpenSSL::X509::Certificate#public_key compares to its private key. + * + * == Example + * x509 = OpenSSL::X509::Certificate.new(pem_encoded_certificate) + * rsa_key = OpenSSL::PKey::RSA.new(pem_encoded_private_key) + * + * rsa_key.compare?(x509.public_key) => true | false + */ +static VALUE +ossl_pkey_compare(VALUE self, VALUE other) +{ + int ret; + EVP_PKEY *selfPKey; + EVP_PKEY *otherPKey; + + GetPKey(self, selfPKey); + GetPKey(other, otherPKey); + + /* Explicitly check the key type given EVP_PKEY_ASN1_METHOD(3) + * docs param_cmp could return any negative number. + */ + if (EVP_PKEY_id(selfPKey) != EVP_PKEY_id(otherPKey)) + ossl_raise(rb_eTypeError, "cannot match different PKey types"); + + ret = EVP_PKEY_cmp(selfPKey, otherPKey); + + if (ret == 0) + return Qfalse; + else if (ret == 1) + return Qtrue; + else + ossl_raise(ePKeyError, "EVP_PKEY_cmp"); +} + +/* + * call-seq: * pkey.sign(digest, data) -> String * * To sign the String _data_, _digest_, an instance of OpenSSL::Digest, must @@ -1031,6 +1069,7 @@ Init_ossl_pkey(void) rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1); rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0); rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0); + rb_define_method(cPKey, "compare?", ossl_pkey_compare, 1); rb_define_method(cPKey, "sign", ossl_pkey_sign, 2); rb_define_method(cPKey, "verify", ossl_pkey_verify, 3); diff --git a/test/openssl/test_pkey.rb b/test/openssl/test_pkey.rb index 5307fe5b..0a516f98 100644 --- a/test/openssl/test_pkey.rb +++ b/test/openssl/test_pkey.rb @@ -151,4 +151,22 @@ class OpenSSL::TestPKey < OpenSSL::PKeyTestCase assert_equal bob_pem, bob.public_to_pem assert_equal [shared_secret].pack("H*"), alice.derive(bob) end + + def test_compare? + key1 = Fixtures.pkey("rsa1024") + key2 = Fixtures.pkey("rsa1024") + key3 = Fixtures.pkey("rsa2048") + key4 = Fixtures.pkey("dh-1") + + assert_equal(true, key1.compare?(key2)) + assert_equal(true, key1.public_key.compare?(key2)) + assert_equal(true, key2.compare?(key1)) + assert_equal(true, key2.public_key.compare?(key1)) + + assert_equal(false, key1.compare?(key3)) + + assert_raise(TypeError) do + key1.compare?(key4) + end + end end |