epics 2.10.0 → 3.0.0.rc1

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.
Files changed (245) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.semaphore/semaphore.yml +17 -8
  4. data/CHANGELOG.md +97 -0
  5. data/EBICS_REFERENCES.md +169 -0
  6. data/README.md +219 -50
  7. data/lib/epics/azv.rb +3 -10
  8. data/lib/epics/b2b.rb +3 -10
  9. data/lib/epics/bka.rb +3 -14
  10. data/lib/epics/builders/body_builder/base.rb +26 -0
  11. data/lib/epics/builders/body_builder/v2.rb +9 -0
  12. data/lib/epics/builders/body_builder/v3.rb +9 -0
  13. data/lib/epics/builders/body_builder.rb +6 -0
  14. data/lib/epics/builders/data_encryption_info_builder.rb +29 -0
  15. data/lib/epics/builders/data_transfer_builder/base.rb +52 -0
  16. data/lib/epics/builders/data_transfer_builder/v2.rb +9 -0
  17. data/lib/epics/builders/data_transfer_builder/v3.rb +12 -0
  18. data/lib/epics/builders/data_transfer_builder.rb +6 -0
  19. data/lib/epics/builders/header_builder/base.rb +26 -0
  20. data/lib/epics/builders/header_builder/v2.rb +9 -0
  21. data/lib/epics/builders/header_builder/v3.rb +9 -0
  22. data/lib/epics/builders/header_builder.rb +6 -0
  23. data/lib/epics/builders/mutable_builder.rb +28 -0
  24. data/lib/epics/builders/order_details_builder/base.rb +100 -0
  25. data/lib/epics/builders/order_details_builder/v2.rb +21 -0
  26. data/lib/epics/builders/order_details_builder/v3.rb +51 -0
  27. data/lib/epics/builders/order_details_builder.rb +10 -0
  28. data/lib/epics/builders/request_builder.rb +25 -0
  29. data/lib/epics/builders/static_builder/base.rb +75 -0
  30. data/lib/epics/builders/static_builder/v2.rb +9 -0
  31. data/lib/epics/builders/static_builder/v3.rb +9 -0
  32. data/lib/epics/builders/static_builder.rb +9 -0
  33. data/lib/epics/builders/transfer_receipt_builder.rb +19 -0
  34. data/lib/epics/builders/xml_builder/base.rb +92 -0
  35. data/lib/epics/builders/xml_builder/v24.rb +31 -0
  36. data/lib/epics/builders/xml_builder/v25.rb +31 -0
  37. data/lib/epics/builders/xml_builder/v3.rb +31 -0
  38. data/lib/epics/builders/xml_builder.rb +7 -0
  39. data/lib/epics/builders.rb +13 -0
  40. data/lib/epics/c2s.rb +3 -10
  41. data/lib/epics/c52.rb +2 -14
  42. data/lib/epics/c53.rb +2 -14
  43. data/lib/epics/c54.rb +2 -14
  44. data/lib/epics/c5n.rb +3 -14
  45. data/lib/epics/ccs.rb +3 -10
  46. data/lib/epics/cct.rb +3 -10
  47. data/lib/epics/cd1.rb +3 -10
  48. data/lib/epics/cdb.rb +3 -10
  49. data/lib/epics/cdd.rb +3 -10
  50. data/lib/epics/cds.rb +3 -10
  51. data/lib/epics/cdz.rb +3 -14
  52. data/lib/epics/cip.rb +3 -10
  53. data/lib/epics/client.rb +491 -123
  54. data/lib/epics/crypt/aes.rb +56 -0
  55. data/lib/epics/crypt/x_509.rb +52 -0
  56. data/lib/epics/crypt.rb +5 -0
  57. data/lib/epics/crz.rb +3 -14
  58. data/lib/epics/factories/crypt/aes_factory.rb +5 -0
  59. data/lib/epics/factories/crypt.rb +4 -0
  60. data/lib/epics/factories/request_factory/base.rb +236 -0
  61. data/lib/epics/factories/request_factory/v2.rb +194 -0
  62. data/lib/epics/factories/request_factory/v24.rb +32 -0
  63. data/lib/epics/factories/request_factory/v25.rb +31 -0
  64. data/lib/epics/factories/request_factory/v3.rb +305 -0
  65. data/lib/epics/factories/request_factory.rb +8 -0
  66. data/lib/epics/factories.rb +5 -0
  67. data/lib/epics/fdl.rb +3 -18
  68. data/lib/epics/ful.rb +6 -0
  69. data/lib/epics/generic_request.rb +31 -92
  70. data/lib/epics/generic_upload_request.rb +14 -67
  71. data/lib/epics/haa.rb +3 -9
  72. data/lib/epics/hac.rb +3 -14
  73. data/lib/epics/handlers/auth_signature_handler.rb +102 -0
  74. data/lib/epics/handlers/order_data_handler/base.rb +98 -0
  75. data/lib/epics/handlers/order_data_handler/v2.rb +39 -0
  76. data/lib/epics/handlers/order_data_handler/v24.rb +11 -0
  77. data/lib/epics/handlers/order_data_handler/v25.rb +11 -0
  78. data/lib/epics/handlers/order_data_handler/v3.rb +41 -0
  79. data/lib/epics/handlers/order_data_handler.rb +8 -0
  80. data/lib/epics/handlers/user_signature_handler/base.rb +10 -0
  81. data/lib/epics/handlers/user_signature_handler/v2.rb +17 -0
  82. data/lib/epics/handlers/user_signature_handler/v3.rb +17 -0
  83. data/lib/epics/handlers/user_signature_handler.rb +6 -0
  84. data/lib/epics/handlers.rb +6 -0
  85. data/lib/epics/hev.rb +2 -15
  86. data/lib/epics/hia.rb +4 -55
  87. data/lib/epics/hkd.rb +3 -9
  88. data/lib/epics/hpb.rb +3 -13
  89. data/lib/epics/hpd.rb +3 -9
  90. data/lib/epics/htd.rb +3 -9
  91. data/lib/epics/ini.rb +4 -46
  92. data/lib/epics/keyring.rb +17 -0
  93. data/lib/epics/letter_renderer.rb +17 -22
  94. data/lib/epics/ptk.rb +3 -14
  95. data/lib/epics/response.rb +34 -29
  96. data/lib/epics/services/crypt_service.rb +62 -0
  97. data/lib/epics/services/digest_resolver/base.rb +30 -0
  98. data/lib/epics/services/digest_resolver/v2.rb +13 -0
  99. data/lib/epics/services/digest_resolver/v3.rb +19 -0
  100. data/lib/epics/services/digest_resolver.rb +6 -0
  101. data/lib/epics/services.rb +5 -0
  102. data/lib/epics/signature.rb +50 -0
  103. data/lib/epics/{key.rb → signature_algorithm/base.rb} +14 -21
  104. data/lib/epics/signature_algorithm/rsa.rb +50 -0
  105. data/lib/epics/signature_algorithm/rsapkcs1.rb +16 -0
  106. data/lib/epics/signature_algorithm/rsapss.rb +20 -0
  107. data/lib/epics/signature_algorithm.rb +2 -0
  108. data/lib/epics/sta.rb +3 -14
  109. data/lib/epics/version.rb +1 -1
  110. data/lib/epics/vmk.rb +3 -14
  111. data/lib/epics/wss.rb +3 -9
  112. data/lib/epics/xct.rb +3 -10
  113. data/lib/epics/xds.rb +3 -10
  114. data/lib/epics/xe2.rb +3 -10
  115. data/lib/epics/xe3.rb +3 -10
  116. data/lib/epics/xek.rb +5 -0
  117. data/lib/epics/yct.rb +6 -0
  118. data/lib/epics/z01.rb +2 -14
  119. data/lib/epics/z52.rb +2 -14
  120. data/lib/epics/z53.rb +2 -14
  121. data/lib/epics/z54.rb +2 -14
  122. data/lib/epics/zsr.rb +5 -0
  123. data/lib/epics.rb +69 -5
  124. data/lib/letter/ini.erb +27 -6
  125. data/spec/aes_spec.rb +46 -0
  126. data/spec/auth_signature_handler_spec.rb +58 -0
  127. data/spec/builders_spec.rb +616 -0
  128. data/spec/certificate_handling_spec.rb +189 -0
  129. data/spec/client_setup_block_spec.rb +41 -0
  130. data/spec/client_spec.rb +143 -91
  131. data/spec/crypt_service_spec.rb +132 -0
  132. data/spec/date_range_spec.rb +46 -0
  133. data/spec/digest_resolver_spec.rb +164 -0
  134. data/spec/fixtures/bank_x509.pem +3 -0
  135. data/spec/fixtures/xml/haa.xml +40 -1
  136. data/spec/fixtures/xml/haa_receipt.xml +33 -30
  137. data/spec/fixtures/xml/haa_response_h004.xml +4 -0
  138. data/spec/fixtures/xml/haa_response_h005.xml +38 -0
  139. data/spec/fixtures/xml/hia_request_order_data.xml +24 -1
  140. data/spec/fixtures/xml/hpb_request.xml +1 -1
  141. data/spec/fixtures/xml/hpb_response_x509.xml +16 -0
  142. data/spec/fixtures/xml/htd_order_data_h005.xml +55 -0
  143. data/spec/fixtures/xml/jruby/hia.xml +20 -22
  144. data/spec/fixtures/xml/jruby/ini.xml +1 -3
  145. data/spec/fixtures/xml/ruby/hia.xml +21 -1
  146. data/spec/fixtures/xml/ruby/ini.xml +21 -1
  147. data/spec/handlers_spec.rb +267 -0
  148. data/spec/hpb_malformed_certificate_spec.rb +36 -0
  149. data/spec/key_file_decryption_spec.rb +27 -0
  150. data/spec/key_file_preservation_spec.rb +78 -0
  151. data/spec/keyring_spec.rb +349 -0
  152. data/spec/middleware/parse_ebics_spec.rb +2 -1
  153. data/spec/order_id_spec.rb +65 -0
  154. data/spec/orders/azv_spec.rb +63 -7
  155. data/spec/orders/b2b_spec.rb +68 -3
  156. data/spec/orders/bka_spec.rb +34 -4
  157. data/spec/orders/c2s_spec.rb +62 -9
  158. data/spec/orders/c52_spec.rb +34 -4
  159. data/spec/orders/c53_spec.rb +34 -4
  160. data/spec/orders/c54_spec.rb +36 -4
  161. data/spec/orders/c5n_spec.rb +36 -4
  162. data/spec/orders/camt_parity_spec.rb +80 -0
  163. data/spec/orders/ccs_spec.rb +62 -9
  164. data/spec/orders/cct_spec.rb +83 -9
  165. data/spec/orders/cd1_spec.rb +50 -7
  166. data/spec/orders/cdb_spec.rb +64 -7
  167. data/spec/orders/cdd_spec.rb +64 -7
  168. data/spec/orders/cds_spec.rb +74 -0
  169. data/spec/orders/cdz_spec.rb +67 -4
  170. data/spec/orders/cip_spec.rb +61 -9
  171. data/spec/orders/crz_spec.rb +67 -4
  172. data/spec/orders/fdl_spec.rb +143 -13
  173. data/spec/orders/ful_spec.rb +63 -0
  174. data/spec/orders/haa_spec.rb +115 -9
  175. data/spec/orders/hac_spec.rb +89 -10
  176. data/spec/orders/hev_spec.rb +1 -6
  177. data/spec/orders/hia_spec.rb +25 -22
  178. data/spec/orders/hkd_spec.rb +23 -4
  179. data/spec/orders/hpb_spec.rb +7 -4
  180. data/spec/orders/hpd_spec.rb +23 -4
  181. data/spec/orders/htd_spec.rb +23 -4
  182. data/spec/orders/ini_spec.rb +23 -18
  183. data/spec/orders/ptk_spec.rb +27 -4
  184. data/spec/orders/sta_spec.rb +129 -11
  185. data/spec/orders/vmk_spec.rb +36 -4
  186. data/spec/orders/wss_spec.rb +29 -3
  187. data/spec/orders/x_509_certificate_spec.rb +9 -1
  188. data/spec/orders/xct_spec.rb +63 -0
  189. data/spec/orders/xds_spec.rb +13 -6
  190. data/spec/orders/xe2_spec.rb +64 -7
  191. data/spec/orders/xe3_spec.rb +64 -7
  192. data/spec/orders/xek_spec.rb +31 -0
  193. data/spec/orders/yct_spec.rb +43 -0
  194. data/spec/orders/z01_spec.rb +34 -4
  195. data/spec/orders/z52_spec.rb +34 -4
  196. data/spec/orders/z53_spec.rb +34 -4
  197. data/spec/orders/z54_spec.rb +36 -4
  198. data/spec/orders/zsr_spec.rb +31 -0
  199. data/spec/request_factory_spec.rb +444 -0
  200. data/spec/response_business_error_spec.rb +45 -0
  201. data/spec/response_validation_spec.rb +23 -0
  202. data/spec/{key_spec.rb → signature_algorithm/rsa_pss_spec.rb} +4 -13
  203. data/spec/support/ebics_matcher.rb +17 -9
  204. data/spec/support/ebics_shared_examples.rb +642 -0
  205. data/spec/support/h005_client_helper.rb +23 -0
  206. data/spec/upload_digest_spec.rb +69 -0
  207. data/spec/user_signature_handler_spec.rb +25 -0
  208. data/spec/version_support_error_spec.rb +76 -0
  209. data/spec/xsd/{ebics_hev.xsd → H000/ebics_hev.xsd} +0 -0
  210. data/spec/xsd/H003/ebics.xsd +11 -0
  211. data/spec/xsd/H003/ebics_keymgmt_request.xsd +555 -0
  212. data/spec/xsd/H003/ebics_keymgmt_response.xsd +131 -0
  213. data/spec/xsd/H003/ebics_orders.xsd +1811 -0
  214. data/spec/xsd/H003/ebics_request.xsd +354 -0
  215. data/spec/xsd/H003/ebics_response.xsd +161 -0
  216. data/spec/xsd/{ebics_signature.xsd → H003/ebics_signature.xsd} +0 -0
  217. data/spec/xsd/H003/ebics_types.xsd +2361 -0
  218. data/spec/xsd/H003/xmldsig-core-schema.xsd +318 -0
  219. data/spec/xsd/H004/ebics_signature.xsd +217 -0
  220. data/spec/xsd/H005/ebics_H005.xsd +11 -0
  221. data/spec/xsd/H005/ebics_keymgmt_request_H005.xsd +523 -0
  222. data/spec/xsd/H005/ebics_keymgmt_response_H005.xsd +137 -0
  223. data/spec/xsd/H005/ebics_orders_H005.xsd +2094 -0
  224. data/spec/xsd/H005/ebics_request_H005.xsd +349 -0
  225. data/spec/xsd/H005/ebics_response_H005.xsd +167 -0
  226. data/spec/xsd/H005/ebics_signature_S002.xsd +177 -0
  227. data/spec/xsd/H005/ebics_types_H005.xsd +1885 -0
  228. data/spec/xsd/H005/xmldsig-core-schema.xsd +318 -0
  229. metadata +200 -36
  230. data/lib/epics/header_request.rb +0 -58
  231. data/lib/epics/middleware/xmlsig.rb +0 -16
  232. data/lib/epics/signer.rb +0 -40
  233. data/lib/epics/x_509_certificate.rb +0 -15
  234. data/lib/letter/ini_with_certs.erb +0 -335
  235. data/spec/generic_upload_spec.rb +0 -58
  236. data/spec/hpb_spec.rb +0 -15
  237. data/spec/signer_spec.rb +0 -34
  238. /data/spec/xsd/{ebics_H004.xsd → H004/ebics_H004.xsd} +0 -0
  239. /data/spec/xsd/{ebics_keymgmt_request_H004.xsd → H004/ebics_keymgmt_request_H004.xsd} +0 -0
  240. /data/spec/xsd/{ebics_keymgmt_response_H004.xsd → H004/ebics_keymgmt_response_H004.xsd} +0 -0
  241. /data/spec/xsd/{ebics_orders_H004.xsd → H004/ebics_orders_H004.xsd} +0 -0
  242. /data/spec/xsd/{ebics_request_H004.xsd → H004/ebics_request_H004.xsd} +0 -0
  243. /data/spec/xsd/{ebics_response_H004.xsd → H004/ebics_response_H004.xsd} +0 -0
  244. /data/spec/xsd/{ebics_types_H004.xsd → H004/ebics_types_H004.xsd} +0 -0
  245. /data/spec/xsd/{xmldsig-core-schema.xsd → H004/xmldsig-core-schema.xsd} +0 -0
