sepafm 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +35 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE +8 -0
  6. data/README.md +236 -0
  7. data/Rakefile +10 -0
  8. data/lib/danske_get_bank_certificate_test.rb +15 -0
  9. data/lib/sepa/application_request.rb +182 -0
  10. data/lib/sepa/application_response.rb +123 -0
  11. data/lib/sepa/client.rb +79 -0
  12. data/lib/sepa/danske_testing/keys/danske_encryption.crt +24 -0
  13. data/lib/sepa/filedescriptor.rb +7 -0
  14. data/lib/sepa/filetypeservice.rb +6 -0
  15. data/lib/sepa/nordea_testing/keys/CSR.csr +0 -0
  16. data/lib/sepa/nordea_testing/keys/nordea.crt +27 -0
  17. data/lib/sepa/nordea_testing/keys/nordea.key +19 -0
  18. data/lib/sepa/nordea_testing/response/content_053.xml +998 -0
  19. data/lib/sepa/nordea_testing/response/content_054.xml +1 -0
  20. data/lib/sepa/nordea_testing/response/download_file_response.xml +14 -0
  21. data/lib/sepa/nordea_testing/response/download_filelist_response.xml +14 -0
  22. data/lib/sepa/nordea_testing/response/get_user_info_response.xml +14 -0
  23. data/lib/sepa/nordea_testing/response/upload_file_response.xml +14 -0
  24. data/lib/sepa/response.rb +177 -0
  25. data/lib/sepa/sender_verifier.rb +15 -0
  26. data/lib/sepa/signature.rb +7 -0
  27. data/lib/sepa/soap_builder.rb +395 -0
  28. data/lib/sepa/soap_danske.rb +47 -0
  29. data/lib/sepa/soap_nordea.rb +68 -0
  30. data/lib/sepa/userfiletype.rb +16 -0
  31. data/lib/sepa/version.rb +3 -0
  32. data/lib/sepa/wsdl/wsdl_danske.xml +234 -0
  33. data/lib/sepa/wsdl/wsdl_danske_cert.xml +280 -0
  34. data/lib/sepa/wsdl/wsdl_nordea.xml +234 -0
  35. data/lib/sepa/wsdl/wsdl_nordea_cert.xml +187 -0
  36. data/lib/sepa/xml_parser.rb +291 -0
  37. data/lib/sepa/xml_schemas/application_request.xsd +135 -0
  38. data/lib/sepa/xml_schemas/application_response.xsd +311 -0
  39. data/lib/sepa/xml_schemas/cert_application_request.xsd +107 -0
  40. data/lib/sepa/xml_schemas/danske_pki.xsd +334 -0
  41. data/lib/sepa/xml_schemas/oasis-200401-wss-wssecurity-secext-1.0.xsd +195 -0
  42. data/lib/sepa/xml_schemas/oasis-200401-wss-wssecurity-utility-1.0.xsd +108 -0
  43. data/lib/sepa/xml_schemas/soap.xsd +126 -0
  44. data/lib/sepa/xml_schemas/wsdl.xml +310 -0
  45. data/lib/sepa/xml_schemas/xml.xsd +287 -0
  46. data/lib/sepa/xml_schemas/xmldsig-core-schema.xsd +318 -0
  47. data/lib/sepa/xml_templates/application_request/create_certificate.xml +10 -0
  48. data/lib/sepa/xml_templates/application_request/danske_get_bank_certificate.xml +10 -0
  49. data/lib/sepa/xml_templates/application_request/download_file.xml +32 -0
  50. data/lib/sepa/xml_templates/application_request/download_file_list.xml +29 -0
  51. data/lib/sepa/xml_templates/application_request/get_certificate.xml +10 -0
  52. data/lib/sepa/xml_templates/application_request/get_user_info.xml +26 -0
  53. data/lib/sepa/xml_templates/application_request/upload_file.xml +29 -0
  54. data/lib/sepa/xml_templates/soap/create_certificate.xml +15 -0
  55. data/lib/sepa/xml_templates/soap/danske_get_bank_certificate.xml +14 -0
  56. data/lib/sepa/xml_templates/soap/download_file.xml +16 -0
  57. data/lib/sepa/xml_templates/soap/download_file_list.xml +16 -0
  58. data/lib/sepa/xml_templates/soap/get_certificate.xml +13 -0
  59. data/lib/sepa/xml_templates/soap/get_user_info.xml +16 -0
  60. data/lib/sepa/xml_templates/soap/header.xml +37 -0
  61. data/lib/sepa/xml_templates/soap/upload_file.xml +16 -0
  62. data/lib/sepa.rb +21 -0
  63. data/lib/sepa_client_testing_mika.rb +32 -0
  64. data/lib/sepa_client_testing_tiere.rb +80 -0
  65. data/sepa.gemspec +29 -0
  66. data/test/sepa/application_request_test.rb +423 -0
  67. data/test/sepa/application_response_test.rb +238 -0
  68. data/test/sepa/cert_application_request_test.rb +99 -0
  69. data/test/sepa/client_test.rb +425 -0
  70. data/test/sepa/danske_test_keys/danskeroot.pem +25 -0
  71. data/test/sepa/danske_test_keys/encryption_pkcs.csr +0 -0
  72. data/test/sepa/danske_test_keys/signing_key.pem +27 -0
  73. data/test/sepa/danske_test_keys/signing_pkcs.csr +0 -0
  74. data/test/sepa/nordea_cert_request_soap_builder_test.rb +112 -0
  75. data/test/sepa/nordea_generic_soap_builder_test.rb +427 -0
  76. data/test/sepa/nordea_test_keys/nordea.crt +27 -0
  77. data/test/sepa/nordea_test_keys/nordea.key +19 -0
  78. data/test/sepa/nordea_test_keys/root_cert.cer +0 -0
  79. data/test/sepa/nordea_test_keys/testcert.csr +0 -0
  80. data/test/sepa/response_test.rb +269 -0
  81. data/test/sepa/sepa_test.rb +20 -0
  82. data/test/sepa/test_files/invalid.wsdl +1 -0
  83. data/test/sepa/test_files/test_responses/df.xml +20 -0
  84. data/test/sepa/test_files/test_responses/dfl.xml +20 -0
  85. data/test/sepa/test_files/test_responses/gui.xml +20 -0
  86. data/test/sepa/test_files/test_responses/uf.xml +20 -0
  87. data/test/sepa/user_file_type_test.rb +21 -0
  88. data/test/sepa/xml_parser_test.rb +73 -0
  89. data/test/test_helper.rb +9 -0
  90. metadata +256 -0
