class Spid::XMLSecurityNew::Document

Constants

ENVELOPED_SIG
INC_PREFIX_LIST
RSA_SHA1
RSA_SHA256
RSA_SHA384
RSA_SHA512
SHA1
SHA256
SHA384
SHA512

Attributes

uuid[RW]

Public Instance Methods

sign_document(private_key, certificate, signature_method = RSA_SHA256, digest_method = SHA256) click to toggle source

<Signature> <SignedInfo> <CanonicalizationMethod /> <SignatureMethod /> <Reference> <Transforms> <DigestMethod> <DigestValue> </Reference> <Reference /> etc. </SignedInfo> <SignatureValue /> <KeyInfo /> <Object /> </Signature>

# File lib/spid/xml_security_new.rb, line 118
def sign_document(private_key, certificate, signature_method = RSA_SHA256, digest_method = SHA256)
  noko = Nokogiri::XML(self.to_s) do |config|
    config.options = Spid::XMLSecurityNew::BaseDocument::NOKOGIRI_OPTIONS
  end

  signature_element = REXML::Element.new("ds:Signature").add_namespace('ds', DSIG)
  signed_info_element = signature_element.add_element("ds:SignedInfo")
  signed_info_element.add_element("ds:CanonicalizationMethod", {"Algorithm" => C14N})
  signed_info_element.add_element("ds:SignatureMethod", {"Algorithm"=>signature_method})

  # Add Reference
  reference_element = signed_info_element.add_element("ds:Reference", {"URI" => "##{uuid}"})

  # Add Transforms
  transforms_element = reference_element.add_element("ds:Transforms")
  transforms_element.add_element("ds:Transform", {"Algorithm" => ENVELOPED_SIG})
  c14element = transforms_element.add_element("ds:Transform", {"Algorithm" => C14N})
  c14element.add_element("ec:InclusiveNamespaces", {"xmlns:ec" => C14N, "PrefixList" => INC_PREFIX_LIST})

  digest_method_element = reference_element.add_element("ds:DigestMethod", {"Algorithm" => digest_method})
  inclusive_namespaces = INC_PREFIX_LIST.split(" ")
  canon_doc = noko.canonicalize(canon_algorithm(C14N), inclusive_namespaces)
  #canon_doc = noko.canonicalize(canon_algorithm(C14N))
  reference_element.add_element("ds:DigestValue").text = compute_digest(canon_doc, algorithm(digest_method_element))

  # add SignatureValue
  noko_sig_element = Nokogiri::XML(signature_element.to_s) do |config|
    config.options = Spid::XMLSecurityNew::BaseDocument::NOKOGIRI_OPTIONS
  end

  noko_signed_info_element = noko_sig_element.at_xpath('//ds:Signature/ds:SignedInfo', 'ds' => DSIG)
  canon_string = noko_signed_info_element.canonicalize(canon_algorithm(C14N), inclusive_namespaces)

  signature = compute_signature(private_key, algorithm(signature_method).new, canon_string)
  signature_element.add_element("ds:SignatureValue").text = signature.to_s.gsub(/\n/, "").gsub(/\t/, "")

  # add KeyInfo
  key_info_element       = signature_element.add_element("ds:KeyInfo")
  x509_element           = key_info_element.add_element("ds:X509Data")
  x509_cert_element      = x509_element.add_element("ds:X509Certificate")
  if certificate.is_a?(String)
    certificate = OpenSSL::X509::Certificate.new(certificate)
  end
  x509_cert_element.text = Base64.encode64(certificate.to_der).to_s.gsub(/\n/, "").gsub(/\t/, "")

  # add the signature
  sp_sso_descriptor = self.root.elements["md:SPSSODescriptor"]
  unless sp_sso_descriptor.blank?
    #inserisco firma nei metadata
    self.root.insert_before sp_sso_descriptor, signature_element
  else
    #inserisco firma nella request
    saml_issuer = self.root.elements["saml:Issuer"]
    self.root.insert_after saml_issuer, signature_element
  end
  

end

Protected Instance Methods

compute_digest(document, digest_algorithm) click to toggle source
# File lib/spid/xml_security_new.rb, line 183
def compute_digest(document, digest_algorithm)
  digest = digest_algorithm.digest(document)
  Base64.encode64(digest).strip!
end
compute_signature(private_key, signature_algorithm, document) click to toggle source
# File lib/spid/xml_security_new.rb, line 179
def compute_signature(private_key, signature_algorithm, document)
  Base64.encode64(private_key.sign(signature_algorithm, document)).to_s.gsub(/\n/, "").gsub(/\t/, "")
end