as2 0.11.0 → 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +100 -17
- data/examples/server.rb +6 -0
- data/lib/as2/client.rb +8 -3
- data/lib/as2/config.rb +11 -1
- data/lib/as2/server.rb +1 -1
- data/lib/as2/version.rb +1 -1
- data/lib/as2.rb +48 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c823318d35a8e64297b050461d423414e07951268caa8fa1565fb5df4068b34f
|
4
|
+
data.tar.gz: 23322af75cf03f24e6a5df4d6d9b17e54ebdacd5a6569859a399cd1629f74735
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a81d120d47bb35d6be109ea7dc873757b3e6f54b4236383a52234d57509cd9ad205beecf0e07faf7965ea5d1a5182da019868e4202ef2eac3c4aee133800b517
|
7
|
+
data.tar.gz: 4367841d4bcb9f3376c3ba963a247b0e9036e5e6dae011d2819bd646f4864e9d4ffa4cd3da0decb8f7104913e70ef185ee050fd004b96063b95894a36710466f
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,8 @@
|
|
1
|
+
## 0.12.0 February 16, 2024
|
2
|
+
|
3
|
+
Allow configuration of which base64 encoding scheme to apply to outbound message bodies.
|
4
|
+
Improves compatibility with some versions of MuleSoft. [#36](https://github.com/alexdean/as2/pull/36)
|
5
|
+
|
1
6
|
## 0.11.0 September 14, 2023
|
2
7
|
|
3
8
|
* Allow configuration of which encryption cipher to use when sending outbound messages. [#35](https://github.com/alexdean/as2/pull/35)
|
data/README.md
CHANGED
@@ -14,23 +14,25 @@ and with [OpenAS2](https://github.com/OpenAS2/OpenAs2App).
|
|
14
14
|
These limitations may be removed over time as demand (and pull requests!) come
|
15
15
|
along.
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
17
|
+
RFC defines a number of optional features that partners can pick and choose
|
18
|
+
amongst. We currently have hard-coded options for many of these. Our current
|
19
|
+
choices are likely the most common ones in use, but we do not offer all the
|
20
|
+
configuration options needed for a fully-compliant implementation.
|
21
|
+
|
22
|
+
https://datatracker.ietf.org/doc/html/rfc4130#section-2.4.2
|
23
|
+
|
24
|
+
|
25
|
+
1. Encrypted or Unencrypted Data: We assume all messages are encrypted. An
|
26
|
+
error will result if partner sends us an unencrypted message.
|
27
|
+
2. Signed or Unsigned Data: We error if partner sends an unsigned message.
|
28
|
+
Partners can request unsigned MDNs, but we always send signed MDNs.
|
29
|
+
3. Optional Use of Receipt: We always send a receipt.
|
30
|
+
4. Use of Synchronous or Asynchronous Receipts: We do not support asynchronous
|
31
|
+
delivery of MDNs.
|
32
|
+
5. Security Formatting: We should be reasonably compliant here.
|
33
|
+
6. Hash Function, Message Digest Choices: We currently always use sha256 for
|
34
|
+
signing. Since [#20](https://github.com/alexdean/as2/pull/20) we have supported
|
35
|
+
allowing partners to request which algorithm we use for MIC generation in MDNs.
|
34
36
|
|
35
37
|
## Installation
|
36
38
|
|
@@ -48,6 +50,87 @@ Or install it yourself as:
|
|
48
50
|
|
49
51
|
$ gem install as2
|
50
52
|
|
53
|
+
## Configuration
|
54
|
+
|
55
|
+
Configuration objects need to be initialized for the local system and once for each partner.
|
56
|
+
|
57
|
+
See scripts in `examples` directory for more usage info.
|
58
|
+
|
59
|
+
A a certificate can be specified as either:
|
60
|
+
|
61
|
+
* a string path to a file containing a PEM-encoded X509 certificate
|
62
|
+
* or an instance of `OpenSSL::X509::Certificate`
|
63
|
+
|
64
|
+
A private key can be specified as either:
|
65
|
+
|
66
|
+
* a string path to a file containing a PEM-encoded private key
|
67
|
+
* or an instance of `OpenSSL::PKey::PKey`
|
68
|
+
|
69
|
+
### Local System
|
70
|
+
|
71
|
+
Supported options:
|
72
|
+
|
73
|
+
* `name`: AS2 id for the local system. (Used as `As2-From` in outbound messages.)
|
74
|
+
* `url`: URL of this system. Mainly for informational purposes.
|
75
|
+
* `domain`: DNS domain name of this system. Mainly for informational purposes.
|
76
|
+
* `certificate`: Certificate used for signing outbound messages.
|
77
|
+
* `pkey`: Private key used for decrypting incoming messages.
|
78
|
+
|
79
|
+
### Partners
|
80
|
+
|
81
|
+
Supported options:
|
82
|
+
|
83
|
+
* `name`: AS2 id for this partner. (Used as `As2-To` in outbound messages.)
|
84
|
+
* `url`: URL to POST outbound messages to.
|
85
|
+
* `certificate`: Certificate to use for both encryption and signature verification.
|
86
|
+
* If this is specified, it will be used for both `encryption_certificate` and `signing_certificate`.
|
87
|
+
* `encryption_certificate`: Certificate to use for encrypting outbound messages.
|
88
|
+
* Only required if `certificate` is not set.
|
89
|
+
* `signing_certificate`: Certificate to use when verifying signatures on incoming messages.
|
90
|
+
* Only required if `certificate` is not set.
|
91
|
+
* `encryption_cipher`: Cipher to use when encrypting outbound messages. A default value is used if this is not specified.
|
92
|
+
* Call `As2::Client.valid_encryption_ciphers` for valid options.
|
93
|
+
* `tls_verify_mode`: Optional. Set to `OpenSSL::SSL::VERIFY_NONE` if partner is using a self-signed certificate for HTTPS.
|
94
|
+
* `mdn_format`: Format to use when building MDNs to send to partners.
|
95
|
+
* `v0`: older/original format which is less compatible with other AS2 systems, but is the default for backwards-compatibility reasons.
|
96
|
+
* `v1`: improved format with better compatibility with other AS2 systems.
|
97
|
+
* `outbound_format`: Format to use when building outbound messages.
|
98
|
+
* `v0`: older/original format which is less compatible with other AS2 systems, but is the default for backwards-compatibility reasons.
|
99
|
+
* `v1`: improved format with better compatibility with other AS2 systems.
|
100
|
+
* `base64_scheme`: What type of base64 encoding to perform on outbound message bodies.
|
101
|
+
* `rfc4648`: older/original format which is less compatible with other AS2 systems, but is the default for backwards-compatibility reasons.
|
102
|
+
* `rfc2045`: format understood by more AS2 systems & recommended for new integrations.
|
103
|
+
|
104
|
+
### Example
|
105
|
+
|
106
|
+
```ruby
|
107
|
+
As2.configure do |conf|
|
108
|
+
conf.name = 'RUBYAS2'
|
109
|
+
conf.url = 'http://localhost:3000/as2'
|
110
|
+
conf.certificate = 'test/certificates/server.crt'
|
111
|
+
conf.pkey = 'test/certificates/server.key'
|
112
|
+
conf.domain = 'localhost'
|
113
|
+
|
114
|
+
conf.add_partner do |partner|
|
115
|
+
partner.name = 'MENDELSON'
|
116
|
+
partner.url = 'http://localhost:8080/as2/HttpReceiver'
|
117
|
+
partner.certificate = 'test/certificates/client.crt'
|
118
|
+
partner.outbound_format = 'v1'
|
119
|
+
partner.mdn_format = 'v1'
|
120
|
+
partner.base64_scheme = 'rfc2045'
|
121
|
+
end
|
122
|
+
|
123
|
+
conf.add_partner do |partner|
|
124
|
+
partner.name = 'OPENAS2'
|
125
|
+
partner.url = 'http://localhost:4088'
|
126
|
+
partner.certificate = 'test/certificates/client.crt'
|
127
|
+
partner.outbound_format = 'v1'
|
128
|
+
partner.mdn_format = 'v1'
|
129
|
+
partner.base64_scheme = 'rfc2045'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
```
|
133
|
+
|
51
134
|
## Usage
|
52
135
|
|
53
136
|
Generate self signed server certificate:
|
data/examples/server.rb
CHANGED
@@ -21,12 +21,18 @@ As2.configure do |conf|
|
|
21
21
|
partner.name = 'MENDELSON'
|
22
22
|
partner.url = 'http://localhost:8080/as2/HttpReceiver'
|
23
23
|
partner.certificate = 'test/certificates/client.crt'
|
24
|
+
partner.outbound_format = 'v1'
|
25
|
+
partner.mdn_format = 'v1'
|
26
|
+
partner.base64_scheme = 'rfc2045'
|
24
27
|
end
|
25
28
|
|
26
29
|
conf.add_partner do |partner|
|
27
30
|
partner.name = 'OPENAS2'
|
28
31
|
partner.url = 'http://localhost:4088'
|
29
32
|
partner.certificate = 'test/certificates/client.crt'
|
33
|
+
partner.outbound_format = 'v1'
|
34
|
+
partner.mdn_format = 'v1'
|
35
|
+
partner.base64_scheme = 'rfc2045'
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
data/lib/as2/client.rb
CHANGED
@@ -172,7 +172,7 @@ module As2
|
|
172
172
|
document_payload << "Content-Transfer-Encoding: base64\r\n"
|
173
173
|
document_payload << "Content-Disposition: attachment; filename=#{file_name}\r\n"
|
174
174
|
document_payload << "\r\n"
|
175
|
-
document_payload <<
|
175
|
+
document_payload << base64_encode(document_content)
|
176
176
|
|
177
177
|
signature = OpenSSL::PKCS7.sign(@server_info.certificate, @server_info.pkey, document_payload)
|
178
178
|
signature.detached = true
|
@@ -201,7 +201,7 @@ module As2
|
|
201
201
|
document_payload << "Content-Transfer-Encoding: base64\r\n"
|
202
202
|
document_payload << "Content-Disposition: attachment; filename=#{file_name}\r\n"
|
203
203
|
document_payload << "\r\n"
|
204
|
-
document_payload <<
|
204
|
+
document_payload << base64_encode(document_content)
|
205
205
|
|
206
206
|
signature = OpenSSL::PKCS7.sign(@server_info.certificate, @server_info.pkey, document_payload)
|
207
207
|
signature.detached = true
|
@@ -211,7 +211,7 @@ module As2
|
|
211
211
|
# strip off the '-----BEGIN PKCS7-----' / '-----END PKCS7-----' delimiters
|
212
212
|
bare_pem_signature.gsub!(/^-----[^\n]+\n/, '')
|
213
213
|
# and update to canonical \r\n line endings
|
214
|
-
bare_pem_signature.
|
214
|
+
bare_pem_signature = As2.canonicalize_line_endings(bare_pem_signature)
|
215
215
|
|
216
216
|
# this is a hack until i can determine a better way to get the micalg parameter
|
217
217
|
# from the pkcs7 signature generated above...
|
@@ -315,6 +315,11 @@ module As2
|
|
315
315
|
|
316
316
|
private
|
317
317
|
|
318
|
+
def base64_encode(content)
|
319
|
+
encoded = As2.base64_encode(content, scheme: @partner.base64_scheme)
|
320
|
+
As2.canonicalize_line_endings(encoded)
|
321
|
+
end
|
322
|
+
|
318
323
|
# extract the MDN body from a multipart/signed wrapper & attempt to verify
|
319
324
|
# the signature
|
320
325
|
#
|
data/lib/as2/config.rb
CHANGED
@@ -12,10 +12,20 @@ module As2
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
class Partner < Struct.new :name, :url, :encryption_certificate, :encryption_cipher, :signing_certificate, :tls_verify_mode, :mdn_format, :outbound_format
|
15
|
+
class Partner < Struct.new :name, :url, :encryption_certificate, :encryption_cipher, :signing_certificate, :tls_verify_mode, :mdn_format, :outbound_format, :base64_scheme
|
16
16
|
def initialize
|
17
17
|
# set default.
|
18
18
|
self.encryption_cipher = 'aes-256-cbc'
|
19
|
+
self.base64_scheme = 'rfc4648'
|
20
|
+
end
|
21
|
+
|
22
|
+
def base64_scheme=(scheme)
|
23
|
+
scheme_s = scheme.to_s
|
24
|
+
valid_schemes = As2.valid_base64_schemes
|
25
|
+
if !valid_schemes.include?(scheme_s)
|
26
|
+
raise ArgumentError, "base64_scheme '#{scheme_s}' must be one of #{valid_schemes.inspect}"
|
27
|
+
end
|
28
|
+
self['base64_scheme'] = scheme_s
|
19
29
|
end
|
20
30
|
|
21
31
|
def url=(url)
|
data/lib/as2/server.rb
CHANGED
@@ -165,7 +165,7 @@ module As2
|
|
165
165
|
# strip off the '-----BEGIN PKCS7-----' / '-----END PKCS7-----' delimiters
|
166
166
|
bare_pem_signature.gsub!(/^-----[^\n]+\n/, '')
|
167
167
|
# and update to canonical \r\n line endings
|
168
|
-
bare_pem_signature.
|
168
|
+
bare_pem_signature = As2.canonicalize_line_endings(bare_pem_signature)
|
169
169
|
|
170
170
|
# this is a hack until i can determine a better way to get the micalg parameter
|
171
171
|
# from the pkcs7 signature generated above...
|
data/lib/as2/version.rb
CHANGED
data/lib/as2.rb
CHANGED
@@ -23,6 +23,54 @@ module As2
|
|
23
23
|
"<#{server_info.name}-#{Time.now.strftime('%Y%m%d-%H%M%S')}-#{SecureRandom.uuid}@#{server_info.domain}>"
|
24
24
|
end
|
25
25
|
|
26
|
+
def self.valid_base64_schemes
|
27
|
+
[
|
28
|
+
'rfc2045',
|
29
|
+
'rfc4648'
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
# create a base64 string from content, based on the given encoding scheme
|
34
|
+
#
|
35
|
+
# @param [String] content
|
36
|
+
# @param [String] scheme one of As2.valid_base64_schemes
|
37
|
+
# @return [String]
|
38
|
+
def self.base64_encode(content, scheme: 'rfc4648')
|
39
|
+
case scheme.to_s
|
40
|
+
when 'rfc2045'
|
41
|
+
# "This method complies with RFC 2045."
|
42
|
+
# https://ruby-doc.org/stdlib-3.0.4/libdoc/base64/rdoc/Base64.html#method-i-encode64
|
43
|
+
# https://www.rfc-editor.org/rfc/rfc2045#section-6.8
|
44
|
+
then Base64.encode64(content)
|
45
|
+
when 'rfc4648'
|
46
|
+
# "This method complies with RFC 4648."
|
47
|
+
# https://ruby-doc.org/stdlib-3.0.4/libdoc/base64/rdoc/Base64.html#method-i-strict_encode64
|
48
|
+
# https://www.rfc-editor.org/rfc/rfc4648#section-4
|
49
|
+
then Base64.strict_encode64(content)
|
50
|
+
else
|
51
|
+
raise ArgumentError, "unsupported scheme '#{scheme}'. choose one of: #{valid_base64_schemes}"
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# canonicalize all line endings in the given text.
|
56
|
+
#
|
57
|
+
# "\n" becomes "\r\n"
|
58
|
+
# "\r\n" remains "\r\n"
|
59
|
+
#
|
60
|
+
# Conversion to canonical form:
|
61
|
+
# The entire body ... is converted to a universal canonical
|
62
|
+
# form. ... For example, in the case of text/plain data, the text
|
63
|
+
# must be converted to a supported character set and lines must
|
64
|
+
# be delimited with CRLF delimiters in accordance with RFC 822.
|
65
|
+
#
|
66
|
+
# https://www.rfc-editor.org/rfc/rfc2049#page-9
|
67
|
+
#
|
68
|
+
# @param [String] content
|
69
|
+
# @return [String] content, but with all bare \n replaced by \r\n
|
70
|
+
def self.canonicalize_line_endings(content)
|
71
|
+
content.gsub(/(?<!\r)\n/, "\r\n")
|
72
|
+
end
|
73
|
+
|
26
74
|
# Select which algorithm to use for calculating a MIC, based on preferences
|
27
75
|
# stated by sender & our list of available algorithms.
|
28
76
|
#
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: as2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.12.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- OfficeLuv
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: exe
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2024-02-16 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mail
|
@@ -205,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
205
205
|
- !ruby/object:Gem::Version
|
206
206
|
version: '0'
|
207
207
|
requirements: []
|
208
|
-
rubygems_version: 3.
|
208
|
+
rubygems_version: 3.4.10
|
209
209
|
signing_key:
|
210
210
|
specification_version: 4
|
211
211
|
summary: Simple AS2 server and client implementation
|