Module: SAML2::Signable
- Included in:
- Entity, Entity::Group, Message, Role
- Defined in:
- lib/saml2/signable.rb
Instance Method Summary collapse
-
#sign(x509_certificate, private_key, algorithm_name = :sha256) ⇒ self
Sign this object.
- #signature ⇒ Nokogiri::XML::Element?
- #signed? ⇒ Boolean
- #signing_key ⇒ KeyInfo?
-
#valid_signature?(**kwargs) ⇒ Boolean
Check if the signature on this object is valid.
-
#validate_signature(key: nil, fingerprint: nil, cert: nil) ⇒ Array<String>
Validate the signature on this object.
Instance Method Details
#sign(x509_certificate, private_key, algorithm_name = :sha256) ⇒ self
Sign this object.
116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
# File 'lib/saml2/signable.rb', line 116 def sign(x509_certificate, private_key, algorithm_name = :sha256) to_xml xml = @document.root xml.set_id_attribute("ID") xml.sign!(cert: x509_certificate, key: private_key, digest_alg: algorithm_name.to_s, signature_alg: "rsa-#{algorithm_name}", uri: "##{id}") # the Signature element must be the first element signature = xml.at_xpath("dsig:Signature", Namespaces::ALL) xml.children.first.add_previous_sibling(signature) self end |
#signature ⇒ Nokogiri::XML::Element?
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/saml2/signable.rb', line 8 def signature unless instance_variable_defined?(:@signature) @signature = xml.xpath("//dsig:Signature", Namespaces::ALL).find do |signature| signed_node = signature.at_xpath("dsig:SignedInfo/dsig:Reference", Namespaces::ALL)["URI"] if signed_node == "" true if xml == xml.document.root elsif signed_node != "##{xml["ID"]}" false else # validating the schema will automatically add ID attributes, so check that first xml.set_id_attribute("ID") unless xml.document.get_id(xml["ID"]) true end end end @signature end |
#signed? ⇒ Boolean
40 41 42 |
# File 'lib/saml2/signable.rb', line 40 def signed? !!signature end |
#signing_key ⇒ KeyInfo?
27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/saml2/signable.rb', line 27 def signing_key unless instance_variable_defined?(:@signing_key) # don't use `... if signature.at_xpath(...)` - we need to make sure we assign the nil @signing_key = if (key_info = signature.at_xpath("dsig:KeyInfo", Namespaces::ALL)) KeyInfo.from_xml(key_info) else nil end end @signing_key end |
#valid_signature?(**kwargs) ⇒ Boolean
Check if the signature on this object is valid.
Either fingerprint
or cert
must be provided.
103 104 105 |
# File 'lib/saml2/signable.rb', line 103 def valid_signature?(**kwargs) validate_signature(**kwargs).empty? end |
#validate_signature(key: nil, fingerprint: nil, cert: nil) ⇒ Array<String>
Validate the signature on this object.
At least one of key
, fingerprint
or cert
must be provided. If the signature doesn’t specify which key to use, the first provided key will be used.
62 63 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 |
# File 'lib/saml2/signable.rb', line 62 def validate_signature(key: nil, fingerprint: nil, cert: nil) return ["not signed"] unless signed? certs = Array(cert) certs = certs.dup if certs.equal?(cert) # see if any given fingerprints match the certificate embedded in the XML; # if so, extract the certificate, and add it to the allowed certificates list Array(fingerprint).each do |fp| certs << signing_key.certificate if signing_key&.fingerprint == SAML2::KeyInfo.format_fingerprint(fp) end certs = certs.uniq trusted_keys = Array.wrap(key).map(&:to_s) trusted_keys.concat(certs.map do |certificate| certificate = OpenSSL::X509::Certificate.new(certificate) if certificate.is_a?(String) certificate.public_key.to_s end) verification_key = signing_key.public_key.to_s if trusted_keys.include?(signing_key&.public_key&.to_s) # signature doesn't say who signed it. hope and pray it's with the only certificate # we know about verification_key = trusted_keys.first if signing_key.nil? return ["no trusted signing key found"] if verification_key.nil? begin result = signature.verify_with(key: verification_key) result ? [] : ["signature is invalid"] rescue XMLSec::VerificationError => e [e.] end end |