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

Ruby 2.7 breaks OpenSSL::PKey::EC public_key to_pem #437

Closed
collimarco opened this issue Apr 15, 2021 · 2 comments
Closed

Ruby 2.7 breaks OpenSSL::PKey::EC public_key to_pem #437

collimarco opened this issue Apr 15, 2021 · 2 comments

Comments

@collimarco
Copy link

collimarco commented Apr 15, 2021

In Ruby 2.6.6 (or any previous version) you can get the public key in PEM format:

curve = OpenSSL::PKey::EC.new('prime256v1')
curve.generate_key

public_key = OpenSSL::PKey::EC.new curve
public_key.private_key = nil
public_key.to_pem

When you upgrade to Ruby 2.6.7 or 2.7.0 (or any later version) the above code doesn't work anymore and changes behavior unexpectedly: it returns the private key in PEM format instead of the public key.

This breaks existing code and can potentially represent a security issue.

However the main problem is that there isn't any way to get the public key in PEM format in the new Ruby versions...

Do you have any idea how to get it? (note that curve.public_key.to_pem doesn't work either)

@rhenium
Copy link
Member

rhenium commented Apr 16, 2021

ruby-openssl 2.2 added OpenSSL::PKey::PKey#public_to_pem and #public_to_der specifically for exporting in X.509 SubjectPublicKey format regardless of the key's state - the format chosen by #to_pem when private key components are not available.

ruby-openssl 2.2 is part of Ruby 3.0 stdlib, but you can install it from RubyGems on any Ruby >= 2.3.

However, there were no relevant changes in OpenSSL::PKey::EC between Ruby 2.6 and Ruby 2.7, which are both based on ruby-openssl 2.1, that would affect #to_pem's behavior.

@rhenium
Copy link
Member

rhenium commented Apr 16, 2021

OpenSSL 1.1.1h made ec.private_key = nil no-op, by openssl/openssl#11127.

It looks like a side-effect, but I can't tell if that was ever intended that EC_KEY_set_private_key() could delete private key from the structure. The man page has no mention and we didn't have test code for this.

The change was in OpenSSL itself, so ruby-openssl has no power over it. My recommendation is to use #public_to_pem.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

No branches or pull requests

2 participants