sepafm 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e8fbb8495a8ef64c200672b7b95856c63373e4d2
4
- data.tar.gz: 0d89865ffa9d69de4c25252ead68e6865d99d326
3
+ metadata.gz: bd61a928b1047406c415f8e76b8dddbd8f303ca8
4
+ data.tar.gz: 999e4c7a9d47219e5a22907cf59d85e9921ff4b7
5
5
  SHA512:
6
- metadata.gz: 229d1763748a90cbc02c9d2395c2b7d8737fdc584d68c97c96becca0aecca888780a72e4f73067a86c3bf1307e3812535e472b1912bf0a0c4ea06d6235a1501b
7
- data.tar.gz: 12e4f735a16657b501354349d886f6e52e88a9a8e2e33b4567d83b23107f347983e73c0d943c100a856be1b71171dfb057990ad60bca7fa27cc6844febc1039e
6
+ metadata.gz: 0c0e5960cc2e6a0941533fae597be7a041b8f4274a3eec0b92b69b9ca84bc5d69c5eb456f8049ecce39f87060a564cd32e1f2ab50426bb10c55e27bd77f1e732
7
+ data.tar.gz: 1e27582d39e099255357ffd6068bee42521e385e4410565cfbc9ff467c4b94eea80c39781aad39b7144144c465054915ef46f02be476d403905890a1185c57e2
@@ -8,18 +8,18 @@ module Sepa
8
8
  instance_variable_set("@#{key}", value)
9
9
  end
10
10
 
11
- @ar = load_body_template AR_TEMPLATE_PATH
11
+ @application_request = load_body_template AR_TEMPLATE_PATH
12
12
  end
13
13
 
14
14
  def to_xml
15
15
  set_common_nodes
16
16
  set_nodes_contents
17
17
  process_signature
18
- @ar.to_xml
18
+ @application_request.to_xml
19
19
  end
20
20
 
21
21
  def to_base64
22
- Base64.encode64(to_xml)
22
+ encode to_xml
23
23
  end
24
24
 
25
25
  def to_nokogiri
@@ -29,11 +29,11 @@ module Sepa
29
29
  private
30
30
 
31
31
  def set_node(node, value)
32
- @ar.at_css(node).content = value
32
+ @application_request.at_css(node).content = value
33
33
  end
34
34
 
35
35
  def set_node_b(node, value)
36
- set_node node, Base64.encode64(value)
36
+ set_node node, encode(value)
37
37
  end
38
38
 
39
39
  def pretty_command
@@ -109,28 +109,30 @@ module Sepa
109
109
  end
110
110
 
111
111
  def remove_node(node, xmlns)
112
- @ar.at_css("xmlns|#{node}", 'xmlns' => xmlns).remove
112
+ @application_request.at_css("xmlns|#{node}", 'xmlns' => xmlns).remove
113
113
  end
114
114
 
115
115
  def add_node_to_root(node)
116
- @ar.root.add_child(node)
116
+ @application_request.root.add_child(node)
117
117
  end
118
118
 
119
119
  def calculate_digest
120
120
  sha1 = OpenSSL::Digest::SHA1.new
121
- Base64.encode64(sha1.digest(@ar.canonicalize))
121
+ encode(sha1.digest(@application_request.canonicalize))
122
122
  end
123
123
 
124
124
  def add_value_to_signature(node, value)
