@@ -25,7 +25,7 @@ def initialize(key, params = nil, options = {})
2525 end
2626
2727 def keypair
28- @keypair ||= create_rsa_key ( jwk_attributes ( *( RSA_KEY_ELEMENTS - [ :kty ] ) ) )
28+ @keypair ||= self . class . create_rsa_key ( jwk_attributes ( *( RSA_KEY_ELEMENTS - [ :kty ] ) ) )
2929 end
3030
3131 def private?
@@ -108,31 +108,53 @@ def encode_open_ssl_bn(key_part)
108108 ::JWT ::Base64 . url_encode ( key_part . to_s ( BINARY ) )
109109 end
110110
111- if ::JWT . openssl_3?
112- ASN1_SEQUENCE = %i[ n e d p q dp dq qi ] . freeze
113- def create_rsa_key ( rsa_parameters )
114- sequence = ASN1_SEQUENCE . each_with_object ( [ ] ) do |key , arr |
111+ def decode_open_ssl_bn ( jwk_data )
112+ self . class . decode_open_ssl_bn ( jwk_data )
113+ end
114+
115+ class << self
116+ def import ( jwk_data )
117+ new ( jwk_data )
118+ end
119+
120+ def decode_open_ssl_bn ( jwk_data )
121+ return nil unless jwk_data
122+
123+ OpenSSL ::BN . new ( ::JWT ::Base64 . url_decode ( jwk_data ) , BINARY )
124+ end
125+
126+ RSA_OPT_PARAMS = %i[ p q dp dq qi ] . freeze
127+ RSA_ASN1_SEQUENCE = ( %i[ n e d ] + RSA_OPT_PARAMS ) . freeze # https://www.rfc-editor.org/rfc/rfc3447#appendix-A.1.2
128+
129+ def create_rsa_key_using_der ( rsa_parameters )
130+ validate_rsa_parameters! ( rsa_parameters )
131+
132+ sequence = RSA_ASN1_SEQUENCE . each_with_object ( [ ] ) do |key , arr |
115133 next if rsa_parameters [ key ] . nil?
116134
117135 arr << OpenSSL ::ASN1 ::Integer . new ( rsa_parameters [ key ] )
118136 end
119137
120- if sequence . size > 2 # For a private key
138+ if sequence . size > 2 # Append "two-prime" version for private key
121139 sequence . unshift ( OpenSSL ::ASN1 ::Integer . new ( 0 ) )
122140 end
123141
124142 OpenSSL ::PKey ::RSA . new ( OpenSSL ::ASN1 ::Sequence ( sequence ) . to_der )
125143 end
126- elsif OpenSSL ::PKey ::RSA . new . respond_to? ( :set_key )
127- def create_rsa_key ( rsa_parameters )
144+
145+ def create_rsa_key_using_sets ( rsa_parameters )
146+ validate_rsa_parameters! ( rsa_parameters )
147+
128148 OpenSSL ::PKey ::RSA . new . tap do |rsa_key |
129149 rsa_key . set_key ( rsa_parameters [ :n ] , rsa_parameters [ :e ] , rsa_parameters [ :d ] )
130150 rsa_key . set_factors ( rsa_parameters [ :p ] , rsa_parameters [ :q ] ) if rsa_parameters [ :p ] && rsa_parameters [ :q ]
131151 rsa_key . set_crt_params ( rsa_parameters [ :dp ] , rsa_parameters [ :dq ] , rsa_parameters [ :qi ] ) if rsa_parameters [ :dp ] && rsa_parameters [ :dq ] && rsa_parameters [ :qi ]
132152 end
133153 end
134- else
135- def create_rsa_key ( rsa_parameters ) # rubocop:disable Metrics/AbcSize
154+
155+ def create_rsa_key_using_accessors ( rsa_parameters ) # rubocop:disable Metrics/AbcSize
156+ validate_rsa_parameters! ( rsa_parameters )
157+
136158 OpenSSL ::PKey ::RSA . new . tap do |rsa_key |
137159 rsa_key . n = rsa_parameters [ :n ]
138160 rsa_key . e = rsa_parameters [ :e ]
@@ -144,17 +166,22 @@ def create_rsa_key(rsa_parameters) # rubocop:disable Metrics/AbcSize
144166 rsa_key . iqmp = rsa_parameters [ :qi ] if rsa_parameters [ :qi ]
145167 end
146168 end
147- end
148169
149- def decode_open_ssl_bn ( jwk_data )
150- return nil unless jwk_data
170+ def validate_rsa_parameters! ( rsa_parameters )
171+ return unless rsa_parameters [ :d ]
151172
152- OpenSSL :: BN . new ( :: JWT :: Base64 . url_decode ( jwk_data ) , BINARY )
153- end
173+ return if RSA_OPT_PARAMS . all? { | k | rsa_parameters . keys . include? ( k ) }
174+ return if RSA_OPT_PARAMS . none? { | k | rsa_parameters . keys . include? ( k ) }
154175
155- class << self
156- def import ( jwk_data )
157- new ( jwk_data )
176+ raise JWT ::JWKError , 'When one of p, q, dp, dq or qi is given all the other optimization parameters also needs to be defined' # https://www.rfc-editor.org/rfc/rfc7518.html#section-6.3.2
177+ end
178+
179+ if ::JWT . openssl_3?
180+ alias create_rsa_key create_rsa_key_using_der
181+ elsif OpenSSL ::PKey ::RSA . new . respond_to? ( :set_key )
182+ alias create_rsa_key create_rsa_key_using_sets
183+ else
184+ alias create_rsa_key create_rsa_key_using_accessors
158185 end
159186 end
160187 end
0 commit comments