Class: XMLSecurity::SignedDocument
- Inherits:
-
REXML::Document
- Object
- REXML::Document
- XMLSecurity::SignedDocument
- Defined in:
- lib/xml_security.rb
Constant Summary collapse
- C14N =
"http://www.w3.org/2001/10/xml-exc-c14n#"
- DSIG =
"http://www.w3.org/2000/09/xmldsig#"
Instance Attribute Summary collapse
-
#noko_sig_element ⇒ Object
Returns the value of attribute noko_sig_element.
-
#sig_element ⇒ Object
Returns the value of attribute sig_element.
-
#signed_element_id ⇒ Object
Returns the value of attribute signed_element_id.
Instance Method Summary collapse
-
#initialize(response) ⇒ SignedDocument
constructor
A new instance of SignedDocument.
- #validate(idp_cert_fingerprint, soft = true) ⇒ Object
- #validate_doc(base64_cert, soft = true) ⇒ Object
Constructor Details
permalink #initialize(response) ⇒ SignedDocument
Returns a new instance of SignedDocument.
42 43 44 45 |
# File 'lib/xml_security.rb', line 42 def initialize(response) super(response) extract_signed_element_id end |
Instance Attribute Details
permalink #noko_sig_element ⇒ Object
Returns the value of attribute noko_sig_element.
40 41 42 |
# File 'lib/xml_security.rb', line 40 def noko_sig_element @noko_sig_element end |
permalink #sig_element ⇒ Object
Returns the value of attribute sig_element.
40 41 42 |
# File 'lib/xml_security.rb', line 40 def sig_element @sig_element end |
permalink #signed_element_id ⇒ Object
Returns the value of attribute signed_element_id.
40 41 42 |
# File 'lib/xml_security.rb', line 40 def signed_element_id @signed_element_id end |
Instance Method Details
permalink #validate(idp_cert_fingerprint, soft = true) ⇒ Object
[View source]
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 |
# File 'lib/xml_security.rb', line 47 def validate(idp_cert_fingerprint, soft = true) # get cert from response cert_element = REXML::XPath.first(self, "//ds:X509Certificate", { "ds"=>DSIG }) base64_cert = cert_element.text cert_text = Base64.decode64(base64_cert) cert = OpenSSL::X509::Certificate.new(cert_text) # check cert matches registered idp cert fingerprint = Digest::SHA1.hexdigest(cert.to_der) if fingerprint != idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/,"").downcase return soft ? false : (raise FederazioneTrentina::Saml::ValidationError.new("Fingerprint mismatch")) end validate_doc(base64_cert, soft) end |
permalink #validate_doc(base64_cert, soft = true) ⇒ Object
[View source]
64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 |
# File 'lib/xml_security.rb', line 64 def validate_doc(base64_cert, soft = true) # validate references # check for inclusive namespaces inclusive_namespaces = extract_inclusive_namespaces document = Nokogiri.parse(self.to_s) # store and remove signature node self.sig_element ||= begin element = REXML::XPath.first(self, "//ds:Signature", {"ds"=>DSIG}) element.remove end # verify signature signed_info_element = REXML::XPath.first(sig_element, "//ds:SignedInfo", {"ds"=>DSIG}) self.noko_sig_element ||= document.at_xpath('//ds:Signature', 'ds' => DSIG) noko_signed_info_element = noko_sig_element.at_xpath('./ds:SignedInfo', 'ds' => DSIG) canon_algorithm = canon_algorithm REXML::XPath.first(sig_element, '//ds:CanonicalizationMethod') canon_string = noko_signed_info_element.canonicalize(canon_algorithm) noko_sig_element.remove # check digests REXML::XPath.each(sig_element, "//ds:Reference", {"ds"=>DSIG}) do |ref| uri = ref.attributes.get_attribute("URI").value hashed_element = document.at_xpath("//*[@ID='#{uri[1..-1]}']") canon_algorithm = canon_algorithm REXML::XPath.first(ref, '//ds:CanonicalizationMethod') canon_hashed_element = hashed_element.canonicalize(canon_algorithm, inclusive_namespaces).gsub('&','&') digest_algorithm = algorithm(REXML::XPath.first(ref, "//ds:DigestMethod")) hash = digest_algorithm.digest(canon_hashed_element) digest_value = Base64.decode64(REXML::XPath.first(ref, "//ds:DigestValue", {"ds"=>DSIG}).text) unless digests_match?(hash, digest_value) return soft ? false : (raise FederazioneTrentina::Saml::ValidationError.new("Digest mismatch")) end end base64_signature = REXML::XPath.first(sig_element, "//ds:SignatureValue", {"ds"=>DSIG}).text signature = Base64.decode64(base64_signature) # get certificate object cert_text = Base64.decode64(base64_cert) cert = OpenSSL::X509::Certificate.new(cert_text) # signature method signature_algorithm = algorithm(REXML::XPath.first(signed_info_element, "//ds:SignatureMethod", {"ds"=>DSIG})) unless cert.public_key.verify(signature_algorithm.new, signature, canon_string) return soft ? false : (raise FederazioneTrentina::Saml::ValidationError.new("Key validation error")) end return true end |