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
219 220 221 222 223 224 225 226 227 228 |
# File 'lib/warden-googleapps/gapps_openid.rb', line 219 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
208 209 210 211 212 213 214 215 216 |
# File 'lib/warden-googleapps/gapps_openid.rb', line 208 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
231 232 233 234 235 236 237 238 239 240 241 242 243 |
# File 'lib/warden-googleapps/gapps_openid.rb', line 231 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
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/warden-googleapps/gapps_openid.rb', line 246 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 |