data/lib/epics/ptk.rb CHANGED
@@ -1,17 +1,6 @@
1
1
  class Epics::PTK < Epics::GenericRequest
2
- def header
3
- client.header_request.build(
4
- nonce: nonce,
5
- timestamp: timestamp,
6
- order_type: 'PTK',
7
- order_attribute: 'DZHNN',
8
- order_params: !!options[:from] && !!options[:to] ? {
9
- DateRange: {
10
- Start: options[:from],
11
- End: options[:to]
12
- }
13
- } : {},
14
- mutable: { TransactionPhase: 'Initialisation' }
15
- )
2
+ def to_xml
3
+ builder = request_factory.create_ptk(options[:from], options[:to])
4
+ builder.to_xml
16
5
  end
17
6
  end
@@ -1,6 +1,9 @@
1
1
  class Epics::Response
2
- attr_accessor :doc
3
- attr_accessor :client
2
+ # Informational body return codes. Every other 01xxxx code in Epics::Error is a
3
+ # failure -- 011001 is a negative acknowledgement, 011101 a segment underrun.
4
+ BUSINESS_OK_CODES = ['', '000000', '011000', '011301'].freeze
5
+
6
+ attr_accessor :doc, :client
4
7
 
5
8
  def initialize(client, xml)
6
9
  self.doc = Nokogiri::XML.parse(xml)
