Skip to content

Commit

Permalink
Create RSA key by importing the parameters in DER format
Browse files Browse the repository at this point in the history
  • Loading branch information
anakinj committed Jul 27, 2022
1 parent e92cea3 commit 293ef90
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 21 deletions.
52 changes: 34 additions & 18 deletions lib/jwt/jwk/rsa.rb
Original file line number Diff line number Diff line change
Expand Up @@ -86,28 +86,44 @@ def jwk_attributes(jwk_data, *attributes)
def rsa_pkey(rsa_parameters)
raise JWT::JWKError, 'Key format is invalid for RSA' unless rsa_parameters[:n] && rsa_parameters[:e]

populate_key(OpenSSL::PKey::RSA.new, rsa_parameters)
create_rsa_key(rsa_parameters)
end

if OpenSSL::PKey::RSA.new.respond_to?(:set_key)
def populate_key(rsa_key, rsa_parameters)
rsa_key.set_key(rsa_parameters[:n], rsa_parameters[:e], rsa_parameters[:d])
rsa_key.set_factors(rsa_parameters[:p], rsa_parameters[:q]) if rsa_parameters[:p] && rsa_parameters[:q]
rsa_key.set_crt_params(rsa_parameters[:dp], rsa_parameters[:dq], rsa_parameters[:qi]) if rsa_parameters[:dp] && rsa_parameters[:dq] && rsa_parameters[:qi]
rsa_key
if ::JWT.openssl_3?
ASN1_SEQUENCE = %i[n e d p q dp dq qi].freeze
def create_rsa_key(rsa_parameters)
sequence = ASN1_SEQUENCE.each_with_object([]) do |key, arr|
next if rsa_parameters[key].nil?

arr << OpenSSL::ASN1::Integer.new(rsa_parameters[key])
end

if sequence.size > 2 # For a private key
sequence.unshift(OpenSSL::ASN1::Integer.new(0))
end

OpenSSL::PKey::RSA.new(OpenSSL::ASN1::Sequence(sequence).to_der)
end
elsif OpenSSL::PKey::RSA.new.respond_to?(:set_key)
def create_rsa_key(rsa_parameters)
OpenSSL::PKey::RSA.new.tap do |rsa_key|
rsa_key.set_key(rsa_parameters[:n], rsa_parameters[:e], rsa_parameters[:d])
rsa_key.set_factors(rsa_parameters[:p], rsa_parameters[:q]) if rsa_parameters[:p] && rsa_parameters[:q]
rsa_key.set_crt_params(rsa_parameters[:dp], rsa_parameters[:dq], rsa_parameters[:qi]) if rsa_parameters[:dp] && rsa_parameters[:dq] && rsa_parameters[:qi]
end
end
else
def populate_key(rsa_key, rsa_parameters)
rsa_key.n = rsa_parameters[:n]
rsa_key.e = rsa_parameters[:e]
rsa_key.d = rsa_parameters[:d] if rsa_parameters[:d]
rsa_key.p = rsa_parameters[:p] if rsa_parameters[:p]
rsa_key.q = rsa_parameters[:q] if rsa_parameters[:q]
rsa_key.dmp1 = rsa_parameters[:dp] if rsa_parameters[:dp]
rsa_key.dmq1 = rsa_parameters[:dq] if rsa_parameters[:dq]
rsa_key.iqmp = rsa_parameters[:qi] if rsa_parameters[:qi]

rsa_key
def create_rsa_key(rsa_parameters) # rubocop:disable Metrics/AbcSize
OpenSSL::PKey::RSA.new.tap do |rsa_key|
rsa_key.n = rsa_parameters[:n]
rsa_key.e = rsa_parameters[:e]
rsa_key.d = rsa_parameters[:d] if rsa_parameters[:d]
rsa_key.p = rsa_parameters[:p] if rsa_parameters[:p]
rsa_key.q = rsa_parameters[:q] if rsa_parameters[:q]
rsa_key.dmp1 = rsa_parameters[:dp] if rsa_parameters[:dp]
rsa_key.dmq1 = rsa_parameters[:dq] if rsa_parameters[:dq]
rsa_key.iqmp = rsa_parameters[:qi] if rsa_parameters[:qi]
end
end
end

Expand Down
5 changes: 5 additions & 0 deletions lib/jwt/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,9 @@ module VERSION
# Build version string
STRING = [MAJOR, MINOR, TINY, PRE].compact.join('.')
end

def self.openssl_3?
return false if OpenSSL::OPENSSL_VERSION.include?('LibreSSL')
return true if OpenSSL::OPENSSL_VERSION_NUMBER >= 3 * 0x10000000
end
end
4 changes: 2 additions & 2 deletions spec/jwk/decode_with_jwk_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -82,8 +82,8 @@
context 'mixing algorithms using kid header' do
let(:hmac_jwk) { JWT::JWK.new('secret') }
let(:rsa_jwk) { JWT::JWK.new(OpenSSL::PKey::RSA.new(2048)) }
let(:ec_jwk_secp384r1) { JWT::JWK.new(OpenSSL::PKey::EC.new('secp384r1').generate_key) }
let(:ec_jwk_secp521r1) { JWT::JWK.new(OpenSSL::PKey::EC.new('secp521r1').generate_key) }
let(:ec_jwk_secp384r1) { JWT::JWK.new(OpenSSL::PKey::EC.generate('secp384r1')) }
let(:ec_jwk_secp521r1) { JWT::JWK.new(OpenSSL::PKey::EC.generate('secp521r1')) }
let(:jwks) { { keys: [hmac_jwk.export(include_private: true), rsa_jwk.export, ec_jwk_secp384r1.export, ec_jwk_secp521r1.export] } }

context 'when RSA key is pointed to as HMAC secret' do
Expand Down
2 changes: 1 addition & 1 deletion spec/jwk_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

RSpec.describe JWT::JWK do
let(:rsa_key) { OpenSSL::PKey::RSA.new(2048) }
let(:ec_key) { OpenSSL::PKey::EC.new('secp384r1').generate_key }
let(:ec_key) { OpenSSL::PKey::EC.generate('secp384r1') }

describe '.import' do
let(:keypair) { rsa_key.public_key }
Expand Down

0 comments on commit 293ef90

Please sign in to comment.