class XMLSecurity::Document

Constants

ENVELOPED_SIG
INC_PREFIX_LIST
SHA1
SHA256
SHA384
SHA512

Attributes

uuid[RW]

Public Instance Methods

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

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

# File lib/xml_security.rb, line 98
def sign_document(private_key, certificate, signature_method = SHA1, digest_method = SHA1)
  noko = Nokogiri.parse(self.to_s)
  canon_doc = noko.canonicalize(canon_algorithm(C14N))

  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})
  transforms_element.add_element("ds:Transform", {"Algorithm" => C14N})
  transforms_element.add_element("ds:InclusiveNamespaces", {"xmlns" => C14N, "PrefixList" => INC_PREFIX_LIST})

  digest_method_element = reference_element.add_element("ds:DigestMethod", {"Algorithm" => digest_method})
  reference_element.add_element("ds:DigestValue").text = compute_digest(canon_doc, algorithm(digest_method_element))

  # add SignatureValue
  noko_sig_element = Nokogiri.parse(signature_element.to_s)
  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))
  signature = compute_signature(private_key, algorithm(signature_method).new, canon_string)
  signature_element.add_element("ds:SignatureValue").text = signature

  # 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).gsub(/\n/, "")

  # add the signature
  issuer_element = self.elements["//saml:Issuer"]
  if issuer_element
    self.root.insert_after issuer_element, signature_element
  else
    self.root.add_element(signature_element)
  end
end

Protected Instance Methods

compute_digest(document, digest_algorithm) click to toggle source
# File lib/xml_security.rb, line 150
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/xml_security.rb, line 146
def compute_signature(private_key, signature_algorithm, document)
  Base64.encode64(private_key.sign(signature_algorithm, document)).gsub(/\n/, "")
end