@@ -8,7 +11,7 @@ class Epics::Response
8
11
  end
9
12
 
10
13
  def technical_error?
11
- !["011000", "000000"].include?(technical_code)
14
+ !%w[011000 000000].include?(technical_code)
12
15
  end
13
16
 
14
17
  def technical_code
@@ -16,19 +19,19 @@ class Epics::Response
16
19
  end
17
20
 
18
21
  def mutable_return_code
19
- doc.xpath("//xmlns:header/xmlns:mutable/xmlns:ReturnCode", xmlns: "urn:org:ebics:H004").text
22
+ doc.xpath('//xmlns:header/xmlns:mutable/xmlns:ReturnCode', xmlns: client.urn_schema).text
20
23
  end
21
24
 
22
25
  def system_return_code
23
- doc.xpath("//xmlns:SystemReturnCode/xmlns:ReturnCode", xmlns: 'http://www.ebics.org/H000').text
26
+ doc.xpath('//xmlns:SystemReturnCode/xmlns:ReturnCode', xmlns: 'http://www.ebics.org/H000').text
24
27
  end
25
28
 
26
29
  def business_error?
27
- !["", "000000"].include?(business_code)
30
+ !BUSINESS_OK_CODES.include?(business_code)
28
31
  end
29
32
 
30
33
  def business_code
