Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add wrapper method for EVP_PKEY_cmp to compare same type keys #383

Merged
merged 1 commit into from Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
39 changes: 39 additions & 0 deletions ext/openssl/ossl_pkey.c
Expand Up @@ -732,6 +732,44 @@ ossl_pkey_public_to_pem(VALUE self)
return ossl_pkey_export_spki(self, 0);
}

/*
* 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
Expand Down Expand Up @@ -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);
Expand Down
18 changes: 18 additions & 0 deletions test/openssl/test_pkey.rb
Expand Up @@ -151,4 +151,22 @@ def test_x25519
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
cwjenkins marked this conversation as resolved.
Show resolved Hide resolved
end
end