@@ -73,65 +73,88 @@ def import(jwk_data)
7373 new ( rsa_pkey ( pkey_params ) , kid : jwk_attributes ( jwk_data , :kid ) [ :kid ] )
7474 end
7575
76- private
76+ RSA_OPT_PARAMS = %i[ p q dp dq qi ] . freeze
77+ RSA_ASN1_SEQUENCE = ( %i[ n e d ] + RSA_OPT_PARAMS ) . freeze # https://www.rfc-editor.org/rfc/rfc3447#appendix-A.1.2
7778
78- def jwk_attributes ( jwk_data , *attributes )
79- attributes . each_with_object ( { } ) do |attribute , hash |
80- value = jwk_data [ attribute ] || jwk_data [ attribute . to_s ]
81- value = yield ( value ) if block_given?
82- hash [ attribute ] = value
79+ def create_rsa_key_using_der ( rsa_parameters )
80+ validate_rsa_parameters! ( rsa_parameters )
81+
82+ sequence = RSA_ASN1_SEQUENCE . each_with_object ( [ ] ) do |key , arr |
83+ next if rsa_parameters [ key ] . nil?
84+
85+ arr << OpenSSL ::ASN1 ::Integer . new ( rsa_parameters [ key ] )
8386 end
84- end
8587
86- def rsa_pkey ( rsa_parameters )
87- raise JWT ::JWKError , 'Key format is invalid for RSA' unless rsa_parameters [ :n ] && rsa_parameters [ :e ]
88+ if sequence . size > 2 # Append "two-prime" version for private key
89+ sequence . unshift ( OpenSSL ::ASN1 ::Integer . new ( 0 ) )
90+ end
8891
89- create_rsa_key ( rsa_parameters )
92+ OpenSSL :: PKey :: RSA . new ( OpenSSL :: ASN1 :: Sequence ( sequence ) . to_der )
9093 end
9194
92- if ::JWT . openssl_3?
93- ASN1_SEQUENCE = %i[ n e d p q dp dq qi ] . freeze
94- def create_rsa_key ( rsa_parameters )
95- sequence = ASN1_SEQUENCE . each_with_object ( [ ] ) do |key , arr |
96- next if rsa_parameters [ key ] . nil?
95+ def create_rsa_key_using_sets ( rsa_parameters )
96+ validate_rsa_parameters! ( rsa_parameters )
9797
98- arr << OpenSSL ::ASN1 :: Integer . new ( rsa_parameters [ key ] )
99- end
100-
101- if sequence . size > 2 # For a private key
102- sequence . unshift ( OpenSSL :: ASN1 :: Integer . new ( 0 ) )
103- end
98+ OpenSSL ::PKey :: RSA . new . tap do | rsa_key |
99+ rsa_key . set_key ( rsa_parameters [ :n ] , rsa_parameters [ :e ] , rsa_parameters [ :d ] )
100+ rsa_key . set_factors ( rsa_parameters [ :p ] , rsa_parameters [ :q ] ) if rsa_parameters [ :p ] && rsa_parameters [ :q ]
101+ rsa_key . set_crt_params ( rsa_parameters [ :dp ] , rsa_parameters [ :dq ] , rsa_parameters [ :qi ] ) if rsa_parameters [ :dp ] && rsa_parameters [ :dq ] && rsa_parameters [ :qi ]
102+ end
103+ end
104104
105- OpenSSL ::PKey ::RSA . new ( OpenSSL ::ASN1 ::Sequence ( sequence ) . to_der )
105+ def create_rsa_key_using_accessors ( rsa_parameters ) # rubocop:disable Metrics/AbcSize
106+ validate_rsa_parameters! ( rsa_parameters )
107+
108+ OpenSSL ::PKey ::RSA . new . tap do |rsa_key |
109+ rsa_key . n = rsa_parameters [ :n ]
110+ rsa_key . e = rsa_parameters [ :e ]
111+ rsa_key . d = rsa_parameters [ :d ] if rsa_parameters [ :d ]
112+ rsa_key . p = rsa_parameters [ :p ] if rsa_parameters [ :p ]
113+ rsa_key . q = rsa_parameters [ :q ] if rsa_parameters [ :q ]
114+ rsa_key . dmp1 = rsa_parameters [ :dp ] if rsa_parameters [ :dp ]
115+ rsa_key . dmq1 = rsa_parameters [ :dq ] if rsa_parameters [ :dq ]
116+ rsa_key . iqmp = rsa_parameters [ :qi ] if rsa_parameters [ :qi ]
106117 end
118+ end
119+
120+ if ::JWT . openssl_3?
121+ alias create_rsa_key create_rsa_key_using_der
107122 elsif OpenSSL ::PKey ::RSA . new . respond_to? ( :set_key )
108- def create_rsa_key ( rsa_parameters )
109- OpenSSL ::PKey ::RSA . new . tap do |rsa_key |
110- rsa_key . set_key ( rsa_parameters [ :n ] , rsa_parameters [ :e ] , rsa_parameters [ :d ] )
111- rsa_key . set_factors ( rsa_parameters [ :p ] , rsa_parameters [ :q ] ) if rsa_parameters [ :p ] && rsa_parameters [ :q ]
112- rsa_key . set_crt_params ( rsa_parameters [ :dp ] , rsa_parameters [ :dq ] , rsa_parameters [ :qi ] ) if rsa_parameters [ :dp ] && rsa_parameters [ :dq ] && rsa_parameters [ :qi ]
113- end
114- end
123+ alias create_rsa_key create_rsa_key_using_sets
115124 else
116- def create_rsa_key ( rsa_parameters ) # rubocop:disable Metrics/AbcSize
117- OpenSSL ::PKey ::RSA . new . tap do |rsa_key |
118- rsa_key . n = rsa_parameters [ :n ]
119- rsa_key . e = rsa_parameters [ :e ]
120- rsa_key . d = rsa_parameters [ :d ] if rsa_parameters [ :d ]
121- rsa_key . p = rsa_parameters [ :p ] if rsa_parameters [ :p ]
122- rsa_key . q = rsa_parameters [ :q ] if rsa_parameters [ :q ]
123- rsa_key . dmp1 = rsa_parameters [ :dp ] if rsa_parameters [ :dp ]
124- rsa_key . dmq1 = rsa_parameters [ :dq ] if rsa_parameters [ :dq ]
125- rsa_key . iqmp = rsa_parameters [ :qi ] if rsa_parameters [ :qi ]
126- end
127- end
125+ alias create_rsa_key create_rsa_key_using_accessors
128126 end
129127
130128 def decode_open_ssl_bn ( jwk_data )
131129 return nil unless jwk_data
132130
133131 OpenSSL ::BN . new ( ::JWT ::Base64 . url_decode ( jwk_data ) , BINARY )
134132 end
133+
134+ private
135+
136+ def validate_rsa_parameters! ( rsa_parameters )
137+ return unless rsa_parameters [ :d ]
138+
139+ return if RSA_OPT_PARAMS . all? { |k | rsa_parameters . keys . include? ( k ) }
140+ return if RSA_OPT_PARAMS . none? { |k | rsa_parameters . keys . include? ( k ) }
141+
142+ raise JWT ::JWKError , 'When one of p, q, dp, dq or qi is given all the other optimization parameters also needs to be defined'
143+ end
144+
145+ def jwk_attributes ( jwk_data , *attributes )
146+ attributes . each_with_object ( { } ) do |attribute , hash |
147+ value = jwk_data [ attribute ] || jwk_data [ attribute . to_s ]
148+ value = yield ( value ) if block_given?
149+ hash [ attribute ] = value
150+ end
151+ end
152+
153+ def rsa_pkey ( rsa_parameters )
154+ raise JWT ::JWKError , 'Key format is invalid for RSA' unless rsa_parameters [ :n ] && rsa_parameters [ :e ]
155+
156+ create_rsa_key ( rsa_parameters )
157+ end
135158 end
136159 end
137160 end
0 commit comments