31
- doc.xpath("//xmlns:body/xmlns:ReturnCode", xmlns: "urn:org:ebics:H004").text
34
+ doc.xpath('//xmlns:body/xmlns:ReturnCode', xmlns: client.urn_schema).text
32
35
  end
33
36
 
34
37
  def ok?
@@ -36,55 +39,61 @@ class Epics::Response
36
39
  end
37
40
 
38
41
  def last_segment?
39
- !!doc.at_xpath("//xmlns:header/xmlns:mutable/*[@lastSegment='true']", xmlns: "urn:org:ebics:H004")
42
+ !!doc.at_xpath("//xmlns:header/xmlns:mutable/*[@lastSegment='true']", xmlns: client.urn_schema)
40
43
  end
41
44
 
42
45
  def segmented?
43
- !!doc.at_xpath("//xmlns:header/xmlns:mutable/xmlns:SegmentNumber", xmlns: "urn:org:ebics:H004")
46
+ !!doc.at_xpath('//xmlns:header/xmlns:mutable/xmlns:SegmentNumber', xmlns: client.urn_schema)
44
47
  end
45
48
 
46
49
  def return_code
47
- doc.xpath("//xmlns:ReturnCode", xmlns: "urn:org:ebics:H004").last.content
50
+ doc.xpath('//xmlns:ReturnCode', xmlns: client.urn_schema).last.content
48
51
  rescue NoMethodError
49
52
  nil
50
53
  end
51
54
 
52
55
  def report_text
53
- doc.xpath("//xmlns:ReportText", xmlns: "urn:org:ebics:H004").first.content
56
+ doc.xpath('//xmlns:ReportText', xmlns: client.urn_schema).first.content
54
57
  end
55
58
 
56
59
  def transaction_id
57
- doc.xpath("//xmlns:header/xmlns:static/xmlns:TransactionID", xmlns: 'urn:org:ebics:H004').text
60
+ doc.xpath('//xmlns:header/xmlns:static/xmlns:TransactionID', xmlns: client.urn_schema).text
58
61
  end
