Class: OpenID::SimpleSign
- Inherits:
-
Object
- Object
- OpenID::SimpleSign
- Defined in:
- lib/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
232 233 234 235 236 237 238 239 240 241 |
# File 'lib/gapps_openid.rb', line 232 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
220 221 222 223 224 225 226 227 228 229 |
# File 'lib/gapps_openid.rb', line 220 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) ⇒ Boolean
Verifies the chain of trust for the signing certificates
244 245 246 247 248 249 250 251 252 253 254 255 256 |
# File 'lib/gapps_openid.rb', line 244 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
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
# File 'lib/gapps_openid.rb', line 259 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 |