@@ -0,0 +1,423 @@
1
+ require File.expand_path('../../test_helper.rb', __FILE__)
2
+
3
+ class TestApplicationRequest < MiniTest::Test
4
+ def setup
5
+ keys_path = File.expand_path('../nordea_test_keys', __FILE__)
6
+
7
+ @xml_templates_path = File.expand_path(
8
+ '../../../lib/sepa/xml_templates/application_request', __FILE__
9
+ )
10
+
11
+ @schemas_path = File.expand_path('../../../lib/sepa/xml_schemas',__FILE__)
12
+
13
+ @private_key = OpenSSL::PKey::RSA.new(File.read("#{keys_path}/nordea.key"))
14
+ @cert = OpenSSL::X509::Certificate.new(File.read("#{keys_path}/nordea.crt"))
15
+ certplain = "-----BEGIN CERTIFICATE-----
16
+ MIIDwTCCAqmgAwIBAgIEAX1JuTANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJT
17
+ RTEeMBwGA1UEChMVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMR8wHQYDVQQDExZOb3Jk
18
+ ZWEgQ29ycG9yYXRlIENBIDAxMRQwEgYDVQQFEws1MTY0MDYtMDEyMDAeFw0xMzA1
19
+ MDIxMjI2MzRaFw0xNTA1MDIxMjI2MzRaMEQxCzAJBgNVBAYTAkZJMSAwHgYDVQQD
20
+ DBdOb3JkZWEgRGVtbyBDZXJ0aWZpY2F0ZTETMBEGA1UEBRMKNTc4MDg2MDIzODCB
21
+ nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwtFEfAtbJuGzQwwRumZkvYh2BjGY
22
+ VsAMUeiKtOne3bZSeisfCq+TXqL1gI9LofyeAQ9I/sDm6tL80yrD5iaSUqVm6A73
23
+ 9MsmpW/iyZcVf7ms8xAN51ESUgN6akwZCU9pH62ngJDj2gUsktY0fpsoVsARdrvO
24
+ Fk0fTSUXKWd6LbcCAwEAAaOCAR0wggEZMAkGA1UdEwQCMAAwEQYDVR0OBAoECEBw
25
+ 2cj7+XMAMBMGA1UdIAQMMAowCAYGKoVwRwEDMBMGA1UdIwQMMAqACEALddbbzwun
26
+ MDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3Aubm9yZGVh
27
+ LnNlL0NDQTAxMA4GA1UdDwEB/wQEAwIFoDCBhQYDVR0fBH4wfDB6oHigdoZ0bGRh
28
+ cCUzQS8vbGRhcC5uYi5zZS9jbiUzRE5vcmRlYStDb3Jwb3JhdGUrQ0ErMDElMkNv
29
+ JTNETm9yZGVhK0JhbmsrQUIrJTI4cHVibCUyOSUyQ2MlM0RTRSUzRmNlcnRpZmlj
30
+ YXRlcmV2b2NhdGlvbmxpc3QwDQYJKoZIhvcNAQEFBQADggEBACLUPB1Gmq6286/s
31
+ ROADo7N+w3eViGJ2fuOTLMy4R0UHOznKZNsuk4zAbS2KycbZsE5py4L8o+IYoaS8
32
+ 8YHtEeckr2oqHnPpz/0Eg7wItj8Ad+AFWJqzbn6Hu/LQhlnl5JEzXzl3eZj9oiiJ
33
+ 1q/2CGXvFomY7S4tgpWRmYULtCK6jode0NhgNnAgOI9uy76pSS16aDoiQWUJqQgV
34
+ ydowAnqS9h9aQ6gedwbOdtkWmwKMDVXU6aRz9Gvk+JeYJhtpuP3OPNGbbC5L7NVd
35
+ no+B6AtwxmG3ozd+mPcMeVuz6kKLAmQyIiBSrRNa5OrTkq/CUzxO9WUgTnm/Sri7
36
+ zReR6mU=
37
+ -----END CERTIFICATE-----"
38
+ pkeyplain = "-----BEGIN PRIVATE KEY-----
39
+ MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBAMLRRHwLWybhs0MM
40
+ EbpmZL2IdgYxmFbADFHoirTp3t22UnorHwqvk16i9YCPS6H8ngEPSP7A5urS/NMq
41
+ w+YmklKlZugO9/TLJqVv4smXFX+5rPMQDedRElIDempMGQlPaR+tp4CQ49oFLJLW
42
+ NH6bKFbAEXa7zhZNH00lFylnei23AgMBAAECgYEAqt912/7x4jaQTrxlSELLFVp9
43
+ eo1BesVTiPwXvPpsGbbyvGjZ/ztkXNs9zZbh1aCGzZMkiR2U7F5GlsiprlIif4cF
44
+ 6Xz7rCjaAs7iDRt9PjhjVuqNGR2I+VIIlbQ9XWFJ3lJFW3v7TIZ8JbLnn0XOFz+Z
45
+ BBSSGTK1zTNh4TBQtjECQQDe5M3uu9m4RwSw9R6GaDw/IFQZgr0oWSv0WIjRwvwW
46
+ nFnSX2lbkNAjulP0daGsmn7vxIpqZxPxwcrU4wFqTF5dAkEA38DnbCm3YfogzwLH
47
+ Nre2hBmGqjWarhtxqtRarrkgnmOd8W0Z1Hb1dSHrliUSVSrINbK5ZdEV15Rpu7VD
48
+ OePzIwJAPMslS+8alANyyR0iJUC65fDYX1jkZOPldDDNqIDJJxWf/hwd7WaTDpuc
49
+ mHmZDi3ZX2Y45oqUywSzYNtFoIuR1QJAZYUZuyqmSK77SdGB36K1DfSi9AFEQDC1
50
+ fwPAbTwTv6mFFPAiYxLiRZXxVPtW+QtjMXH4ymh2V4y/+GnCqbZyLwJBAJQSDAME
51
+ Sn4Uz7Zjk3UrBIbMYEv0u2mcCypwsb0nGE5/gzDPjGE9cxWW+rXARIs+sNQVClnh
52
+ 45nhdfYxOjgYff0=
53
+ -----END PRIVATE KEY-----"
54
+ @params = {
55
+ bank: :nordea,
56
+ private_key_plain: pkeyplain,
57
+ cert_plain: certplain,
58
+ command: :download_file,
59
+ customer_id: '11111111',
60
+ environment: 'PRODUCTION',
61
+ status: 'NEW',
62
+ target_id: '11111111A1',
63
+ language: 'FI',
64
+ file_type: 'TITO',
65
+ content: Base64.encode64("haisuli"),
66
+ file_reference: "11111111A12006030329501800000014"
67
+ }
68
+
69
+ #@ar_file = Sepa::ApplicationRequest.new(@params)
70
+ @ar_file = Sepa::SoapBuilder.new(@params).get_ar_as_base64
71
+
72
+ @params[:command] = :get_user_info
73
+ #@ar_get = Sepa::ApplicationRequest.new(@params)
74
+ @ar_get = Sepa::SoapBuilder.new(@params).get_ar_as_base64
75
+
76
+ @params[:command] = :download_file_list
77
+ #@ar_list = Sepa::ApplicationRequest.new(@params)
78
+ @ar_list = Sepa::SoapBuilder.new(@params).get_ar_as_base64
79
+
80
+ @params[:command] = :upload_file
81
+ #@ar_up = Sepa::ApplicationRequest.new(@params)
82
+ @ar_up = Sepa::SoapBuilder.new(@params).get_ar_as_base64
83
+
84
+ @doc_file = Nokogiri::XML(Base64.decode64(@ar_file))
85
+ @doc_get = Nokogiri::XML(Base64.decode64(@ar_get))
86
+ @doc_list = Nokogiri::XML(Base64.decode64(@ar_list))
87
+ @doc_up = Nokogiri::XML(Base64.decode64(@ar_up))
88
+ end
89
+
90
+ # Just to make sure that the xml templates are unmodified because
91
+ # the application logic is designed for exactly these templates
92
+ def test_xml_templates_are_unmodified
93
+ sha1 = OpenSSL::Digest::SHA1.new
94
+
95
+ get_user_info_template = File.read(
96
+ "#{@xml_templates_path}/get_user_info.xml"
97
+ )
98
+
99
+ download_file_list_template = File.read(
100
+ "#{@xml_templates_path}/download_file_list.xml"
101
+ )
102
+
103
+ download_file_template = File.read(
104
+ "#{@xml_templates_path}/download_file.xml"
105
+ )
106
+
107
+ upload_file_template = File.read(
108
+ "#{@xml_templates_path}/upload_file.xml"
109
+ )
110
+
111
+ get_user_info_digest = Base64.encode64(
112
+ sha1.digest(get_user_info_template)
113
+ ).strip
114
+
115
+ sha1.reset
116
+
117
+ download_file_list_digest = Base64.encode64(
118
+ sha1.digest(download_file_list_template)
119
+ ).strip
120
+
121
+ sha1.reset
122
+
123
+ download_file_digest = sha1.digest(download_file_template)
124
+
125
+ sha1.reset
126
+
127
+ upload_file_digest = sha1.digest(upload_file_template)
128
+
129
+ assert_equal get_user_info_digest, "LW5J5R7SnPFPurAa2pM7weTWL1Y="
130
+
131
+ assert_equal download_file_list_digest.strip,
132
+ "dYtf4lOP1TXfXPVjYLvaTozhVrg="
133
+
134
+ assert_equal Base64.encode64(download_file_digest).strip,
135
+ "lY+8u+BhXlQmUyQiOiXcUfCUikc="
136
+
137
+ assert_equal Base64.encode64(upload_file_digest).strip,
138
+ "zRQTrNHkq4OLSX3u3ogxU05RJsI="
139
+ end
140
+
141
+ def test_schemas_are_unmodified
142
+ sha1 = OpenSSL::Digest::SHA1.new
143
+
144
+ ar_schema = File.read(
145
+ "#{@schemas_path}/application_request.xsd"
146
+ )
147
+
148
+ xmldsig_schema = File.read(
149
+ "#{@schemas_path}/xmldsig-core-schema.xsd"
150
+ )
151
+
152
+ ar_schema_digest = sha1.digest(ar_schema)
153
+
154
+ sha1.reset
155
+
156
+ xmldsig_schema_digest = sha1.digest(xmldsig_schema)
157
+
158
+ assert_equal Base64.encode64(ar_schema_digest).strip,
159
+ "1O24A7+/6S7CFYVlhH1jEZh1ARs="
160
+
161
+ assert_equal Base64.encode64(xmldsig_schema_digest).strip,
162
+ "bmG0+2KykgkLeWsXsl6CFbyo4Yc="
163
+ end
164
+
165
+ def test_ar_should_initialize_with_proper_params
166
+ assert Sepa::SoapBuilder.new(@params)
167
+ end
168
+
169
+ def test_should_get_key_error_if_private_key_plain_missing
170
+ @params.delete(:private_key_plain)
171
+
172
+ assert_raises(ArgumentError) do
173
+ Sepa::SoapBuilder.new(@params)
174
+ end
175
+ end
176
+
177
+ def test_should_get_key_error_if_cert_plain_missing
178
+ @params.delete(:cert_plain)
179
+
180
+ assert_raises(ArgumentError) do
181
+ Sepa::SoapBuilder.new(@params)
182
+ end
183
+ end
184
+
185
+ def test_should_get_key_error_if_command_missing
186
+ @params.delete(:command)
187
+
188
+ assert_raises(ArgumentError) do
189
+ Sepa::SoapBuilder.new(@params)
190
+ end
191
+ end
192
+
193
+ def test_should_get_key_error_if_customer_id_missing
194
+ @params.delete(:customer_id)
195
+
196
+ assert_raises(ArgumentError) do
197
+ Sepa::SoapBuilder.new(@params)
198
+ end
199
+ end
200
+
201
+ def test_should_get_key_error_if_environment_missing
202
+ @params.delete(:environment)
203
+
204
+ assert_raises(ArgumentError) do
205
+ Sepa::SoapBuilder.new(@params)
206
+ end
207
+ end
208
+
209
+ def test_should_have_customer_id_set_in_with_all_commands
210
+ assert_equal @doc_file.at_css("CustomerId").content, @params[:customer_id]
211
+ assert_equal @doc_get.at_css("CustomerId").content, @params[:customer_id]
212
+ assert_equal @doc_list.at_css("CustomerId").content, @params[:customer_id]
213
+ assert_equal @doc_up.at_css("CustomerId").content, @params[:customer_id]
214
+ end
215
+
216
+ def test_should_have_timestamp_set_properly_with_all_commands
217
+ timestamp_file = Time.strptime(@doc_file.at_css("Timestamp").content,
218
+ '%Y-%m-%dT%H:%M:%S%z')
219
+
220
+ timestamp_get = Time.strptime(@doc_get.at_css("Timestamp").content,
221
+ '%Y-%m-%dT%H:%M:%S%z')
222
+
223
+ timestamp_list = Time.strptime(@doc_list.at_css("Timestamp").content,
224
+ '%Y-%m-%dT%H:%M:%S%z')
225
+
226
+ timestamp_up = Time.strptime(@doc_up.at_css("Timestamp").content,
227
+ '%Y-%m-%dT%H:%M:%S%z')
228
+
229
+ assert timestamp_file <= Time.now && timestamp_file > (Time.now - 60),
230
+ "Timestamp was not set correctly"
231
+
232
+ assert timestamp_get <= Time.now && timestamp_get > (Time.now - 60),
233
+ "Timestamp was not set correctly"
234
+
235
+ assert timestamp_list <= Time.now && timestamp_list > (Time.now - 60),
236
+ "Timestamp was not set correctly"
237
+
238
+ assert timestamp_up <= Time.now && timestamp_up > (Time.now - 60),
239
+ "Timestamp was not set correctly"
240
+ end
241
+
242
+ def test_should_have_command_set_when_get_user_info
243
+
244
+ assert_equal @doc_get.at_css("Command").content, "GetUserInfo"
245
+ end
246
+
247
+ def test_should_have_command_set_when_download_file_list
248
+ assert_equal @doc_list.at_css("Command").content, "DownloadFileList"
249
+ end
250
+
251
+ def test_should_have_command_set_when_download_file
252
+ assert_equal @doc_file.at_css("Command").content, "DownloadFile"
253
+ end
254
+
255
+ def test_should_have_command_set_when_upload_file
256
+ assert_equal @doc_up.at_css("Command").content, "UploadFile"
257
+ end
258
+
259
+ def test_should_have_environment_set_with_all_commands
260
+ assert_equal @doc_file.at_css("Environment").content, @params[:environment]
261
+ assert_equal @doc_get.at_css("Environment").content, @params[:environment]
262
+ assert_equal @doc_list.at_css("Environment").content, @params[:environment]
263
+ assert_equal @doc_up.at_css("Environment").content, @params[:environment]
264
+ end
265
+
266
+ def test_should_have_software_id_set_with_all_commands
267
+ assert_equal @doc_file.at_css("SoftwareId").content,
268
+ "Sepa Transfer Library version " + Sepa::VERSION
269
+
270
+ assert_equal @doc_get.at_css("SoftwareId").content,
271
+ "Sepa Transfer Library version " + Sepa::VERSION
272
+
273
+ assert_equal @doc_list.at_css("SoftwareId").content,
274
+ "Sepa Transfer Library version " + Sepa::VERSION
275
+
276
+ assert_equal @doc_up.at_css("SoftwareId").content,
277
+ "Sepa Transfer Library version " + Sepa::VERSION
278
+ end
279
+
280
+ def test_should_have_status_set_when_download_file_list
281
+ assert_equal @doc_list.at_css("Status").content, @params[:status]
282
+ end
283
+
284
+ def test_should_have_status_set_when_download_file
285
+ assert_equal @doc_file.at_css("Status").content, @params[:status]
286
+ end
287
+
288
+ def test_should_not_have_status_set_when_get_user_info
289
+ refute @doc_get.at_css("Status")
290
+ end
291
+
292
+ def test_should_not_have_status_set_when_upload_file
293
+ refute @doc_up.at_css("Status")
294
+ end
295
+
296
+ def test_should_have_target_id_set_when_download_file_list
297
+ assert_equal @doc_list.at_css("TargetId").content, @params[:target_id]
298
+ end
299
+
300
+ def test_should_have_target_id_set_when_download_file
301
+ assert_equal @doc_file.at_css("TargetId").content, @params[:target_id]
302
+ end
303
+
304
+ def test_should_not_have_target_id_set_when_get_user_info
305
+ refute @doc_get.at_css("TargetId")
306
+ end
307
+
308
+ def test_should_have_file_type_set_when_download_file_list
309
+ assert_equal @doc_list.at_css("FileType").content, @params[:file_type]
310
+ end
311
+
312
+ def test_should_have_file_type_set_when_download_file
313
+ assert_equal @doc_file.at_css("FileType").content, @params[:file_type]
314
+ end
315
+
316
+ def test_should_have_file_type_set_when_upload_file
317
+ assert_equal @doc_up.at_css("FileType").content, @params[:file_type]
318
+ end
319
+
320
+ def test_should_not_have_file_type_set_when_get_user_info
321
+ refute @doc_get.at_css("FileType")
322
+ end
323
+
324
+ def test_should_have_file_reference_set_when_download_file
325
+ assert_equal @doc_file.at_css("FileReference").content,
326
+ @params[:file_reference]
327
+ end
328
+
329
+ def test_should_not_have_file_ref_when_download_file_list
330
+ refute @doc_list.at_css("FileReference")
331
+ end
332
+
333
+ def test_should_not_have_file_ref_when_get_user_info
334
+ refute @doc_get.at_css("FileReference")
335
+ end
336
+
337
+ def test_should_not_have_file_ref_when_upload_file
338
+ refute @doc_up.at_css("FileReference")
339
+ end
340
+
341
+ def test_should_have_content_when_upload_file
342
+ assert_equal @doc_up.at_css("Content").content,
343
+ Base64.encode64(@params[:content])
344
+ end
345
+
346
+ def test_should_not_have_content_when_download_file_list
347
+ refute @doc_list.at_css("Content")
348
+ end
349
+
350
+ def test_should_not_have_content_when_download_file
351
+ refute @doc_file.at_css("Content")
352
+ end
353
+
354
+ def test_should_not_have_content_when_get_user_info
355
+ refute @doc_get.at_css("Content")
356
+ end
357
+
358
+ def test_should_raise_argument_error_with_invalid_command
359
+ assert_raises(ArgumentError) do
360
+ @params[:command] = :wrong_kind_of_command
361
+ ar = Sepa::ApplicationRequest.new(@params)
362
+ doc = ar.get_as_base64
363
+ end
364
+ end
365
+
366
+ def test_digest_is_calculatd_correctly
367
+ calculated_digest = @doc_file.at_css(
368
+ "dsig|DigestValue", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#'
369
+ ).content
370
+
371
+ # Remove signature for calculating digest
372
+ @doc_file.at_css(
373
+ "dsig|Signature", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#'
374
+ ).remove
375
+
376
+ # Calculate digest
377
+ sha1 = OpenSSL::Digest::SHA1.new
378
+ actual_digest = Base64.encode64(sha1.digest(@doc_file.canonicalize))
379
+
380
+ # And then make sure the two are equal
381
+ assert_equal calculated_digest.strip, actual_digest.strip
382
+ end
383
+
384
+ def test_signature_is_constructed_correctly
385
+ #private_key = @params.fetch(:private_key)
386
+
387
+ signed_info_node = @doc_file.at_css(
388
+ "dsig|SignedInfo", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#')
389
+
390
+ # The value of the signature node in the constructed ar
391
+ calculated_signature = @doc_file.at_css(
392
+ "dsig|SignatureValue", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#'
393
+ ).content
394
+
395
+ # Calculate the actual signature
396
+ sha1 = OpenSSL::Digest::SHA1.new
397
+ actual_signature = Base64.encode64(@private_key.sign(
398
+ sha1, signed_info_node.canonicalize))
399
+
400
+ # And then of course assert the two are equal
401
+ assert_equal calculated_signature, actual_signature
402
+ end
403
+
404
+ def test_certificate_is_added_correctly
405
+ added_cert = @doc_file.at_css(
406
+ "dsig|X509Certificate", 'dsig' => 'http://www.w3.org/2000/09/xmldsig#'
407
+ ).content
408
+
409
+ actual_cert = @params.fetch(:cert).to_s
410
+ actual_cert = actual_cert.split('-----BEGIN CERTIFICATE-----')[1]
411
+ actual_cert = actual_cert.split('-----END CERTIFICATE-----')[0]
412
+ actual_cert.gsub!(/\s+/, "")
413
+
414
+ assert_equal added_cert, actual_cert
415
+ end
416
+
417
+ def test_should_validate_against_schema
418
+ Dir.chdir(@schemas_path) do
419
+ xsd = Nokogiri::XML::Schema(IO.read('application_request.xsd'))
420
+ assert xsd.valid?(@doc_file)
421
+ end
422
+ end
423
+ end
@@ -0,0 +1,238 @@
1
+ require File.expand_path('../../test_helper.rb', __FILE__)
2
+
3
+ class ApplicationResponseTest < MiniTest::Test
4
+ def setup
5
+ keys_path = File.expand_path('../nordea_test_keys', __FILE__)
6
+
7
+ @root_cert = OpenSSL::X509::Certificate.new File.read(
8
+ "#{keys_path}/root_cert.cer"
9
+ )
10
+
11
+ @not_root_cert = OpenSSL::X509::Certificate.new File.read(
12
+ "#{keys_path}/nordea.crt"
13
+ )
14
+
15
+ responses_path = File.expand_path('../test_files/test_responses', __FILE__)
16
+
17
+ @dfl = Nokogiri::XML(File.read("#{responses_path}/dfl.xml"))
18
+ @dfl = Sepa::Response.new(@dfl).application_response
19
+
20
+ @uf = Nokogiri::XML(File.read("#{responses_path}/uf.xml"))
21
+ @uf = Sepa::Response.new(@uf).application_response
22
+
23
+ @df = Nokogiri::XML(File.read("#{responses_path}/df.xml"))
24
+ @df = Sepa::Response.new(@df).application_response
25
+
26
+ @gui = Nokogiri::XML(File.read("#{responses_path}/gui.xml"))
27
+ @gui = Sepa::Response.new(@gui).application_response
28
+
29
+ @dfl_ar = Sepa::ApplicationResponse.new(@dfl)
30
+ @uf_ar = Sepa::ApplicationResponse.new(@uf)
31
+ @df_ar = Sepa::ApplicationResponse.new(@df)
32
+ @gui_ar = Sepa::ApplicationResponse.new(@gui)
33
+ end
34
+
35
+ def test_should_initialize_with_proper_params
36
+ assert Sepa::ApplicationResponse.new(@dfl)
37
+ assert Sepa::ApplicationResponse.new(@uf)
38
+ assert Sepa::ApplicationResponse.new(@df)
39
+ assert Sepa::ApplicationResponse.new(@gui)
40
+ end
41
+
42
+ def test_should_complain_if_initialized_with_something_not_nokogiri_xml
43
+ assert_raises(ArgumentError) { Sepa::ApplicationResponse.new("Jees") }
44
+ end
45
+
46
+ def test_should_complain_if_ar_not_valid_against_schema
47
+ assert_raises(ArgumentError) do
48
+ Sepa::ApplicationResponse.new(Nokogiri::XML("<ar>text</ar>"))
49
+ end
50
+ end
51
+
52
+ def test_proper_dfl_hash_check_should_verify
53
+ assert @dfl_ar.hashes_match?
54
+ end
55
+
56
+ def test_proper_uf_hash_check_should_verify
57
+ assert @uf_ar.hashes_match?
58
+ end
59
+
60
+ def test_proper_df_hash_check_should_verify
61
+ assert @df_ar.hashes_match?
62
+ end
63
+
64
+ def test_proper_gui_hash_check_should_verify
65
+ assert @gui_ar.hashes_match?
66
+ end
67
+
68
+ def test_invalid_dfl_hash_check_should_not_verify
69
+ customer_id_node = @dfl.at_css('c2b|CustomerId')
70
+ customer_id_node.content = customer_id_node.content[0..-2]
71
+
72
+ refute Sepa::ApplicationResponse.new(@dfl).hashes_match?
73
+ end
74
+
75
+ def test_invalid_uf_hash_check_should_not_verify
76
+ timestamp_node = @uf.at_css('c2b|Timestamp')
77
+ timestamp_node.content = Time.now.iso8601
78
+
79
+ refute Sepa::ApplicationResponse.new(@uf).hashes_match?
80
+ end
81
+
82
+ def test_invalid_df_hash_check_should_not_verify
83
+ digest_value_node = @df.at_css(
84
+ 'xmlns|DigestValue',
85
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
86
+ )
87
+
88
+ digest_value_node.content = digest_value_node.content[4..-1]
89
+
90
+ refute Sepa::ApplicationResponse.new(@df).hashes_match?
91
+ end
92
+
93
+ def test_invalid_gui_hash_check_should_not_verify
94
+ digest_value_node = @gui.at_css(
95
+ 'xmlns|DigestValue',
96
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
97
+ )
98
+
99
+ digest_value_node.content = '1234' + digest_value_node.content
100
+
101
+ refute Sepa::ApplicationResponse.new(@gui).hashes_match?
102
+ end
103
+
104
+ def test_proper_dfl_signature_should_verify
105
+ assert @dfl_ar.signature_is_valid?
106
+ end
107
+
108
+ def test_proper_uf_signature_should_verify
109
+ assert @uf_ar.signature_is_valid?
110
+ end
111
+
112
+ def test_proper_df_signature_should_verify
113
+ assert @df_ar.signature_is_valid?
114
+ end
115
+
116
+ def test_proper_gui_signature_should_verify
117
+ assert @gui_ar.signature_is_valid?
118
+ end
119
+
120
+ def test_corrupted_signature_in_dfl_should_fail_signature_verification
121
+ signature_node = @dfl.at_css(
122
+ 'xmlns|SignatureValue',
123
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
124
+ )
125
+
126
+ signature_node.content = signature_node.content[4..-1]
127
+
128
+ refute Sepa::ApplicationResponse.new(@dfl).signature_is_valid?
129
+ end
130
+
131
+ def test_corrupted_signature_in_uf_should_fail_signature_verification
132
+ signature_node = @uf.at_css(
133
+ 'xmlns|SignatureValue',
134
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
135
+ )
136
+
137
+ signature_node.content = signature_node.content[0..-5]
138
+
139
+ refute Sepa::ApplicationResponse.new(@uf).signature_is_valid?
140
+ end
141
+
142
+ def test_corrupted_signature_in_df_should_fail_signature_verification
143
+ signature_node = @df.at_css(
144
+ 'xmlns|SignatureValue',
145
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
146
+ )
147
+
148
+ signature_node.content = 'a' + signature_node.content[1..-1]
149
+
150
+ refute Sepa::ApplicationResponse.new(@df).signature_is_valid?
151
+ end
152
+
153
+ def test_corrupted_signature_in_gui_should_fail_signature_verification
154
+ signature_node = @gui.at_css(
155
+ 'xmlns|SignatureValue',
156
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
157
+ )
158
+
159
+ signature_node.content = 'zombi' + signature_node.content[1..-1]
160
+
161
+ refute Sepa::ApplicationResponse.new(@gui).signature_is_valid?
162
+ end
163
+
164
+ def test_should_raise_error_if_certificate_corrupted_in_dfl
165
+ cert_node = @dfl.at_css(
166
+ 'xmlns|X509Certificate',
167
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
168
+ )
169
+
170
+ cert_node.content = cert_node.content[0..-5]
171
+
172
+ assert_raises(OpenSSL::X509::CertificateError) do
173
+ Sepa::ApplicationResponse.new(@dfl).certificate
174
+ end
175
+ end
176
+
177
+ def test_should_raise_error_if_certificate_corrupted_in_uf
178
+ cert_node = @uf.at_css(
179
+ 'xmlns|X509Certificate',
180
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
181
+ )
182
+
183
+ cert_node.content = cert_node.content[4..-1]
184
+
185
+ assert_raises(OpenSSL::X509::CertificateError) do
186
+ Sepa::ApplicationResponse.new(@uf).certificate
187
+ end
188
+ end
189
+
190
+ def test_should_raise_error_if_certificate_corrupted_in_df
191
+ cert_node = @df.at_css(
192
+ 'xmlns|X509Certificate',
193
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
194
+ )
195
+
196
+ cert_node.content = "n5iw#{cert_node.content}"
197
+
198
+ assert_raises(OpenSSL::X509::CertificateError) do
199
+ Sepa::ApplicationResponse.new(@df).certificate
200
+ end
201
+ end
202
+
203
+ def test_should_raise_error_if_certificate_corrupted_in_gui
204
+ cert_node = @gui.at_css(
205
+ 'xmlns|X509Certificate',
206
+ 'xmlns' => 'http://www.w3.org/2000/09/xmldsig#'
207
+ )
208
+
209
+ cert_node.content = Base64.encode64('voivoi')
210
+
211
+ assert_raises(OpenSSL::X509::CertificateError) do
212
+ Sepa::ApplicationResponse.new(@gui).certificate
213
+ end
214
+ end
215
+
216
+ def test_cert_should_be_trusted_with_correct_root_cert
217
+ assert @dfl_ar.cert_is_trusted?(@root_cert)
218
+ assert @uf_ar.cert_is_trusted?(@root_cert)
219
+ assert @df_ar.cert_is_trusted?(@root_cert)
220
+ assert @gui_ar.cert_is_trusted?(@root_cert)
221
+ end
222
+
223
+ def test_dfl_should_fail_if_wrong_root_cert
224
+ assert_raises(SecurityError) { @dfl_ar.cert_is_trusted?(@not_root_cert) }
225
+ end
226
+
227
+ def test_uf_should_fail_if_wrong_root_cert
228
+ assert_raises(SecurityError) { @uf_ar.cert_is_trusted?(@not_root_cert) }
229
+ end
230
+
231
+ def test_df_should_fail_if_wrong_root_cert
232
+ assert_raises(SecurityError) { @df_ar.cert_is_trusted?(@not_root_cert) }
233
+ end
234
+
235
+ def test_gui_should_fail_if_wrong_root_cert
236
+ assert_raises(SecurityError) { @gui_ar.cert_is_trusted?(@not_root_cert) }
237
+ end
238
+ end