nov/json-jwt

OpenSSL::PKey interface has changed in Ruby 2.4

cmoylan opened this issue · 10 comments

The attributes e, n, d, etc are no longer directly accessible. Those attributes are now set through setter functions:
https://ruby-doc.org/stdlib-2.4.1/libdoc/openssl/rdoc/OpenSSL/PKey/RSA.html#method-i-set_key
https://ruby-doc.org/stdlib-2.4.1/libdoc/openssl/rdoc/OpenSSL/PKey/RSA.html#method-i-set_factors
https://ruby-doc.org/stdlib-2.4.1/libdoc/openssl/rdoc/OpenSSL/PKey/RSA.html#method-i-set_crt_params

I had a pull request #44 to update JWK#to_rsa_key but it breaks for versions of Ruby < 2.4. The simplest solution is to check the OpenSSL version before attempting to set the key attributes. If you don't have any objections or a better solution, I'm happy to submit a PR with the change.

nov commented

Even under ruby 2.4.1, I can execute this code.

e = 'AQAB'
n = 'xT8fom6CyF90d4FaipIZuYD6jC7Eie6JpPAAgKy7qWjzzG-Aof9_ULPFabxMGP_M4Y83iV8dI8swEI4dfkY8zzgLfvZIcwOOy6KQvdWQcas8rrLMTkeT2pfY-abG1awvuz3aEpaibia1-UF80IvYHPpr6_4b5YAPQ3LF4WZHd1gEvQ1WC-rBiWbmVIC-MSIMeQHGISM0SVxa-p3LtsQGbgb0VsaTSbWHHCwKAfLdYLmrOh0bGEtC0aZoAmoBMefEw7FVTQmyBHiJtnuZ7oPGjSMGlP1DSfa6GkUYw-qA7OBoJaYAzZiboIiUyAkPQE5QiBipW-DIoiBzUn_n12fIhw'

key = OpenSSL::PKey::RSA.new
key.e = OpenSSL::BN.new(UrlSafeBase64.decode64(e), 2)
key.n = OpenSSL::BN.new(UrlSafeBase64.decode64(n), 2)
puts key.to_pem

FYI: my ruby, openssl, openssl gem versions are here.

nov@tov json-jwt (master)$ pry
[1] pry(main)> require 'openssl'
=> true
[2] pry(main)> RUBY_VERSION
=> "2.4.1"
[3] pry(main)> OpenSSL::OPENSSL_VERSION
=> "OpenSSL 1.0.2k  26 Jan 2017"
[4] pry(main)> OpenSSL::VERSION
=> "2.0.3"

That's odd. If I run the specs for the gem on 2.4.1 I get a bunch of failures with:

      Failure/Error: key.e = e

      NoMethodError:
        undefined method `e=' for #<OpenSSL::PKey::RSA:0x007fba39cb1858>
        Did you mean?  e

For the time being, I'll stay on 2.3 which doesn't cause any issues. I wonder why I have problems on 2.4 and you don't. I was on MRI 2.4.1, installed through RVM.

nov commented

Checking Ruby version is't sufficient.
You need to check your OpenSSL::OPENSSL_VERSION (it also can be confirmed via openssl version in your terminal), and OpenSSL::VERSION too.

Since my local MacBook and travis server passes the specs, I guess your machine have buggy version of them.
https://travis-ci.org/nov/json-jwt/jobs/217231907

ps.
If you are familiar with C, you can confirm the methods are defined here.
https://github.com/ruby/openssl/blob/master/ext/openssl/ossl_pkey_rsa.c#L735

Ok, thank you.

I'm not sure why this was closed, but when running the same setup as @nov, I'm getting a large number of deprecation warnings on these methods.

/usr/local/var/rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/json-jwt-1.7.1/lib/json/jwk.rb:105: warning: #e= is deprecated; use #set_key
/usr/local/var/rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/json-jwt-1.7.1/lib/json/jwk.rb:106: warning: #n= is deprecated; use #set_key
/usr/local/var/rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/json-jwt-1.7.1/lib/json/jwk.rb:107: warning: #d= is deprecated; use #set_key
/usr/local/var/rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/json-jwt-1.7.1/lib/json/jwk.rb:108: warning: #p= is deprecated; use #set_factors
/usr/local/var/rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/json-jwt-1.7.1/lib/json/jwk.rb:109: warning: #q= is deprecated; use #set_factors
/usr/local/var/rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/json-jwt-1.7.1/lib/json/jwk.rb:110: warning: #dmp1= is deprecated; use #set_crt_params
/usr/local/var/rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/json-jwt-1.7.1/lib/json/jwk.rb:111: warning: #dmq1= is deprecated; use #set_crt_params
/usr/local/var/rbenv/versions/2.4.1/lib/ruby/gems/2.4.0/gems/json-jwt-1.7.1/lib/json/jwk.rb:112: warning: #iqmp= is deprecated; use #set_crt_params

Everything still works, but clearly these methods are going to be deprecated. The initial suggestion of switching on the version of OpenSSL might still be a good one?

nov commented

which version of openssl gem and openssl otself are you using?

As you mentioned in your post, here's the output in my local:

[1] pry(main)> require 'openssl'
=> true
[2] pry(main)> RUBY_VERSION
=> "2.4.1"
[3] pry(main)> OpenSSL::OPENSSL_VERSION
=> "OpenSSL 1.0.2k  26 Jan 2017"
[4] pry(main)> OpenSSL::VERSION
=> "2.0.3"

I get the same output when running those lines in irb, as well as when running those lines in rails console.

I don't see any of the warnings (or exceptions) when running the example that you posted here: #45 (comment)

So I can't really explain it yet. I'm seeing the warnings when running the tests for a fork of https://github.com/nsarno/knock where I've integrated json-jwt for supporting JWKs. You can clone the repo and run the tests with rake test on the support_jwks_keys branch:

https://github.com/bitmaker-internal/knock/tree/support_jwks_keys

Let me know if you need me to dig further!

nov commented

Beauty! Nice sleuthing!