sepafm 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +14 -30
- data/.ruby-version +1 -1
- data/.travis.yml +15 -0
- data/Gemfile +1 -1
- data/LICENSE +16 -4
- data/README.md +180 -319
- data/Rakefile +7 -2
- data/lib/sepa/application_request.rb +100 -131
- data/lib/sepa/application_response.rb +28 -84
- data/lib/sepa/attribute_checks.rb +169 -0
- data/lib/sepa/banks/danske/danske_response.rb +19 -0
- data/lib/sepa/banks/danske/soap_danske.rb +132 -0
- data/lib/sepa/banks/nordea/nordea_response.rb +20 -0
- data/lib/sepa/banks/nordea/soap_nordea.rb +51 -0
- data/lib/sepa/client.rb +72 -60
- data/lib/sepa/error_messages.rb +15 -0
- data/lib/sepa/response.rb +88 -85
- data/lib/sepa/soap_builder.rb +51 -341
- data/lib/sepa/utilities.rb +132 -0
- data/lib/sepa/version.rb +1 -1
- data/lib/sepa/xml_schemas/PKIFactory.xsd +334 -0
- data/lib/sepa/xml_schemas/xml_id.xsd +9 -0
- data/lib/sepa/xml_templates/application_request/create_certificate.xml +15 -10
- data/lib/sepa/xml_templates/application_request/danske_get_bank_certificate.xml +13 -9
- data/lib/sepa/xml_templates/application_request/download_file.xml +32 -30
- data/lib/sepa/xml_templates/application_request/download_file_list.xml +29 -27
- data/lib/sepa/xml_templates/application_request/encrypted_request.xml +22 -0
- data/lib/sepa/xml_templates/application_request/get_certificate.xml +9 -8
- data/lib/sepa/xml_templates/application_request/get_user_info.xml +26 -24
- data/lib/sepa/xml_templates/application_request/upload_file.xml +29 -27
- data/lib/sepa/xml_templates/soap/create_certificate.xml +17 -15
- data/lib/sepa/xml_templates/soap/danske_get_bank_certificate.xml +15 -13
- data/lib/sepa/xml_templates/soap/download_file.xml +19 -15
- data/lib/sepa/xml_templates/soap/download_file_list.xml +19 -15
- data/lib/sepa/xml_templates/soap/get_certificate.xml +2 -1
- data/lib/sepa/xml_templates/soap/get_user_info.xml +19 -15
- data/lib/sepa/xml_templates/soap/header.xml +48 -37
- data/lib/sepa/xml_templates/soap/upload_file.xml +19 -15
- data/lib/sepafm.rb +20 -18
- data/{sepa.gemspec → sepafm.gemspec} +10 -9
- data/test/sepa/banks/danske/danske_cert_response_test.rb +52 -0
- data/test/sepa/banks/danske/danske_cert_soap_builder_test.rb +100 -0
- data/test/sepa/banks/danske/danske_generic_soap_builder_test.rb +278 -0
- data/test/sepa/banks/danske/danske_get_bank_cert_test.rb +111 -0
- data/{lib/sepa/danske_testing/keys/danske_encryption.crt → test/sepa/banks/danske/keys/bank_encryption_cert.pem} +0 -0
- data/test/sepa/{danske_test_keys/danskeroot.pem → banks/danske/keys/bank_root_cert.pem} +1 -1
- data/test/sepa/banks/danske/keys/bank_signing_cert.pem +24 -0
- data/test/sepa/banks/danske/keys/danske_encryption.crt +24 -0
- data/test/sepa/banks/danske/keys/enc_private_key.pem +27 -0
- data/test/sepa/{danske_test_keys → banks/danske/keys}/encryption_pkcs.csr +0 -0
- data/test/sepa/banks/danske/keys/own_enc_cert.pem +21 -0
- data/test/sepa/banks/danske/keys/own_signing_cert.pem +22 -0
- data/test/sepa/{danske_test_keys → banks/danske/keys}/signing_key.pem +0 -0
- data/test/sepa/{danske_test_keys → banks/danske/keys}/signing_pkcs.csr +0 -0
- data/test/sepa/banks/danske/keys/signing_private_key.pem +27 -0
- data/test/sepa/banks/danske/responses/create_cert.xml +38 -0
- data/test/sepa/banks/danske/responses/get_bank_cert.xml +37 -0
- data/{lib/sepa/nordea_testing → test/sepa/banks/nordea}/keys/nordea.crt +0 -4
- data/test/sepa/{nordea_test_keys → banks/nordea/keys}/nordea.key +0 -3
- data/test/sepa/{nordea_test_keys → banks/nordea/keys}/root_cert.cer +0 -0
- data/test/sepa/{nordea_test_keys → banks/nordea/keys}/testcert.csr +0 -0
- data/test/sepa/banks/nordea/nordea_application_request_test.rb +252 -0
- data/test/sepa/{application_response_test.rb → banks/nordea/nordea_application_response_test.rb} +40 -46
- data/test/sepa/banks/nordea/nordea_cert_application_request_test.rb +72 -0
- data/test/sepa/banks/nordea/nordea_cert_request_soap_builder_test.rb +65 -0
- data/test/sepa/banks/nordea/nordea_generic_soap_builder_test.rb +280 -0
- data/test/sepa/banks/nordea/nordea_response_test.rb +116 -0
- data/test/sepa/banks/nordea/responses/df_ktl.xml +45 -0
- data/test/sepa/{test_files/test_responses/df.xml → banks/nordea/responses/df_tito.xml} +1 -1
- data/test/sepa/{test_files/test_responses → banks/nordea/responses}/dfl.xml +0 -0
- data/test/sepa/banks/nordea/responses/gbc.xml +15 -0
- data/test/sepa/banks/nordea/responses/gc.xml +49 -0
- data/test/sepa/{test_files/test_responses → banks/nordea/responses}/gui.xml +0 -0
- data/test/sepa/{test_files/test_responses → banks/nordea/responses}/uf.xml +0 -0
- data/test/sepa/client_test.rb +156 -302
- data/test/sepa/fixtures.rb +214 -0
- data/test/sepa/sepa_test.rb +3 -13
- data/test/sepa/test_files/{invalid.wsdl → invalid_wsdl.wsdl} +0 -0
- data/test/test_helper.rb +29 -3
- metadata +140 -116
- data/lib/danske_get_bank_certificate_test.rb +0 -15
- data/lib/sepa/custom_exceptions.rb +0 -2
- data/lib/sepa/filedescriptor.rb +0 -7
- data/lib/sepa/filetypeservice.rb +0 -6
- data/lib/sepa/nordea_testing/keys/CSR.csr +0 -0
- data/lib/sepa/nordea_testing/keys/nordea.key +0 -19
- data/lib/sepa/nordea_testing/response/content_053.xml +0 -998
- data/lib/sepa/nordea_testing/response/content_054.xml +0 -1
- data/lib/sepa/nordea_testing/response/download_file_response.xml +0 -14
- data/lib/sepa/nordea_testing/response/download_filelist_response.xml +0 -14
- data/lib/sepa/nordea_testing/response/get_user_info_response.xml +0 -14
- data/lib/sepa/nordea_testing/response/upload_file_response.xml +0 -14
- data/lib/sepa/payload.rb +0 -109
- data/lib/sepa/payment.rb +0 -97
- data/lib/sepa/sender_verifier.rb +0 -15
- data/lib/sepa/signature.rb +0 -7
- data/lib/sepa/soap_danske.rb +0 -47
- data/lib/sepa/soap_nordea.rb +0 -68
- data/lib/sepa/transaction.rb +0 -178
- data/lib/sepa/userfiletype.rb +0 -16
- data/lib/sepa/xml_parser.rb +0 -291
- data/lib/sepa_client_testing_mika.rb +0 -32
- data/lib/sepa_client_testing_tiere.rb +0 -257
- data/test/sepa/application_request_test.rb +0 -423
- data/test/sepa/cert_application_request_test.rb +0 -99
- data/test/sepa/nordea_cert_request_soap_builder_test.rb +0 -112
- data/test/sepa/nordea_generic_soap_builder_test.rb +0 -427
- data/test/sepa/nordea_test_keys/nordea.crt +0 -27
- data/test/sepa/payload_test.rb +0 -297
- data/test/sepa/payment_test.rb +0 -198
- data/test/sepa/response_test.rb +0 -269
- data/test/sepa/transaction_test.rb +0 -362
- data/test/sepa/user_file_type_test.rb +0 -21
- data/test/sepa/xml_parser_test.rb +0 -73
data/lib/sepa/soap_builder.rb
CHANGED
@@ -1,43 +1,40 @@
|
|
1
1
|
module Sepa
|
2
2
|
class SoapBuilder
|
3
|
-
|
4
|
-
def initialize(params)
|
5
|
-
|
6
|
-
check_params(params)
|
7
|
-
# Generate a request ID for the request
|
8
|
-
params[:request_id] = generate_request_id
|
9
|
-
|
10
|
-
# Check if the bank&command need keys/certificates/csr's
|
11
|
-
@params = initialize_certificates_and_csr(params)
|
12
|
-
|
13
|
-
check_if_bank_allows_command(@params)
|
3
|
+
include Utilities
|
14
4
|
|
15
|
-
|
5
|
+
attr_reader :ar
|
16
6
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
@
|
7
|
+
# SoapBuilder creates the SOAP structure.
|
8
|
+
def initialize(params)
|
9
|
+
@bank = params[:bank]
|
10
|
+
@private_key = params[:private_key]
|
11
|
+
@cert = params[:cert]
|
12
|
+
@command = params[:command]
|
13
|
+
@customer_id = params[:customer_id]
|
14
|
+
@environment = params[:environment]
|
15
|
+
@status = params[:status]
|
16
|
+
@target_id = params[:target_id]
|
17
|
+
@language = params[:language]
|
18
|
+
@file_type = params[:file_type]
|
19
|
+
@content = params[:content]
|
20
|
+
@file_reference = params[:file_reference]
|
21
|
+
@enc_cert = params[:enc_cert]
|
22
|
+
@header_template = load_header_template
|
23
|
+
@template = load_body_template SOAP_TEMPLATE_PATH
|
24
|
+
@ar = ApplicationRequest.new(params)
|
25
|
+
|
26
|
+
find_correct_bank_extension
|
21
27
|
end
|
22
28
|
|
23
29
|
def to_xml
|
24
30
|
# Returns a complete SOAP message in xml format
|
25
|
-
find_correct_build
|
26
|
-
end
|
27
|
-
|
28
|
-
def get_ar_as_base64
|
29
|
-
@ar
|
31
|
+
find_correct_build.to_xml
|
30
32
|
end
|
31
33
|
|
32
34
|
private
|
33
35
|
|
34
|
-
def
|
35
|
-
|
36
|
-
reqid
|
37
|
-
end
|
38
|
-
|
39
|
-
def find_correct_bank_extension(bank)
|
40
|
-
case bank
|
36
|
+
def find_correct_bank_extension
|
37
|
+
case @bank
|
41
38
|
when :danske
|
42
39
|
self.extend(DanskeSoapRequest)
|
43
40
|
when :nordea
|
@@ -45,351 +42,64 @@ module Sepa
|
|
45
42
|
end
|
46
43
|
end
|
47
44
|
|
48
|
-
# Generic building steps
|
49
45
|
def calculate_digest(doc, node)
|
50
46
|
sha1 = OpenSSL::Digest::SHA1.new
|
51
|
-
|
52
47
|
node = doc.at_css(node)
|
53
48
|
|
54
49
|
canon_node = node.canonicalize(
|
55
|
-
mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
|
56
|
-
inclusive_namespaces=nil,with_comments=false
|
50
|
+
mode = Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
|
51
|
+
inclusive_namespaces = nil, with_comments = false
|
57
52
|
)
|
58
53
|
|
59
54
|
Base64.encode64(sha1.digest(canon_node)).gsub(/\s+/, "")
|
60
55
|
end
|
61
56
|
|
62
|
-
def calculate_signature(doc, node
|
57
|
+
def calculate_signature(doc, node)
|
63
58
|
sha1 = OpenSSL::Digest::SHA1.new
|
64
|
-
|
65
59
|
node = doc.at_css(node)
|
66
60
|
|
67
61
|
canon_signed_info_node = node.canonicalize(
|
68
|
-
mode=Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
|
69
|
-
with_comments=false
|
62
|
+
mode = Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
|
63
|
+
inclusive_namespaces = nil, with_comments = false
|
70
64
|
)
|
71
65
|
|
72
|
-
signature = private_key.sign(sha1, canon_signed_info_node)
|
73
|
-
|
66
|
+
signature = @private_key.sign(sha1, canon_signed_info_node)
|
74
67
|
Base64.encode64(signature).gsub(/\s+/, "")
|
75
68
|
end
|
76
69
|
|
77
|
-
def
|
78
|
-
|
79
|
-
|
80
|
-
path = "#{@template_path}/download_file_list.xml"
|
81
|
-
when :get_user_info
|
82
|
-
path = "#{@template_path}/get_user_info.xml"
|
83
|
-
when :upload_file
|
84
|
-
path = "#{@template_path}/upload_file.xml"
|
85
|
-
when :download_file
|
86
|
-
path = "#{@template_path}/download_file.xml"
|
87
|
-
when :get_certificate
|
88
|
-
path = "#{@template_path}/get_certificate.xml"
|
89
|
-
when :get_bank_certificate
|
90
|
-
path = "#{@template_path}/danske_get_bank_certificate.xml"
|
91
|
-
end
|
92
|
-
|
93
|
-
body_template = File.open(path)
|
94
|
-
body = Nokogiri::XML(body_template)
|
95
|
-
body_template.close
|
96
|
-
|
97
|
-
body
|
70
|
+
def load_header_template
|
71
|
+
path = File.open("#{SOAP_TEMPLATE_PATH}/header.xml")
|
72
|
+
Nokogiri::XML(path)
|
98
73
|
end
|
99
74
|
|
100
75
|
def set_node(doc, node, value)
|
101
76
|
doc.at_css(node).content = value
|
102
77
|
end
|
103
78
|
|
104
|
-
def add_body_to_header
|
105
|
-
body =
|
106
|
-
|
107
|
-
|
108
|
-
end
|
109
|
-
|
110
|
-
def extract_public_key(cert)
|
111
|
-
pkey = cert.public_key
|
112
|
-
pkey = OpenSSL::PKey::RSA.new(pkey)
|
113
|
-
|
114
|
-
pkey
|
115
|
-
end
|
116
|
-
|
117
|
-
def format_cert(cert)
|
118
|
-
cert = cert.to_s
|
119
|
-
cert = cert.split('-----BEGIN CERTIFICATE-----')[1]
|
120
|
-
cert = cert.split('-----END CERTIFICATE-----')[0]
|
121
|
-
cert.gsub!(/\s+/, "")
|
122
|
-
end
|
123
|
-
|
124
|
-
def load_header_template(template_path)
|
125
|
-
header_template = File.open("#{template_path}/header.xml")
|
126
|
-
header = Nokogiri::XML(header_template)
|
127
|
-
header_template.close
|
128
|
-
header
|
129
|
-
end
|
130
|
-
|
131
|
-
def process_header(header, body, private_key, cert)
|
132
|
-
set_node(header, 'wsu|Created', Time.now.iso8601)
|
133
|
-
|
134
|
-
set_node(header, 'wsu|Expires', (Time.now + 3600).iso8601)
|
135
|
-
|
136
|
-
timestamp_digest = calculate_digest(header,'wsu|Timestamp')
|
137
|
-
set_node(header,'dsig|Reference[URI="#dsfg8sdg87dsf678g6dsg6ds7fg"]' \
|
138
|
-
' dsig|DigestValue', timestamp_digest)
|
139
|
-
|
140
|
-
body_digest = calculate_digest(body, 'env|Body')
|
141
|
-
set_node(header,'dsig|Reference[URI="#sdf6sa7d86f87s6df786sd87f6s8fsd'\
|
142
|
-
'a"] dsig|DigestValue', body_digest)
|
143
|
-
|
144
|
-
signature = calculate_signature(header, 'dsig|SignedInfo', private_key)
|
145
|
-
set_node(header, 'dsig|SignatureValue', signature)
|
146
|
-
|
147
|
-
formatted_cert = format_cert(cert)
|
148
|
-
set_node(header, 'wsse|BinarySecurityToken', formatted_cert)
|
79
|
+
def add_body_to_header
|
80
|
+
body = @template.at_css('env|Body')
|
81
|
+
@header_template.root.add_child(body)
|
82
|
+
@header_template
|
149
83
|
end
|
150
84
|
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
check_params_hash(params)
|
155
|
-
check_certificate_and_key_requirements(params)
|
156
|
-
check_bank(params[:bank])
|
157
|
-
check_env(params[:environment])
|
158
|
-
check_customer_id(params[:customer_id])
|
85
|
+
def process_header
|
86
|
+
set_node(@header_template, 'wsu|Created', iso_time)
|
87
|
+
set_node(@header_template, 'wsu|Expires', (Time.now.utc + 300).iso8601)
|
159
88
|
|
160
|
-
|
161
|
-
|
89
|
+
timestamp_digest = calculate_digest(@header_template, 'wsu|Timestamp')
|
90
|
+
dsig = 'dsig|Reference[URI="#dsfg8sdg87dsf678g6dsg6ds7fg"] dsig|DigestValue'
|
91
|
+
set_node(@header_template, dsig, timestamp_digest)
|
162
92
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
check_pin(params[:pin])
|
167
|
-
check_service(params[:service])
|
168
|
-
when *generic_commands
|
169
|
-
if params[:bank] == :nordea
|
170
|
-
check_lang(params[:language])
|
171
|
-
check_status(params[:status])
|
172
|
-
check_target_id(params[:target_id])
|
173
|
-
check_file_type(params[:file_type])
|
174
|
-
end
|
175
|
-
when :upload_file
|
176
|
-
check_lang(params[:language])
|
177
|
-
check_target_id(params[:target_id])
|
178
|
-
check_file_type(params[:file_type])
|
179
|
-
check_content(params[:content])
|
180
|
-
when :get_bank_certificate
|
181
|
-
if params[:bank] == :danske
|
182
|
-
# Nothing here
|
183
|
-
end
|
184
|
-
else
|
185
|
-
fail ArgumentError, "Command not supported."
|
186
|
-
end
|
187
|
-
end
|
93
|
+
body_digest = calculate_digest(@template, 'env|Body')
|
94
|
+
dsig = 'dsig|Reference[URI="#sdf6sa7d86f87s6df786sd87f6s8fsda"] dsig|DigestValue'
|
95
|
+
set_node(@header_template, dsig, body_digest)
|
188
96
|
|
189
|
-
|
190
|
-
|
191
|
-
fail ArgumentError, "You didn't provide a certificate signing request"
|
192
|
-
end
|
193
|
-
end
|
194
|
-
|
195
|
-
def check_params_hash(params)
|
196
|
-
unless params.respond_to?(:each_pair)
|
197
|
-
fail ArgumentError, "You didn't provide a proper hash"
|
198
|
-
end
|
199
|
-
end
|
97
|
+
signature = calculate_signature(@header_template, 'dsig|SignedInfo')
|
98
|
+
set_node(@header_template, 'dsig|SignatureValue', signature)
|
200
99
|
|
201
|
-
|
202
|
-
|
203
|
-
fail ArgumentError, "You didn't provide a proper bank. " \
|
204
|
-
"Acceptable values are nordea OR danske."
|
205
|
-
end
|
206
|
-
end
|
207
|
-
|
208
|
-
def check_request_id(request_id)
|
209
|
-
if request_id.to_i == 0
|
210
|
-
fail ArgumentError, "Request ID must be a number and not 0"
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
def check_keygen_type(keygen)
|
215
|
-
unless keygen
|
216
|
-
fail ArgumentError, "You didn't provide any Key Generator Type"
|
217
|
-
end
|
218
|
-
end
|
219
|
-
|
220
|
-
def check_encryption_pkcs10(enc_cert)
|
221
|
-
unless enc_cert
|
222
|
-
fail ArgumentError, "You didn't provide Encrypting certificate PKCS10"
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
|
-
def check_signing_pkcs10(sig_cert)
|
227
|
-
unless sig_cert
|
228
|
-
fail ArgumentError, "You didn't provide Signing certificate PKCS10"
|
229
|
-
end
|
100
|
+
formatted_cert = format_cert(@cert)
|
101
|
+
set_node(@header_template, 'wsse|BinarySecurityToken', formatted_cert)
|
230
102
|
end
|
231
103
|
|
232
|
-
def check_pin(pin)
|
233
|
-
unless pin
|
234
|
-
fail ArgumentError, "You didn't provide a secret PIN"
|
235
|
-
end
|
236
|
-
end
|
237
|
-
|
238
|
-
def check_private_key(private_key)
|
239
|
-
unless private_key.respond_to?(:sign)
|
240
|
-
fail ArgumentError, "You didn't provide a proper private key. The " \
|
241
|
-
"key has to be in OpenSSL::PKey::RSA - format."
|
242
|
-
end
|
243
|
-
end
|
244
|
-
|
245
|
-
def check_cert(cert)
|
246
|
-
unless cert.respond_to?(:check_private_key)
|
247
|
-
fail ArgumentError, "You didn't provide a proper certificate. The " \
|
248
|
-
"certificate has to be in OpenSSL::X509::Certificate - format."
|
249
|
-
end
|
250
|
-
end
|
251
|
-
|
252
|
-
def check_customer_id(customer_id)
|
253
|
-
unless customer_id && customer_id.respond_to?(:to_s) &&
|
254
|
-
customer_id.length <= 16
|
255
|
-
fail ArgumentError, "You didn't provide a proper customer id"
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
def check_env(env)
|
260
|
-
unless ['PRODUCTION', 'TEST', 'customertest'].include?(env)
|
261
|
-
fail ArgumentError, "You didn't provide a proper environment. " \
|
262
|
-
"Acceptable values are PRODUCTION or TEST or customertest."
|
263
|
-
end
|
264
|
-
end
|
265
|
-
|
266
|
-
def check_status(status)
|
267
|
-
unless ['NEW', 'DOWNLOADED', 'ALL'].include?(status)
|
268
|
-
fail ArgumentError, "You didn't provide a proper status. " \
|
269
|
-
"Acceptable values are NEW, DOWNLOADED or ALL."
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
def check_target_id(target_id)
|
274
|
-
unless target_id && target_id.respond_to?(:to_s) &&
|
275
|
-
target_id.length <= 80
|
276
|
-
fail ArgumentError, "You didn't provide a proper target id"
|
277
|
-
end
|
278
|
-
end
|
279
|
-
|
280
|
-
def check_lang(lang)
|
281
|
-
unless ['FI', 'SE', 'EN'].include?(lang)
|
282
|
-
fail ArgumentError, "You didn't provide a proper language. " \
|
283
|
-
"Acceptable values are FI, SE or EN."
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
def check_file_type(file_type)
|
288
|
-
unless file_type && file_type.respond_to?(:to_s) &&
|
289
|
-
file_type.length <= 20
|
290
|
-
fail ArgumentError, "You didn't provide a proper file type. Check " \
|
291
|
-
"Your bank's documentation for available file types."
|
292
|
-
end
|
293
|
-
end
|
294
|
-
|
295
|
-
def check_content(content)
|
296
|
-
unless content
|
297
|
-
fail ArgumentError, "You didn't provide any content."
|
298
|
-
end
|
299
|
-
end
|
300
|
-
|
301
|
-
def check_service(service)
|
302
|
-
unless ['service', 'ISSUER', 'MATU'].include?(service)
|
303
|
-
fail ArgumentError, "You didn't provide a proper service."
|
304
|
-
end
|
305
|
-
end
|
306
|
-
|
307
|
-
def check_hmac(hmac)
|
308
|
-
unless hmac
|
309
|
-
fail ArgumentError, "You didn't provide any HMAC."
|
310
|
-
end
|
311
|
-
end
|
312
|
-
|
313
|
-
def check_if_bank_allows_command(params)
|
314
|
-
bank = params.fetch(:bank)
|
315
|
-
command = params.fetch(:command)
|
316
|
-
case bank
|
317
|
-
when :nordea
|
318
|
-
allowed_commands = [:get_certificate,:get_user_info,
|
319
|
-
:download_file_list,:download_file,:upload_file]
|
320
|
-
unless allowed_commands.include?(command)
|
321
|
-
fail ArgumentError, "You didn't provide a matching bank and service."
|
322
|
-
end
|
323
|
-
when :danske
|
324
|
-
allowed_commands = [:get_bank_certificate]
|
325
|
-
unless allowed_commands.include?(command)
|
326
|
-
fail ArgumentError, "You didn't provide a matching bank and service."
|
327
|
-
end
|
328
|
-
end
|
329
|
-
end
|
330
|
-
|
331
|
-
def check_certificate_and_key_requirements(params)
|
332
|
-
command = params[:command]
|
333
|
-
require_private_and_cert = [:get_user_info,:download_file_list,
|
334
|
-
:download_file,:upload_file]
|
335
|
-
require_nothing = [:get_bank_certificate]
|
336
|
-
require_pkcs = [:get_certificate]
|
337
|
-
|
338
|
-
case command
|
339
|
-
when *require_private_and_cert
|
340
|
-
if params[:cert_path] == nil && params[:cert_plain] == nil
|
341
|
-
fail ArgumentError, "You must provide a path to the certificate " \
|
342
|
-
"or certificate in plain text"
|
343
|
-
end
|
344
|
-
if params[:private_key_path] == nil && params[:private_key_plain] == nil
|
345
|
-
fail ArgumentError, "You must provide a path to your private key " \
|
346
|
-
"or private key in plain text"
|
347
|
-
end
|
348
|
-
when *require_nothing
|
349
|
-
when *require_pkcs
|
350
|
-
if params[:csr_path] == nil && params[:csr_plain] == nil
|
351
|
-
fail ArgumentError, "You must provide a path to the CSR or CSR in plain text"
|
352
|
-
end
|
353
|
-
end
|
354
|
-
end
|
355
|
-
|
356
|
-
def initialize_certificates_and_csr(params)
|
357
|
-
begin
|
358
|
-
command = params[:command]
|
359
|
-
require_private_and_cert = [:get_user_info,:download_file_list,
|
360
|
-
:download_file,:upload_file]
|
361
|
-
require_nothing = [:get_bank_certificate]
|
362
|
-
require_pkcs = [:get_certificate]
|
363
|
-
|
364
|
-
case command
|
365
|
-
when *require_private_and_cert
|
366
|
-
if params[:cert_path] != nil
|
367
|
-
params[:cert] = OpenSSL::X509::Certificate.new(File.read(params.fetch(:cert_path)))
|
368
|
-
elsif params[:cert_plain] != nil
|
369
|
-
params[:cert] = OpenSSL::X509::Certificate.new(params.fetch(:cert_plain))
|
370
|
-
end
|
371
|
-
if params[:private_key_path] != nil
|
372
|
-
params[:private_key] = OpenSSL::PKey::RSA.new(File.read(params.fetch(:private_key_path)))
|
373
|
-
elsif params[:private_key_plain] != nil
|
374
|
-
params[:private_key] = OpenSSL::PKey::RSA.new(params.fetch(:private_key_plain))
|
375
|
-
end
|
376
|
-
check_private_key(params[:private_key])
|
377
|
-
check_cert(params[:cert])
|
378
|
-
when *require_nothing
|
379
|
-
when *require_pkcs
|
380
|
-
if params[:csr_path] != nil
|
381
|
-
params[:csr] = OpenSSL::X509::Request.new(File.read(params.fetch(:csr_path)))
|
382
|
-
elsif params[:csr_plain] != nil
|
383
|
-
params[:csr] = OpenSSL::X509::Request.new(params.fetch(:csr_plain))
|
384
|
-
end
|
385
|
-
check_csr(params[:csr])
|
386
|
-
else
|
387
|
-
fail ArgumentError, "No matching cases for initialize_certificates_and_csr"
|
388
|
-
end
|
389
|
-
params
|
390
|
-
rescue Exception => e
|
391
|
-
fail ArgumentError, "Parameter failed to initialize, check private key and cert path/plain"
|
392
|
-
end
|
393
|
-
end
|
394
104
|
end
|
395
105
|
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
module Sepa
|
2
|
+
module Utilities
|
3
|
+
|
4
|
+
def calculate_digest(node)
|
5
|
+
sha1 = OpenSSL::Digest::SHA1.new
|
6
|
+
|
7
|
+
canon_node = node.canonicalize(
|
8
|
+
mode = Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0,
|
9
|
+
inclusive_namespaces = nil, with_comments = false
|
10
|
+
)
|
11
|
+
|
12
|
+
Base64.encode64(sha1.digest(canon_node)).gsub(/\s+/, "")
|
13
|
+
end
|
14
|
+
|
15
|
+
# Takes a certificate, adds begin and end
|
16
|
+
# certificate texts and splits it into multiple lines so that OpenSSL
|
17
|
+
# can read it.
|
18
|
+
def process_cert_value(cert_value)
|
19
|
+
cert = "-----BEGIN CERTIFICATE-----\n"
|
20
|
+
cert += cert_value.to_s.gsub(/\s+/, "").scan(/.{1,64}/).join("\n")
|
21
|
+
cert += "\n"
|
22
|
+
cert + "-----END CERTIFICATE-----"
|
23
|
+
end
|
24
|
+
|
25
|
+
def format_cert(cert)
|
26
|
+
cert = cert.to_s
|
27
|
+
cert = cert.split('-----BEGIN CERTIFICATE-----')[1]
|
28
|
+
cert = cert.split('-----END CERTIFICATE-----')[0]
|
29
|
+
cert.gsub!(/\s+/, "")
|
30
|
+
end
|
31
|
+
|
32
|
+
def format_cert_request(cert_request)
|
33
|
+
cert_request = cert_request.split('-----BEGIN CERTIFICATE REQUEST-----')[1]
|
34
|
+
cert_request = cert_request.split('-----END CERTIFICATE REQUEST-----')[0]
|
35
|
+
cert_request.gsub!(/\s+/, "")
|
36
|
+
end
|
37
|
+
|
38
|
+
def check_validity_against_schema(doc, schema)
|
39
|
+
Dir.chdir(SCHEMA_PATH) do
|
40
|
+
xsd = Nokogiri::XML::Schema(IO.read(schema))
|
41
|
+
unless doc.respond_to?(:canonicalize) && xsd.valid?(doc)
|
42
|
+
errors.add(:base, 'The document did not validate against the schema file')
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Extracts a certificate from a document and return it as an OpenSSL X509 certificate
|
48
|
+
# Return nil is the node cannot be found
|
49
|
+
def extract_cert(doc, node, namespace)
|
50
|
+
return nil unless doc.respond_to? :at
|
51
|
+
|
52
|
+
cert_raw = doc.at("xmlns|#{node}", 'xmlns' => namespace)
|
53
|
+
|
54
|
+
return nil if cert_raw.nil?
|
55
|
+
|
56
|
+
cert_raw = cert_raw.content.gsub(/\s+/, "")
|
57
|
+
|
58
|
+
cert = process_cert_value(cert_raw)
|
59
|
+
|
60
|
+
begin
|
61
|
+
OpenSSL::X509::Certificate.new(cert)
|
62
|
+
rescue => e
|
63
|
+
fail OpenSSL::X509::CertificateError,
|
64
|
+
"The certificate could not be processed. It's most likely corrupted. OpenSSL had this to say: #{e}."
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def cert_request_valid?(cert_request)
|
69
|
+
begin
|
70
|
+
OpenSSL::X509::Request.new cert_request
|
71
|
+
rescue
|
72
|
+
return false
|
73
|
+
end
|
74
|
+
|
75
|
+
true
|
76
|
+
end
|
77
|
+
|
78
|
+
def load_body_template(template)
|
79
|
+
path = "#{template}/"
|
80
|
+
|
81
|
+
case @command
|
82
|
+
when :download_file_list
|
83
|
+
path << "download_file_list.xml"
|
84
|
+
when :get_user_info
|
85
|
+
path << "get_user_info.xml"
|
86
|
+
when :upload_file
|
87
|
+
path << "upload_file.xml"
|
88
|
+
when :download_file
|
89
|
+
path << "download_file.xml"
|
90
|
+
when :get_certificate
|
91
|
+
path << "get_certificate.xml"
|
92
|
+
when :get_bank_certificate
|
93
|
+
path << "danske_get_bank_certificate.xml"
|
94
|
+
when :create_certificate
|
95
|
+
path << "create_certificate.xml"
|
96
|
+
else
|
97
|
+
fail ArgumentError
|
98
|
+
end
|
99
|
+
|
100
|
+
Nokogiri::XML(File.open(path))
|
101
|
+
end
|
102
|
+
|
103
|
+
# Checks that the certificate in the application response is signed with the
|
104
|
+
# private key of the public key of the certificate as parameter.
|
105
|
+
def cert_is_trusted(root_cert)
|
106
|
+
if root_cert.subject == certificate.issuer
|
107
|
+
# Return true or false
|
108
|
+
certificate.verify(root_cert.public_key)
|
109
|
+
else
|
110
|
+
fail SecurityError, "false"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def iso_time
|
115
|
+
@iso_time ||= Time.now.utc.iso8601
|
116
|
+
end
|
117
|
+
|
118
|
+
def hmac(pin, csr)
|
119
|
+
Base64.encode64(OpenSSL::HMAC.digest('sha1', pin, csr)).chop
|
120
|
+
end
|
121
|
+
|
122
|
+
def csr_to_binary(csr)
|
123
|
+
OpenSSL::X509::Request.new(csr).to_der
|
124
|
+
end
|
125
|
+
|
126
|
+
def canonicalized_node(doc, namespace, node)
|
127
|
+
content_node = doc.at("xmlns|#{node}", xmlns: namespace)
|
128
|
+
content_node.canonicalize if content_node
|
129
|
+
end
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
data/lib/sepa/version.rb
CHANGED