@@ -25,7 +25,7 @@ def initialize(key, params = nil, options = {})
25
25
end
26
26
27
27
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 ] ) ) )
29
29
end
30
30
31
31
def private?
@@ -108,31 +108,53 @@ def encode_open_ssl_bn(key_part)
108
108
::JWT ::Base64 . url_encode ( key_part . to_s ( BINARY ) )
109
109
end
110
110
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 |
115
133
next if rsa_parameters [ key ] . nil?
116
134
117
135
arr << OpenSSL ::ASN1 ::Integer . new ( rsa_parameters [ key ] )
118
136
end
119
137
120
- if sequence . size > 2 # For a private key
138
+ if sequence . size > 2 # Append "two-prime" version for private key
121
139
sequence . unshift ( OpenSSL ::ASN1 ::Integer . new ( 0 ) )
122
140
end
123
141
124
142
OpenSSL ::PKey ::RSA . new ( OpenSSL ::ASN1 ::Sequence ( sequence ) . to_der )
125
143
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
+
128
148
OpenSSL ::PKey ::RSA . new . tap do |rsa_key |
129
149
rsa_key . set_key ( rsa_parameters [ :n ] , rsa_parameters [ :e ] , rsa_parameters [ :d ] )
130
150
rsa_key . set_factors ( rsa_parameters [ :p ] , rsa_parameters [ :q ] ) if rsa_parameters [ :p ] && rsa_parameters [ :q ]
131
151
rsa_key . set_crt_params ( rsa_parameters [ :dp ] , rsa_parameters [ :dq ] , rsa_parameters [ :qi ] ) if rsa_parameters [ :dp ] && rsa_parameters [ :dq ] && rsa_parameters [ :qi ]
132
152
end
133
153
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
+
136
158
OpenSSL ::PKey ::RSA . new . tap do |rsa_key |
137
159
rsa_key . n = rsa_parameters [ :n ]
138
160
rsa_key . e = rsa_parameters [ :e ]
@@ -144,17 +166,22 @@ def create_rsa_key(rsa_parameters) # rubocop:disable Metrics/AbcSize
144
166
rsa_key . iqmp = rsa_parameters [ :qi ] if rsa_parameters [ :qi ]
145
167
end
146
168
end
147
- end
148
169
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 ]
151
172
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 ) }
154
175
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
158
185
end
159
186
end
160
187
end
0 commit comments