class OpenID::SimpleSign
Basic implementation of the XML Simple Sign algorithm. Currently only supports RSA-SHA1
Constants
- C14N_RAW_OCTETS
- NAMESPACES
- SIGN_RSA_SHA1
Public Class Methods
parse_certificates(doc)
click to toggle source
Extracts the signer's certificates from the XML
# File lib/gapps_openid.rb, line 264 def self.parse_certificates(doc) certs = [] REXML::XPath.each(doc, "//ds:Signature/ds:KeyInfo/ds:X509Data/ds:X509Certificate", NAMESPACES ) { | encoded | encoded = encoded.text.strip.scan(/.{1,64}/).join("\n") encoded = "-----BEGIN CERTIFICATE-----\n#{encoded}\n-----END CERTIFICATE-----\n" cert = OpenSSL::X509::Certificate.new(encoded) certs << cert } return certs end
store()
click to toggle source
Initialize the store
# File lib/gapps_openid.rb, line 252 def self.store if @@store.nil? OpenID.logger.info("Initializing CA bundle") unless OpenID.logger.nil? ca_bundle_path = File.join(File.dirname(__FILE__), 'ca-bundle.crt') @@store = OpenSSL::X509::Store.new @@store.set_default_paths @@store.add_file(ca_bundle_path) end return @@store end
valid_chain?(chain)
click to toggle source
Verifies the chain of trust for the signing certificates
# File lib/gapps_openid.rb, line 276 def self.valid_chain?(chain) if chain.nil? or chain.empty? return false end cert = chain.shift if self.store.verify(cert) return true end if chain.empty? or not cert.verify(chain.first.public_key) return false end return self.valid_chain?(chain) end
verify(xml, signature_value)
click to toggle source
Verifies the signature of the doc, returning the CN of the signer if valid
# File lib/gapps_openid.rb, line 291 def self.verify(xml, signature_value) doc = REXML::Document.new(xml) return nil if REXML::XPath.first(doc, "//ds:Signature").nil? and signature_value.nil? decoded_sig = Base64.decode64(signature_value) certs = self.parse_certificates(doc) raise "No signature in document" if certs.nil? or certs.empty? raise "Missing signature value" if signature_value.nil? signing_certificate = certs.first raise "Invalid signature" if !signing_certificate.public_key.verify(OpenSSL::Digest::SHA1.new, decoded_sig, xml) raise "Certificate chain not valid" if !self.valid_chain?(certs) # Signature is valid, return CN of the subject subject = signing_certificate.subject.to_a signed_by = subject.last[1] return signed_by end