59
62
 
60
63
  def order_id
61
- doc.xpath("//xmlns:header/xmlns:mutable/xmlns:OrderID", xmlns: "urn:org:ebics:H004").text
64
+ doc.xpath('//xmlns:header/xmlns:mutable/xmlns:OrderID', xmlns: client.urn_schema).text
62
65
  end
63
66
 
64
67
  def digest_valid?
65
68
  authenticated = doc.xpath("//*[@authenticate='true']").map(&:canonicalize).join
66
- digest_value = doc.xpath("//ds:DigestValue", ds: "http://www.w3.org/2000/09/xmldsig#").first
69
+ digest_value = doc.xpath('//ds:DigestValue', ds: 'http://www.w3.org/2000/09/xmldsig#').first
67
70
 
68
- digest = Base64.encode64(digester.digest(authenticated)).strip
71
+ digest = Base64.encode64(OpenSSL::Digest.digest('sha256', authenticated)).strip
69
72
 
70
73
  digest == digest_value.content
71
74
  end
72
75
 
73
76
  def signature_valid?
74
- signature = doc.xpath("//ds:SignedInfo", ds: "http://www.w3.org/2000/09/xmldsig#").first.canonicalize
75
- signature_value = doc.xpath("//ds:SignatureValue", ds: "http://www.w3.org/2000/09/xmldsig#").first
77
+ key = client.bank_authentication_key
78
+ raise Epics::MissingKeyError, "The bank's authentication key" if !key
79
+
80
+ signature = doc.xpath('//ds:SignedInfo', ds: 'http://www.w3.org/2000/09/xmldsig#').first.canonicalize
81
+ signature_value = doc.xpath('//ds:SignatureValue', ds: 'http://www.w3.org/2000/09/xmldsig#').first
76
82
 
77
- client.bank_x.key.verify(digester, Base64.decode64(signature_value.content), signature)
83
+ key.verify(signature_value.content, signature)
78
84
  end
79
85
 
80
86
  def public_digest_valid?
81
- encryption_pub_key_digest = doc.xpath("//xmlns:EncryptionPubKeyDigest", xmlns: 'urn:org:ebics:H004').first
87
+ key = client.encryption_key
88
+ raise Epics::MissingKeyError, 'The encryption key' if !key
89
+
90
+ encryption_pub_key_digest = doc.xpath('//xmlns:EncryptionPubKeyDigest', xmlns: client.urn_schema).first
82
91
 
83
- client.e.public_digest == encryption_pub_key_digest.content
92
+ key.public_digest == encryption_pub_key_digest.content
84
93
  end
85
94
 
86
95
  def order_data
87
- order_data_encrypted = Base64.decode64(doc.xpath("//xmlns:OrderData", xmlns: 'urn:org:ebics:H004').first.content)
96
+ order_data_encrypted = Base64.decode64(doc.xpath('//xmlns:OrderData', xmlns: client.urn_schema).first.content)
88
97
 
89
98
  data = (cipher.update(order_data_encrypted) + cipher.final)
90
99
 
@@ -92,7 +101,7 @@ class Epics::Response
92
101
  end
93
102
 
94
103
  def cipher
95
- cipher = OpenSSL::Cipher.new("aes-128-cbc")
104
+ cipher = OpenSSL::Cipher.new('aes-128-cbc')
96
105
 
97
106
  cipher.decrypt
98
107
  cipher.padding = 0
@@ -101,13 +110,9 @@ class Epics::Response
101
110
  end
102
111
 
103
112
  def transaction_key
104
- transaction_key_encrypted = Base64.decode64(doc.xpath("//xmlns:TransactionKey", xmlns: 'urn:org:ebics:H004').first.content)
113
+ transaction_key_encrypted = Base64.decode64(doc.xpath('//xmlns:TransactionKey',
114
+ xmlns: client.urn_schema).first.content)
105
115
 
106
- @transaction_key ||= client.e.key.private_decrypt(transaction_key_encrypted)
116
+ @transaction_key ||= client.encryption_key.key.private_decrypt(transaction_key_encrypted)
107
117
  end
108
-
109
- def digester
110
- @digester ||= OpenSSL::Digest::SHA256.new
111
- end
112
-
113
118
  end
