Class: WebpayRails::Verifier

Inherits:
Object
  • Object
show all
Defined in:
lib/webpay_rails/verifier.rb

Class Method Summary collapse

Class Method Details

.canonicalize(node = document, inclusive_namespaces = nil) ⇒ Object



47
48
49
50
# File 'lib/webpay_rails/verifier.rb', line 47

def self.canonicalize(node = document, inclusive_namespaces=nil)
  # The last argument should be exactly +nil+ to remove comments from result
  node.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0, inclusive_namespaces, nil)
end

.check_digest(doc, signed_info_node) ⇒ Object



15
16
17
18
19
20
21
# File 'lib/webpay_rails/verifier.rb', line 15

def self.check_digest(doc, signed_info_node)
  signed_info_node.xpath("//ds:Reference", ds: 'http://www.w3.org/2000/09/xmldsig#').each do |node|
    return false if !process_ref_node(doc, node)
  end

  true
end

.check_signature(doc, signed_info_node, cert) ⇒ Object



23
24
25
26
27
28
29
30
31
# File 'lib/webpay_rails/verifier.rb', line 23

def self.check_signature(doc, signed_info_node, cert)
  signed_info_canon = canonicalize(signed_info_node, ['soap'])
  signature = doc.at_xpath('//wsse:Security/ds:Signature/ds:SignatureValue', {
    ds: 'http://www.w3.org/2000/09/xmldsig#',
    wsse: 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
  }).text

  cert.public_key.verify(OpenSSL::Digest::SHA1.new, Base64.decode64(signature), signed_info_canon)
end

.digest(message) ⇒ Object



33
34
35
# File 'lib/webpay_rails/verifier.rb', line 33

def self.digest(message)
  OpenSSL::Digest::SHA1.new.reset.digest(message)
end

.process_ref_node(doc, node) ⇒ Object



37
38
39
40
41
42
43
44
45
# File 'lib/webpay_rails/verifier.rb', line 37

def self.process_ref_node(doc, node)
  uri = node.attr('URI')
  element = doc.at_xpath("//*[@wsu:Id='#{uri[1..-1]}']", wsu: 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd')
  target = canonicalize(element, nil)
  my_digest_value = Base64.encode64(digest(target)).strip
  digest_value = node.at_xpath('//ds:DigestValue', ds: 'http://www.w3.org/2000/09/xmldsig#').text

  my_digest_value == digest_value
end

.verify(document, cert) ⇒ Object



3
4
5
6
7
8
9
10
11
12
13
# File 'lib/webpay_rails/verifier.rb', line 3

def self.verify(document, cert)
  document = Nokogiri::XML(document.to_s, &:noblanks)
  signed_info_node = document.at_xpath('/soap:Envelope/soap:Header/wsse:Security/ds:Signature/ds:SignedInfo', {
    ds: 'http://www.w3.org/2000/09/xmldsig#',
    wsse: 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd',
    soap: 'http://schemas.xmlsoap.org/soap/envelope/'
  })

  # check that digest match
  check_digest(document, signed_info_node) && check_signature(document, signed_info_node, cert)
end