as2 0.11.0 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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
|