125
- sig = @ar.at_css("dsig|#{node}", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#')
125
+ dsig = 'http://www.w3.org/2000/09/xmldsig#'
126
+ sig = @application_request.at_css("dsig|#{node}", 'dsig' => dsig)
126
127
  sig.content = value
127
128
  end
128
129
 
129
130
  def calculate_signature
130
131
  sha1 = OpenSSL::Digest::SHA1.new
131
- node = @ar.at_css("dsig|SignedInfo", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#')
132
+ dsig = 'http://www.w3.org/2000/09/xmldsig#'
133
+ node = @application_request.at_css("dsig|SignedInfo", 'dsig' => dsig)
132
134
  signature = @private_key.sign(sha1, node.canonicalize)
133
- Base64.encode64(signature)
135
+ encode signature
134
136
  end
135
137
 
136
138
  def process_signature
@@ -3,29 +3,26 @@ module Sepa
3
3
  include ActiveModel::Validations
4
4
  include Utilities
5
5
 
6
- attr_accessor :ar, :certificate
6
+ attr_reader :xml
7
7
 
8
8
  validate :response_must_validate_against_schema
9
9
  validate :validate_document_format
10
10
 
11
11
  def initialize(app_resp)
12
- self.ar = app_resp
13
- self.certificate = extract_cert(ar, 'X509Certificate', 'http://www.w3.org/2000/09/xmldsig#')
12
+ @xml = app_resp
13
+ end
14
+
15
+ def doc
16
+ @doc ||= xml_doc @xml
14
17
  end
15
18
 
16
19
  # Checks that the hash value reported in the signature matches the actual one.
17
20
  def hashes_match?
18
- are = ar.clone
21
+ are = doc.clone
19
22
 
20
- digest_value = are.at_css(
21
- 'xmlns|DigestValue',
22
- 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
23
- ).content.strip
23
+ digest_value = are.at('xmlns|DigestValue', xmlns: DSIG).content.strip
24
24
 
25
- are.at_css(
26
- "xmlns|Signature",
27
- 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
28
- ).remove
25
+ are.at('xmlns|Signature', xmlns: DSIG).remove
29
26
 
30
27
  actual_digest = calculate_digest(are)
31
28
 
@@ -36,31 +33,34 @@ module Sepa
36
33
 
37
34
  # Checks that the signature is signed with the private key of the certificate's public key.
38
35
  def signature_is_valid?
39
- node = ar.at_css('xmlns|SignedInfo', 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#')
40
-
36
+ node = doc.at('xmlns|SignedInfo', 'xmlns' => DSIG)
41
37
  node = node.canonicalize
42
38
 
43
- signature = ar.at_css(
44
- 'xmlns|SignatureValue',
45
- 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
46
- ).content
47
-
48
- signature = Base64.decode64(signature)
39
+ signature = doc.at('xmlns|SignatureValue', 'xmlns' => DSIG).content
40
+ signature = decode(signature)
49
41
 
50
42
  # Return true or false
51
43
  certificate.public_key.verify(OpenSSL::Digest::SHA1.new, signature, node)
52
44
  end
53
45
 
46
+ def to_s
47
+ @xml
48
+ end
49
+
50
+ def certificate
51
+ extract_cert(doc, 'X509Certificate', DSIG)
52
+ end
53
+
54
54
  private
55
55
 
56
56
  def validate_document_format
57
- unless ar.respond_to?(:canonicalize)
58
- errors.add(:base, 'Document must be a Nokogiri XML file')
57
+ unless doc.respond_to?(:canonicalize)
58
+ errors.add(:base, 'Document must be a valid XML file')
59
59
  end
60
60
  end
61
61
 
62
62
  def response_must_validate_against_schema
63
- check_validity_against_schema(ar, 'application_response.xsd')
63
+ check_validity_against_schema(doc, 'application_response.xsd')
64
64
  end
65
65
 
66
66
  end
@@ -50,27 +50,6 @@ module Sepa
50
50
  end
51
51
  end
52
52
 
53
- def wsdl
54
- case bank
55
- when :nordea
56
- if command == :get_certificate
57
- file = "wsdl_nordea_cert.xml"
58
- else
59
- file = "wsdl_nordea.xml"
60
- end
61
- when :danske
62
- if [:get_bank_certificate, :create_certificate].include? command
63
- file = "wsdl_danske_cert.xml"
64
- else
65
- file = "wsdl_danske.xml"
66
- end
67
- else
68
- return nil
69
- end
70
-
71
- "#{WSDL_PATH}/#{file}"
72
- end
73
-
74
53
  def check_wsdl
75
54
  return unless wsdl.present?
76
55
 
@@ -1,19 +1,45 @@
1
1
  module Sepa
2
2
  class DanskeResponse < Response
3
- attr_reader :bank_encryption_cert, :bank_signing_cert, :bank_root_cert, :own_encryption_cert,
4
- :own_signing_cert, :ca_certificate
5
-
6
- # Namespace used in danske bank certificate responses and requests
7
- TNS = 'http://danskebank.dk/PKI/PKIFactoryService/elements'
8
-
9
- def initialize(response, command: nil)
10
- super
11
- @bank_encryption_cert = extract_cert(soap, 'BankEncryptionCert', TNS)
12
- @bank_signing_cert = extract_cert(soap, 'BankSigningCert', TNS)
13
- @bank_root_cert = extract_cert(soap, 'BankRootCert', TNS)
14
- @own_encryption_cert = extract_cert(soap, 'EncryptionCert', TNS)
15
- @own_signing_cert = extract_cert(soap, 'SigningCert', TNS)
16
- @ca_certificate = extract_cert(soap, 'CACert', TNS)
3
+
4
+ def bank_encryption_cert
5
+ @bank_encryption_cert ||= extract_cert(doc, 'BankEncryptionCert', DANSKE_PKI)
6
+ end
7
+
8
+ def bank_signing_cert
9
+ @bank_signing_cert ||= extract_cert(doc, 'BankSigningCert', DANSKE_PKI)
10
+ end
11
+
12
+ def bank_root_cert
13
+ @bank_root_cert ||= extract_cert(doc, 'BankRootCert', DANSKE_PKI)
14
+ end
15
+
16
+ def own_encryption_cert
17
+ @own_encryption_cert ||= extract_cert(doc, 'EncryptionCert', DANSKE_PKI)
18
+ end
19
+
20
+ def own_signing_cert
21
+ @own_signing_cert ||= extract_cert(doc, 'SigningCert', DANSKE_PKI)
22
+ end
23
+
24
+ def ca_certificate
25
+ @ca_certificate ||= extract_cert(doc, 'CACert', DANSKE_PKI)
26
+ end
27
+
28
+ def certificate
29
+ if @command == :create_certificate
30
+ @certificate ||= begin
31
+ extract_cert(doc, 'X509Certificate', DSIG)
32
+ end
33
+ end
17
34
  end
35
+
36
+ private
37
+
38
+ def find_node_by_uri(uri)
39
+ node = doc.at("[xml|id='#{uri}']")
40
+ node.at('xmlns|Signature', xmlns: DSIG).remove
41
+ node
42
+ end
43
+
18
44
  end
19
45
  end
@@ -1,132 +1,134 @@
1
1
  module Sepa
2
2
  module DanskeSoapRequest
3
3
 
4
- def find_correct_build
5
- case @command
6
- when :create_certificate
7
- build_certificate_request
8
- when :upload_file, :download_file, :get_user_info, :download_file_list
9
- build_danske_generic_request
10
- when :get_bank_certificate
11
- build_get_bank_certificate_request
4
+ private
5
+
6
+ def find_correct_build
7
+ case @command
8
+ when :create_certificate
9
+ build_certificate_request
10
+ when :upload_file, :download_file, :get_user_info, :download_file_list
11
+ build_danske_generic_request
12
+ when :get_bank_certificate
13
+ build_get_bank_certificate_request
14
+ end
15
+ end
16
+
17
+ def encrypt_application_request
18
+ encryption_cert = OpenSSL::X509::Certificate.new(@enc_cert)
19
+ encryption_public_key = encryption_cert.public_key
20
+ encryption_cert = format_cert(encryption_cert)
21
+ encrypted_ar, key = encrypt_ar
22
+ encrypted_key = encrypt_key(key, encryption_public_key)
23
+ build_encrypted_ar(encryption_cert, encrypted_key, encrypted_ar)
24
+ end
25
+
26
+ # Encrypts a given symmetric encryption key with a public key and returns it in base64 encoded
27
+ # format
28
+ def encrypt_key(key, public_key)
29
+ encrypted_key = public_key.public_encrypt(key)
30
+ encode encrypted_key
31
+ end
32
+
33
+ # Encrypts the application request and returns it in base64 encoded format.
34
+ # Also returns the key needed to decrypt it
35
+ def encrypt_ar
36
+ cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').encrypt
37
+
38
+ key = cipher.random_key
39
+ iv = cipher.random_iv
40
+
41
+ encrypted_data = cipher.update(@application_request.to_xml)
42
+ encrypted_data << cipher.final
43
+ encrypted_data = iv + encrypted_data
44
+ encrypted_data = encode encrypted_data
45
+
46
+ return encrypted_data, key
47
+ end
48
+
49
+ def build_encrypted_ar(cert, encrypted_data, encrypted_key)
50
+ ar = Nokogiri::XML File.open "#{AR_TEMPLATE_PATH}/encrypted_request.xml"
51
+ set_node(ar, 'dsig|X509Certificate', cert)
52
+ set_node(ar, 'dsig|KeyInfo xenc|CipherValue', encrypted_data)
53
+ set_node(ar, 'xenc|EncryptedData > xenc|CipherData > xenc|CipherValue', encrypted_key)
54
+ ar
55
+ end
56
+
57
+ def set_generic_request_contents
58
+ set_node(@template, 'bxd|SenderId', @customer_id)
59
+ set_node(@template, 'bxd|RequestId', request_id)
60
+ set_node(@template, 'bxd|Timestamp', iso_time)
61
+ set_node(@template, 'bxd|Language', @language)
62
+ set_node(@template, 'bxd|UserAgent', "Sepa Transfer Library version " + VERSION)
63
+ set_node(@template, 'bxd|ReceiverId', @target_id)
64
+ end
65
+
66
+ def set_create_cert_contents
67
+ set_node(@template, 'pkif|SenderId', @customer_id)
68
+ set_node(@template, 'pkif|CustomerId', @customer_id)
69
+ set_node(@template, 'pkif|RequestId', request_id)
70
+ set_node(@template, 'pkif|Timestamp', iso_time)
71
+ set_node(@template, 'pkif|InterfaceVersion', 1)
72
+ set_node(@template, 'pkif|Environment', @environment)
73
+ end
74
+
75
+ def set_bank_certificate_contents
76
+ set_node(@template, 'pkif|SenderId', @customer_id)
77
+ set_node(@template, 'pkif|CustomerId', @customer_id)
78
+ set_node(@template, 'pkif|RequestId', request_id)
79
+ set_node(@template, 'pkif|Timestamp', iso_time)
80
+ set_node(@template, 'pkif|InterfaceVersion', 1)
81
+ end
82
+
83
+ def build_danske_generic_request
84
+ set_generic_request_contents
85
+ encrypted_request = encrypt_application_request
86
+ add_encrypted_generic_request_to_soap(encrypted_request)
87
+
88
+ process_header
89
+ add_body_to_header
90
+ end
91
+
92
+ def build_certificate_request
93
+ set_create_cert_contents
94
+ encrypted_request = encrypt_application_request
95
+ add_encrypted_request_to_soap(encrypted_request)
96
+ end
97
+
98
+ def build_get_bank_certificate_request
99
+ set_bank_certificate_contents
100
+ add_bank_certificate_body_to_soap
101
+ end
102
+
103
+ def add_encrypted_request_to_soap(encrypted_request)
104
+ encrypted_request = Nokogiri::XML(encrypted_request.to_xml)
105
+ encrypted_request = encrypted_request.root
106
+ @template.at_css('pkif|CreateCertificateIn').add_child(encrypted_request)
107
+
108
+ @template
109
+ end
110
+
111
+ def add_encrypted_generic_request_to_soap(encrypted_request)
112
+ encrypted_request = Nokogiri::XML(encrypted_request.to_xml)
113
+ encrypted_request = encrypted_request.root
114
+ encrypted_request = encode encrypted_request.to_xml
115
+ @template.at_css('bxd|ApplicationRequest').add_child(encrypted_request)
116
+
117
+ @template
118
+ end
119
+
120
+ def add_bank_certificate_body_to_soap
121
+ ar = @application_request.to_nokogiri
122
+
123
+ ar = ar.at_css('elem|GetBankCertificateRequest')
124
+ @template.at_css('pkif|GetBankCertificateIn').add_child(ar)
125
+
126
+ @template
127
+ end
128
+
129
+ def request_id
130
+ SecureRandom.hex(5)
12
131
  end
13
- end
14
-
15
- def encrypt_application_request
16
- encryption_cert = OpenSSL::X509::Certificate.new(@enc_cert)
17
- encryption_public_key = encryption_cert.public_key
18
- encryption_cert = format_cert(encryption_cert)
19
- encrypted_ar, key = encrypt_ar
20
- encrypted_key = encrypt_key(key, encryption_public_key)
21
- build_encrypted_ar(encryption_cert, encrypted_key, encrypted_ar)
22
- end
23
-
24
- # Encrypts a given symmetric encryption key with a public key and returns it in base64 encoded
25
- # format
26
- def encrypt_key(key, public_key)
27
- encrypted_key = public_key.public_encrypt(key)
28
- Base64.encode64(encrypted_key)
29
- end
30
-
31
- # Encrypts the application request and returns it in base64 encoded format.
32
- # Also returns the key needed to decrypt it
33
- def encrypt_ar
34
- cipher = OpenSSL::Cipher.new('DES-EDE3-CBC').encrypt
35
-
36
- key = cipher.random_key
37
- iv = cipher.random_iv
38
-
39
- encrypted_data = cipher.update(@ar.to_xml)
40
- encrypted_data << cipher.final
41
- encrypted_data = iv + encrypted_data
42
- encrypted_data = Base64.encode64(encrypted_data)
43
-
44
- return encrypted_data, key
45
- end
46
-
47
- def build_encrypted_ar(cert, encrypted_data, encrypted_key)
48
- ar = Nokogiri::XML File.open "#{AR_TEMPLATE_PATH}/encrypted_request.xml"
49
- set_node(ar, 'dsig|X509Certificate', cert)
50
- set_node(ar, 'dsig|KeyInfo xenc|CipherValue', encrypted_data)
51
- set_node(ar, 'xenc|EncryptedData > xenc|CipherData > xenc|CipherValue', encrypted_key)
52
- ar
53
- end
54
-
55
- def set_generic_request_contents
56
- set_node(@template, 'bxd|SenderId', @customer_id)
57
- set_node(@template, 'bxd|RequestId', request_id)
58
- set_node(@template, 'bxd|Timestamp', iso_time)
59
- set_node(@template, 'bxd|Language', @language)
60
- set_node(@template, 'bxd|UserAgent', "Sepa Transfer Library version " + VERSION)
61
- set_node(@template, 'bxd|ReceiverId', @target_id)
62
- end
63
-
64
- def set_create_cert_contents
65
- set_node(@template, 'pkif|SenderId', @customer_id)
66
- set_node(@template, 'pkif|CustomerId', @customer_id)
67
- set_node(@template, 'pkif|RequestId', request_id)
68
- set_node(@template, 'pkif|Timestamp', iso_time)
69
- set_node(@template, 'pkif|InterfaceVersion', 1)
70
- set_node(@template, 'pkif|Environment', @environment)
71
- end
72
-
73
- def set_bank_certificate_contents
74
- set_node(@template, 'pkif|SenderId', @customer_id)
75
- set_node(@template, 'pkif|CustomerId', @customer_id)
76
- set_node(@template, 'pkif|RequestId', request_id)
77
- set_node(@template, 'pkif|Timestamp', iso_time)
78
- set_node(@template, 'pkif|InterfaceVersion', 1)
79
- end
80
-
81
- def build_danske_generic_request
82
- set_generic_request_contents
83
- encrypted_request = encrypt_application_request
84
- add_encrypted_generic_request_to_soap(encrypted_request)
85
-
86
- process_header
87
- add_body_to_header
88
- end
89
-
90
- def build_certificate_request
91
- set_create_cert_contents
92
- encrypted_request = encrypt_application_request
93
- add_encrypted_request_to_soap(encrypted_request)
94
- end
95
-
96
- def build_get_bank_certificate_request
97
- set_bank_certificate_contents
98
- add_bank_certificate_body_to_soap
99
- end
100
-
101
- def add_encrypted_request_to_soap(encrypted_request)
102
- encrypted_request = Nokogiri::XML(encrypted_request.to_xml)
103
- encrypted_request = encrypted_request.root
104
- @template.at_css('pkif|CreateCertificateIn').add_child(encrypted_request)
105
-
106
- @template
107
- end
108
-
109
- def add_encrypted_generic_request_to_soap(encrypted_request)
110
- encrypted_request = Nokogiri::XML(encrypted_request.to_xml)
111
- encrypted_request = encrypted_request.root
112
- encrypted_request = Base64.encode64(encrypted_request.to_xml)
113
- @template.at_css('bxd|ApplicationRequest').add_child(encrypted_request)
114
-
115
- @template
116
- end
117
-
118
- def add_bank_certificate_body_to_soap
119
- ar = @ar.to_nokogiri
120
-
121
- ar = ar.at_css('elem|GetBankCertificateRequest')
122
- @template.at_css('pkif|GetBankCertificateIn').add_child(ar)
123
-
124
- @template
125
- end
126
-
127
- def request_id
128
- SecureRandom.hex(5)
129
- end
130
132
 
131
133
  end
132
134
  end