@@ -0,0 +1,62 @@
1
+ class Epics::Services::CryptService
2
+ def initialize
3
+ @aes_factory = Epics::Factories::Crypt::AesFactory.new
4
+ end
5
+
6
+ def encrypt(signature, data)
7
+ case signature.version
8
+ when Epics::Signature::A_VERSION_6, Epics::Signature::X_VERSION_2
9
+ signature.key.sign(data)
10
+ when Epics::Signature::A_VERSION_5
11
+ encrypt_by_rsa(signature.key, data)
12
+ end
13
+ end
14
+
15
+ def decrypt_by_key(key, encrypted)
16
+ aes = @aes_factory.create
17
+ aes.key_length = 128
18
+ aes.key = key
19
+ aes.decrypt(encrypted)
20
+ end
21
+
22
+ def encrypt_by_key(key, data)
23
+ aes = @aes_factory.create
24
+ aes.key_length = 128
25
+ aes.key = key
26
+ aes.encrypt(data)
27
+ end
28
+
29
+ def encrypt_transaction_key(key, transaction_key)
30
+ encrypt_by_rsa_public_key(key, transaction_key)
31
+ end
32
+
33
+ def hash(text, algorithm = 'sha256')
34
+ OpenSSL::Digest.digest(algorithm, text)
35
+ end
36
+
37
+ def calculate_digest(signature, algorithm = 'sha256')
38
+ exponent = signature.exponent.to_s(16)
39
+ modulus = signature.modulus.to_s(16)
40
+ key = calculate_key(exponent, modulus)
41
+
42
+ hash(key, algorithm)
43
+ end
44
+
45
+ def calculate_key(exponent, modulus)
46
+ [exponent.gsub(/^0*/,''), modulus.gsub(/^0*/,'')].map(&:downcase).join(' ')
47
+ end
48
+
49
+ def calculate_certificate_fingerprint(certificate, algorithm = 'sha256')
50
+ hash(certificate.to_der, algorithm)
51
+ end
52
+
53
+ private
54
+
55
+ def encrypt_by_rsa_public_key(key, data)
56
+ key.encrypt(data)
57
+ end
58
+
59
+ def encrypt_by_rsa(key, data)
60
+ key.private_encrypt(data)
61
+ end
62
+ end
@@ -0,0 +1,30 @@
1
+ class Epics::Services::DigestResolver::Base
2
+ def self.for_version(version)
3
+ case version
4
+ when Epics::Keyring::VERSION_24, Epics::Keyring::VERSION_25
5
+ Epics::Services::DigestResolver::V2.new
6
+ when Epics::Keyring::VERSION_30
7
+ Epics::Services::DigestResolver::V3.new
8
+ else
9
+ raise ArgumentError, "Unsupported EBICS version for DigestResolver: #{version}"
10
+ end
11
+ end
12
+
13
+ def initialize
14
+ @crypt_service = Epics::Services::CryptService.new
15
+ end
16
+
17
+ def sign_digest(signature, algorithm = 'sha256')
18
+ raise NotImplementedError
19
+ end
20
+
21
+ def confirm_digest(signature, algorithm = 'sha256')
22
+ raise NotImplementedError
23
+ end
24
+
25
+ private
26
+
27
+ def bin2hex(date)
28
+ date.unpack1('H*')
29
+ end
30
+ end
@@ -0,0 +1,13 @@
1
+ class Epics::Services::DigestResolver::V2 < Epics::Services::DigestResolver::Base
2
+ def sign_digest(signature, algorithm = 'sha256')
3
+ @crypt_service.calculate_digest(signature.key, algorithm)
4
+ end
5
+
6
+ def confirm_digest(signature, algorithm = 'sha256')
7
+ bin2hex(if signature.certificate
8
+ @crypt_service.calculate_certificate_fingerprint(signature.certificate, algorithm)
9
+ else
10
+ @crypt_service.calculate_digest(signature.key, algorithm)
11
+ end)
12
+ end
13
+ end
@@ -0,0 +1,19 @@
1
+ class Epics::Services::DigestResolver::V3 < Epics::Services::DigestResolver::Base
2
+ def sign_digest(signature, algorithm = 'sha256')
3
+ if signature.certificate
4
+ @crypt_service.calculate_certificate_fingerprint(signature.certificate, algorithm)
5
+ else
6
+ warn '[epics] WARNING: EBICS 3.0 sign_digest falling back to key-based digest ' \
7
+ "for #{signature.version}. Bank certificate may be missing -- consider running HPB."
8
+ @crypt_service.calculate_digest(signature.key, algorithm)
9
+ end
10
+ end
11
+
12
+ def confirm_digest(signature, algorithm = 'sha256')
13
+ bin2hex(if signature.certificate
14
+ @crypt_service.calculate_certificate_fingerprint(signature.certificate, algorithm)
15
+ else
16
+ @crypt_service.calculate_digest(signature.key, algorithm)
17
+ end)
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ module Epics::Services::DigestResolver
2
+ end
3
+
4
+ require 'epics/services/digest_resolver/base'
5
+ require 'epics/services/digest_resolver/v2'
6
+ require 'epics/services/digest_resolver/v3'
@@ -0,0 +1,5 @@
1
+ module Epics::Services
2
+ end
3
+
4
+ require 'epics/services/crypt_service'
5
+ require 'epics/services/digest_resolver'
@@ -0,0 +1,50 @@
1
+ class Epics::Signature
2
+ A_VERSION_5 = 'A005'
3
+ A_VERSION_6 = 'A006'
4
+ E_VERSION_2 = 'E002'
5
+ X_VERSION_2 = 'X002'
6
+
7
+ A_VERSIONS = [A_VERSION_5, A_VERSION_6]
8
+ E_VERSIONS = [E_VERSION_2]
9
+ X_VERSIONS = [X_VERSION_2]
10
+
11
+ TYPE_A = 'A'
12
+ TYPE_X = 'X'
13
+ TYPE_E = 'E'
14
+
15
+ TYPES = [TYPE_A, TYPE_X, TYPE_E]
16
+
17
+ attr_reader :type, :version
18
+ attr_accessor :key, :certificate
19
+
20
+ def initialize(version, key)
21
+ self.key = key
22
+ self.version = version
23
+ end
24
+
25
+ def version=(value)
26
+ @type = value[0]
27
+ raise UnknownTypeError, type unless TYPES.include?(type)
28
+
29
+ @version = value
30
+ raise UnknownVersionError, version unless self.class.const_get("#{type}_VERSIONS").include?(version)
31
+ end
32
+
33
+ class UnknownVersionError < StandardError
34
+ attr_reader :version
35
+
36
+ def initialize(version)
37
+ @version = version
38
+ super("Unsupported version: #{version}")
39
+ end
40
+ end
41
+
42
+ class UnknownTypeError < StandardError
43
+ attr_reader :type
44
+
45
+ def initialize(type)
46
+ @type = type
47
+ super("Unsupported type: #{type}")
48
+ end
49
+ end
50
+ end
@@ -1,12 +1,8 @@
1
- class Epics::Key
1
+ class Epics::SignatureAlgorithm::Base
2
2
  attr_accessor :key
