Class: OpenID::SimpleSign
- Inherits:
-
Object
- Object
- OpenID::SimpleSign
- Defined in:
- lib/warden-googleapps/gapps_openid.rb
Overview
Basic implementation of the XML Simple Sign algorithm. Currently only supports RSA-SHA1
Constant Summary collapse
- C14N_RAW_OCTETS =
'http://docs.oasis-open.org/xri/xrd/2009/01#canonicalize-raw-octets'
- SIGN_RSA_SHA1 =
'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
- NAMESPACES =
{ 'ds' => 'http://www.w3.org/2000/09/xmldsig#', 'xrds' => 'xri://xrds' }
- @@store =
nil
Class Method Summary collapse
-
.parse_certificates(doc) ⇒ Object
Extracts the signer’s certificates from the XML.
-
.store ⇒ Object
Initialize the store.
-
.valid_chain?(chain) ⇒ Boolean
Verifies the chain of trust for the signing certificates.
-
.verify(xml, signature_value) ⇒ Object
Verifies the signature of the doc, returning the CN of the signer if valid.
Class Method Details
.parse_certificates(doc) ⇒ Object
Extracts the signer’s certificates from the XML
221 222 223 224 225 226 227 228 229 230 |
# File 'lib/warden-googleapps/gapps_openid.rb', line 221 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 ⇒ Object
Initialize the store
210 211 212 213 214 215 216 217 218 |
# File 'lib/warden-googleapps/gapps_openid.rb', line 210 def self.store if @@store.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) ⇒ Boolean
Verifies the chain of trust for the signing certificates
233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/warden-googleapps/gapps_openid.rb', line 233 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) ⇒ Object
Verifies the signature of the doc, returning the CN of the signer if valid
248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 |
# File 'lib/warden-googleapps/gapps_openid.rb', line 248 def self.verify(xml, signature_value) raise "Missing signature value" if signature_value.nil? decoded_sig = Base64.decode64(signature_value) doc = REXML::Document.new(xml) certs = self.parse_certificates(doc) raise "No signature in document" if certs.nil? or certs.empty? 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 |