Class: Rack::Shibboleth::Response
- Inherits:
-
Object
- Object
- Rack::Shibboleth::Response
- Defined in:
- lib/rack/shibboleth/response.rb
Overview
Encapsulates the logic for parsing the response of an IdP to the application. The XML of the response has already been extracted and is the parameter for the construction of this class
Instance Method Summary (collapse)
-
- (LibXML::XML::Document) decode(private_key)
Decodes the response of the IdP and retuns the decrypted XML.
-
- (Response) initialize(xml)
constructor
Initializes a new response with the given XML from the IdP.
Constructor Details
- (Response) initialize(xml)
Initializes a new response with the given XML from the IdP
19 20 21 22 23 24 25 |
# File 'lib/rack/shibboleth/response.rb', line 19 def initialize xml begin @doc = LibXML::XML::Document.string(xml) rescue LibXML::XML::Error @doc = nil end end |
Instance Method Details
- (LibXML::XML::Document) decode(private_key)
Decodes the response of the IdP and retuns the decrypted XML
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/rack/shibboleth/response.rb', line 34 def decode private_key # This is the public key which encrypted the first CipherValue cert = @doc.find_first( '//xenc:EncryptedData//ds:X509Certificate', [DS, XENC]).content c1, c2 = @doc.find('//xenc:CipherValue', XENC).map(&:content) cert = OpenSSL::X509::Certificate.new(Base64.decode64(cert)) return nil unless cert.check_private_key(private_key) # Generate the key used for the cipher below via the RSA::OAEP algo rsak = RSA::Key.new private_key.n, private_key.d v1s = Base64.decode64(c1) begin cipherkey = RSA::OAEP.decode rsak, v1s rescue RSA::OAEP::DecodeError return nil end # The aes-128-cbc cipher has a 128 bit initialization vector (16 bytes) # and this is the first 16 bytes of the raw string. bytes = Base64.decode64(c2).unpack('C*') iv = bytes.pack('c16') others = bytes.pack('c16X16c*') cipher = OpenSSL::Cipher.new('aes-128-cbc') cipher.decrypt cipher.iv = iv cipher.key = cipherkey out = cipher.update(others) # The encrypted string's length might not be a multiple of the block # length of aes-128-cbc (16), so add in another block and then trim # off the padding. More info about padding is available at # http://www.w3.org/TR/2002/REC-xmlenc-core-20021210/Overview.html in # Section 5.2 out << cipher.update("\x00" * 16) padding = out.bytes.to_a.last dec = LibXML::XML::Document.string(out[0..-(padding + 1)]) # Must check that there is a signature listed and that the signature is # valid for the enclosing document. sig = dec.find_first('//ds:Signature', DS) if sig && valid_hashes?(sig) && valid_signature?(sig) dec end end |