3
3
 
4
4
  def initialize(encoded_key, passphrase = nil)
5
- if encoded_key.kind_of?(OpenSSL::PKey::RSA)
6
- self.key = encoded_key
7
- else
8
- self.key = OpenSSL::PKey::RSA.new(encoded_key)
9
- end
5
+ self.key = encoded_key
10
6
  end
11
7
 
12
8
  ###
@@ -15,33 +11,30 @@ class Epics::Key
15
11
  # calculate digest (SHA256)
16
12
  # encode as Base64
17
13
  ####
14
+ # TODO: remove this method
18
15
  def public_digest
19
16
  c = [ e.gsub(/^0*/,''), n.gsub(/^0*/,'') ].map(&:downcase).join(" ")
20
17
 
21
18
  Base64.encode64(digester.digest(c)).strip
22
19
  end
23
20
 
24
- def n
25
- self.key.n.to_s(16)
21
+ def exponent
22
+ raise NotImplementedError
26
23
  end
27
24
 
28
- def e
29
- self.key.e.to_s(16)
25
+ def modulus
26
+ raise NotImplementedError
30
27
  end
31
28
 
32
- def sign(msg)
33
- Base64.encode64(
34
- key.sign_pss(
35
- 'SHA256',
36
- msg,
37
- salt_length: :digest,
38
- mgf1_hash: 'SHA256',
39
- ),
40
- ).gsub("\n", '')
29
+ def encrypt(data)
30
+ raise NotImplementedError
41
31
  end
42
32
 
43
- def digester
44
- @digester ||= OpenSSL::Digest::SHA256.new
33
+ def sign(msg)
34
+ raise NotImplementedError
45
35
  end
46
36
 
37
+ def verify(signature, msg)
38
+ raise NotImplementedError
39
+ end
47
40
  end
@@ -0,0 +1,50 @@
1
+ class Epics::SignatureAlgorithm::Rsa < Epics::SignatureAlgorithm::Base
2
+ HASH_ALGORITHM = 'sha256'
3
+
4
+ def initialize(encoded_key, passphrase = nil)
5
+ if encoded_key.kind_of?(OpenSSL::PKey::RSA)
6
+ self.key = encoded_key
7
+ else
8
+ self.key = OpenSSL::PKey::RSA.new(encoded_key)
9
+ end
10
+ end
11
+
12
+ def exponent
13
+ key.e
14
+ end
15
+
16
+ # TODO: remove this method
17
+ def e
18
+ exponent.to_s(16)
19
+ end
20
+
21
+ def modulus
22
+ key.n
23
+ end
24
+
25
+ # TODO: remove this method
26
+ def n
27
+ modulus.to_s(16)
28
+ end
29
+
30
+ def mgf1_hash_algorithm
31
+ OpenSSL::Digest.new(HASH_ALGORITHM)
32
+ end
33
+
34
+ def hash_algorithm
35
+ OpenSSL::Digest.new(HASH_ALGORITHM)
36
+ end
37
+
38
+ def encrypt(data)
39
+ key.public_encrypt(data)
40
+ end
41
+
42
+ def private_encrypt(data)
43
+ key.private_encrypt(data)
44
+ end
45
+
46
+ # TODO: remove this method
47
+ def digester
48
+ @digester ||= OpenSSL::Digest::SHA256.new
49
+ end
50
+ end
@@ -0,0 +1,16 @@
1
+ class Epics::SignatureAlgorithm::RsaPkcs1 < Epics::SignatureAlgorithm::Rsa
2
+ def sign(msg)
3
+ key.sign(
4
+ hash_algorithm,
5
+ msg
6
+ )
7
+ end
8
+
9
+ def verify(signature, msg)
10
+ key.verify(
11
+ hash_algorithm,
12
+ Base64.decode64(signature),
13
+ msg
14
+ )
15
+ end
16
+ end
@@ -0,0 +1,20 @@
1
+ class Epics::SignatureAlgorithm::RsaPss < Epics::SignatureAlgorithm::Rsa
2
+ def sign(msg)
3
+ key.sign_pss(
4
+ hash_algorithm,
5
+ msg,
6
+ salt_length: :digest,
7
+ mgf1_hash: mgf1_hash_algorithm,
8
+ )
9
+ end
10
+
11
+ def verify(signature, msg)
12
+ key.verify_pss(
13
+ hash_algorithm,
14
+ Base64.decode64(signature),
15
+ msg,
16
+ salt_length: :digest,
17
+ mgf1_hash: mgf1_hash_algorithm,
18
+ )
19
+ end
20
+ end
@@ -0,0 +1,2 @@
1
+ module Epics::SignatureAlgorithm
2
+ end
data/lib/epics/sta.rb CHANGED
@@ -1,17 +1,6 @@
1
1
  class Epics::STA < Epics::GenericRequest
