@@ -227,42 +227,48 @@ def validate_document(idp_cert_fingerprint, soft = true, options = {})
227227 end
228228
229229 def validate_signature ( base64_cert , soft = true )
230- # validate references
231-
232- # check for inclusive namespaces
233- inclusive_namespaces = extract_inclusive_namespaces
234230
235231 document = Nokogiri . parse ( self . to_s ) do |options |
236232 options = XMLSecurity ::BaseDocument ::NOKOGIRI_OPTIONS
237233 end
238234
239- # create a working copy so we don't modify the original
235+ # create a rexml document
240236 @working_copy ||= REXML ::Document . new ( self . to_s ) . root
241237
242- # store and remove signature node
243- @sig_element ||= begin
244- element = REXML ::XPath . first (
238+ # get signature node
239+ sig_element = REXML ::XPath . first (
245240 @working_copy ,
246241 "//ds:Signature" ,
247242 { "ds" => DSIG }
248- )
249- element . remove
250- end
243+ )
251244
252- # verify signature
253- signed_info_element = REXML ::XPath . first (
254- @ sig_element,
255- "// ds:SignedInfo" ,
245+ # signature method
246+ sig_alg_value = REXML ::XPath . first (
247+ sig_element ,
248+ "./ ds:SignedInfo/ds:SignatureMethod " ,
256249 { "ds" => DSIG }
257250 )
258- noko_sig_element = document . at_xpath ( '//ds:Signature' , 'ds' => DSIG )
259- noko_signed_info_element = noko_sig_element . at_xpath ( './ds:SignedInfo' , 'ds' => DSIG )
251+ signature_algorithm = algorithm ( sig_alg_value )
252+
253+ # get signature
254+ base64_signature = REXML ::XPath . first (
255+ sig_element ,
256+ "./ds:SignatureValue" ,
257+ { "ds" => DSIG }
258+ ) . text
259+ signature = Base64 . decode64 ( base64_signature )
260+
261+ # canonicalization method
260262 canon_algorithm = canon_algorithm REXML ::XPath . first (
261- @ sig_element,
262- '/ /ds:CanonicalizationMethod' ,
263+ sig_element ,
264+ './ds:SignedInfo /ds:CanonicalizationMethod' ,
263265 'ds' => DSIG
264266 )
265267
268+ noko_sig_element = document . at_xpath ( '//ds:Signature' , 'ds' => DSIG )
269+ noko_signed_info_element = noko_sig_element . at_xpath ( './ds:SignedInfo' , 'ds' => DSIG )
270+
271+ # Handle when no URI
266272 noko_signed_info_reference_element_uri_attr = noko_signed_info_element . at_xpath ( './ds:Reference' , 'ds' => DSIG ) . attributes [ "URI" ]
267273 if ( noko_signed_info_reference_element_uri_attr . value . empty? )
268274 noko_signed_info_reference_element_uri_attr . value = "##{ document . root . attribute ( 'ID' ) } "
@@ -271,8 +277,11 @@ def validate_signature(base64_cert, soft = true)
271277 canon_string = noko_signed_info_element . canonicalize ( canon_algorithm )
272278 noko_sig_element . remove
273279
280+ # get inclusive namespaces
281+ inclusive_namespaces = extract_inclusive_namespaces
282+
274283 # check digests
275- REXML ::XPath . each ( @ sig_element, "//ds:Reference" , { "ds" => DSIG } ) do |ref |
284+ REXML ::XPath . each ( sig_element , "//ds:Reference" , { "ds" => DSIG } ) do |ref |
276285 uri = ref . attributes . get_attribute ( "URI" ) . value
277286
278287 hashed_element = uri . empty? ? document : document . at_xpath ( "//*[@ID=$uri]" , nil , { 'uri' => uri [ 1 ..-1 ] } )
@@ -303,26 +312,11 @@ def validate_signature(base64_cert, soft = true)
303312 end
304313 end
305314
306- base64_signature = REXML ::XPath . first (
307- @sig_element ,
308- "//ds:SignatureValue" ,
309- { "ds" => DSIG }
310- ) . text
311-
312- signature = Base64 . decode64 ( base64_signature )
313-
314315 # get certificate object
315316 cert_text = Base64 . decode64 ( base64_cert )
316317 cert = OpenSSL ::X509 ::Certificate . new ( cert_text )
317318
318- # signature method
319- sig_alg_value = REXML ::XPath . first (
320- signed_info_element ,
321- "//ds:SignatureMethod" ,
322- { "ds" => DSIG }
323- )
324- signature_algorithm = algorithm ( sig_alg_value )
325-
319+ # verify signature
326320 unless cert . public_key . verify ( signature_algorithm . new , signature , canon_string )
327321 @errors << "Key validation error"
328322 return soft ? false : ( raise OneLogin ::RubySaml ::ValidationError . new ( "Key validation error" ) )
@@ -347,7 +341,7 @@ def extract_signed_element_id
347341 return nil if reference_element . nil?
348342
349343 sei = reference_element . attribute ( "URI" ) . value [ 1 ..-1 ]
350- self . signed_element_id = sei . nil? ? self . root . attribute ( "ID" ) : sei
344+ sei . nil? ? self . root . attribute ( "ID" ) : sei
351345 end
352346
353347 def extract_inclusive_namespaces
0 commit comments