2
- def header
3
- client.header_request.build(
4
- nonce: nonce,
5
- timestamp: timestamp,
6
- order_type: 'STA',
7
- order_attribute: 'DZHNN',
8
- order_params: !!options[:from] && !!options[:to] ? {
9
- DateRange: {
10
- Start: options[:from],
11
- End: options[:to]
12
- }
13
- } : {},
14
- mutable: { TransactionPhase: 'Initialisation' }
15
- )
2
+ def to_xml
3
+ builder = request_factory.create_sta(options[:from], options[:to])
4
+ builder.to_xml
16
5
  end
17
6
  end
data/lib/epics/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Epics
4
- VERSION = '2.10.0'
4
+ VERSION = '3.0.0.rc1'
5
5
  end
data/lib/epics/vmk.rb CHANGED
@@ -1,17 +1,6 @@
1
1
  class Epics::VMK < Epics::GenericRequest
2
- def header
3
- client.header_request.build(
4
- nonce: nonce,
5
- timestamp: timestamp,
6
- order_type: 'VMK',
7
- order_attribute: 'DZHNN',
8
- order_params: !!options[:from] && !!options[:to] ? {
9
- DateRange: {
10
- Start: options[:from],
11
- End: options[:to]
12
- }
13
- } : {},
14
- mutable: { TransactionPhase: 'Initialisation' }
15
- )
2
+ def to_xml
3
+ builder = request_factory.create_vmk(options[:from], options[:to])
4
+ builder.to_xml
16
5
  end
17
6
  end
data/lib/epics/wss.rb CHANGED
@@ -1,13 +1,7 @@
1
1
  class Epics::WSS < Epics::GenericRequest
2
- def header
3
- client.header_request.build(
4
- nonce: nonce,
5
- timestamp: timestamp,
6
- order_type: 'WSS',
7
- order_attribute: 'DZHNN',
8
- order_params: {},
9
- mutable: { TransactionPhase: 'Initialisation' }
10
- )
2
+ def to_xml
3
+ builder = request_factory.create_wss
4
+ builder.to_xml
11
5
  end
12
6
  end
13
7
 
data/lib/epics/xct.rb CHANGED
@@ -1,13 +1,6 @@
1
1
  class Epics::XCT < Epics::GenericUploadRequest
2
- def header
3
- client.header_request.build(
4
- nonce: nonce,
5
- timestamp: timestamp,
6
- order_type: 'XCT',
7
- order_attribute: 'OZHNN',
8
- order_params: {},
9
- num_segments: 1,
10
- mutable: { TransactionPhase: 'Initialisation' }
11
- )
2
+ def to_xml
3
+ builder = request_factory.create_xct(document_digest, transaction_key, **options)
4
+ builder.to_xml
12
5
  end
13
6
  end
data/lib/epics/xds.rb CHANGED
@@ -1,13 +1,6 @@
1
1
  class Epics::XDS < Epics::GenericUploadRequest
2
- def header
3
- client.header_request.build(
4
- nonce: nonce,
5
- timestamp: timestamp,
6
- order_type: 'XDS',
7
- order_attribute: 'OZHNN',
8
- order_params: {},
9
- num_segments: 1,
10
- mutable: { TransactionPhase: 'Initialisation' }
11
- )
2
+ def to_xml
3
+ builder = request_factory.create_xds(document_digest, transaction_key, **options)
4
+ builder.to_xml
12
5
  end
13
6
  end
data/lib/epics/xe2.rb CHANGED
@@ -1,13 +1,6 @@
1
1
  class Epics::XE2 < Epics::GenericUploadRequest
2
- def header
3
- client.header_request.build(
4
- nonce: nonce,
5
- timestamp: timestamp,
6
- order_type: 'XE2',
7
- order_attribute: 'OZHNN',
8
- order_params: {},
9
- num_segments: 1,
10
- mutable: { TransactionPhase: 'Initialisation' }
11
- )
2
+ def to_xml
3
+ builder = request_factory.create_xe2(document_digest, transaction_key, **options)
4
+ builder.to_xml
12
5
  end
13
6
  end
data/lib/epics/xe3.rb CHANGED
@@ -1,13 +1,6 @@
1
1
  class Epics::XE3 < Epics::GenericUploadRequest
2
- def header
3
- client.header_request.build(
4
- nonce: nonce,
5
- timestamp: timestamp,
6
- order_type: 'XE3',
7
- order_attribute: 'OZHNN',
8
- order_params: {},
9
- num_segments: 1,
10
- mutable: { TransactionPhase: 'Initialisation' }
11
- )
2
+ def to_xml
3
+ builder = request_factory.create_xe3(document_digest, transaction_key, **options)
4
+ builder.to_xml
12
5
  end
13
6
  end
data/lib/epics/xek.rb ADDED
@@ -0,0 +1,5 @@
1
+ class Epics::XEK < Epics::GenericRequest
2
+ def to_xml
3
+ request_factory.create_xek(options[:from], options[:to], **service_options).to_xml
4
+ end
5
+ end
data/lib/epics/yct.rb ADDED
@@ -0,0 +1,6 @@
1
+ class Epics::YCT < Epics::GenericUploadRequest
2
+ def to_xml
3
+ builder = request_factory.create_yct(document_digest, transaction_key, **options)
4
+ builder.to_xml
5
+ end
6
+ end