as2 0.9.0 → 0.10.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 +13 -0
- data/lib/as2/client.rb +5 -5
- data/lib/as2/config.rb +20 -5
- data/lib/as2/message.rb +9 -9
- data/lib/as2/server.rb +2 -2
- data/lib/as2/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7e21a1d3326b7db528a205964fb6c5e99656ea20e4ad7dcba0877088fdd86104
|
4
|
+
data.tar.gz: c46538361b3cdb28f6b97a602465adea7dea2f348dbdc54fd18c33ca7a496801
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52189a26063743097ea72abfe0b12e21866417ab60af8633b581eab7c1902ebb32bf904538daf4301f5320c0cbfd730d94c1aa14f6a365d0ea270158f649565c
|
7
|
+
data.tar.gz: ec40485fcd9e7f7f38cbc3649c3b7c84986ebc1be2242a3208c9563d42bea239fb8d4f38a73bd0ce580e54e2371890a45689d138b55c5eccc0c489b6c7526a45
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
## 0.10.0 September 13, 2023
|
2
|
+
|
3
|
+
support for separate signing & encryption certificates for partners. [#34](https://github.com/alexdean/as2/pull/34)
|
4
|
+
|
5
|
+
BREAKING CHANGES:
|
6
|
+
|
7
|
+
* `As2::Config::Partner`
|
8
|
+
* Added `signing_certificate` and `encryption_certificate`
|
9
|
+
* Removed `certificate`.
|
10
|
+
* `certificate=` is still supported, and assigns the same certificate to both.
|
11
|
+
* `As2::Client#parse_signed_mdn`: requires `signing_certificate:` rather than `certificate:`.
|
12
|
+
* `As2::Message.verify`: requires `signing_certificate:` rather than `certificate:`.
|
13
|
+
|
1
14
|
## 0.9.0, August 28, 2023
|
2
15
|
|
3
16
|
* Bugfix for quoting AS2-From/AS2-To identifiers
|
data/lib/as2/client.rb
CHANGED
@@ -83,7 +83,7 @@ module As2
|
|
83
83
|
)
|
84
84
|
|
85
85
|
cipher = OpenSSL::Cipher::AES256.new(:CBC) # default, but we might have to make this configurable
|
86
|
-
encrypted = OpenSSL::PKCS7.encrypt([@partner.
|
86
|
+
encrypted = OpenSSL::PKCS7.encrypt([@partner.encryption_certificate], request_body, cipher)
|
87
87
|
|
88
88
|
# > HTTP can handle binary data and so there is no need to use the
|
89
89
|
# > content transfer encodings of MIME
|
@@ -257,7 +257,7 @@ module As2
|
|
257
257
|
if mdn_content_type.start_with?('multipart/signed')
|
258
258
|
result = parse_signed_mdn(
|
259
259
|
multipart_signed_message: response_content,
|
260
|
-
|
260
|
+
signing_certificate: @partner.signing_certificate
|
261
261
|
)
|
262
262
|
mdn_report = result[:mdn_report]
|
263
263
|
report[:signature_verification_error] = result[:signature_verification_error]
|
@@ -314,7 +314,7 @@ module As2
|
|
314
314
|
# * :mdn_mime_body [Mail::Message] The 'inner' MDN body, with signature removed
|
315
315
|
# * :signature_verification_error [String] Any error which resulted when checking the
|
316
316
|
# signature. If this is empty it means the signature was valid.
|
317
|
-
def parse_signed_mdn(multipart_signed_message:,
|
317
|
+
def parse_signed_mdn(multipart_signed_message:, signing_certificate:)
|
318
318
|
smime = nil
|
319
319
|
|
320
320
|
begin
|
@@ -347,7 +347,7 @@ module As2
|
|
347
347
|
# based on As2::Message version
|
348
348
|
# TODO: test cases based on valid/invalid responses. (response signed with wrong certificate, etc.)
|
349
349
|
# See notes in As2::Message.verify for reasoning on flag usage
|
350
|
-
smime.verify [
|
350
|
+
smime.verify [signing_certificate], OpenSSL::X509::Store.new, nil, OpenSSL::PKCS7::NOVERIFY | OpenSSL::PKCS7::NOINTERN
|
351
351
|
|
352
352
|
signature_verification_error = smime.error_string
|
353
353
|
else
|
@@ -383,7 +383,7 @@ module As2
|
|
383
383
|
result = As2::Message.verify(
|
384
384
|
content: content,
|
385
385
|
signature_text: signature_text,
|
386
|
-
|
386
|
+
signing_certificate: signing_certificate
|
387
387
|
)
|
388
388
|
|
389
389
|
signature_verification_error = result[:error]
|
data/lib/as2/config.rb
CHANGED
@@ -12,7 +12,7 @@ module As2
|
|
12
12
|
end
|
13
13
|
end
|
14
14
|
|
15
|
-
class Partner < Struct.new :name, :url, :
|
15
|
+
class Partner < Struct.new :name, :url, :encryption_certificate, :signing_certificate, :tls_verify_mode, :mdn_format, :outbound_format
|
16
16
|
def url=(url)
|
17
17
|
if url.kind_of? String
|
18
18
|
self['url'] = URI.parse url
|
@@ -40,7 +40,17 @@ module As2
|
|
40
40
|
end
|
41
41
|
|
42
42
|
def certificate=(certificate)
|
43
|
-
|
43
|
+
cert = As2::Config.build_certificate(certificate)
|
44
|
+
self['encryption_certificate'] = cert
|
45
|
+
self['signing_certificate'] = cert
|
46
|
+
end
|
47
|
+
|
48
|
+
def encryption_certificate=(certificate)
|
49
|
+
self['encryption_certificate'] = As2::Config.build_certificate(certificate)
|
50
|
+
end
|
51
|
+
|
52
|
+
def signing_certificate=(certificate)
|
53
|
+
self['signing_certificate'] = As2::Config.build_certificate(certificate)
|
44
54
|
end
|
45
55
|
|
46
56
|
# if set, will be used for SSL transmissions.
|
@@ -87,14 +97,18 @@ module As2
|
|
87
97
|
unless partner.name
|
88
98
|
raise 'Partner name is required'
|
89
99
|
end
|
90
|
-
unless partner.
|
91
|
-
raise 'Partner certificate is required'
|
100
|
+
unless partner.signing_certificate
|
101
|
+
raise 'Partner signing certificate is required'
|
102
|
+
end
|
103
|
+
unless partner.encryption_certificate
|
104
|
+
raise 'Partner encryption certificate is required'
|
92
105
|
end
|
93
106
|
unless partner.url
|
94
107
|
raise 'Partner URL is required'
|
95
108
|
end
|
96
109
|
Config.partners[partner.name] = partner
|
97
|
-
Config.store.add_cert partner.
|
110
|
+
Config.store.add_cert partner.signing_certificate
|
111
|
+
Config.store.add_cert partner.encryption_certificate
|
98
112
|
end
|
99
113
|
end
|
100
114
|
|
@@ -123,6 +137,7 @@ module As2
|
|
123
137
|
@partners ||= {}
|
124
138
|
end
|
125
139
|
|
140
|
+
# TODO: deprecate this.
|
126
141
|
def store
|
127
142
|
@store ||= OpenSSL::X509::Store.new
|
128
143
|
end
|
data/lib/as2/message.rb
CHANGED
@@ -53,7 +53,7 @@ module As2
|
|
53
53
|
# * :valid [boolean] was the verification successful or not?
|
54
54
|
# * :error [String, nil] a verification error message.
|
55
55
|
# will be empty when `valid` is true.
|
56
|
-
def self.verify(content:, signature_text:,
|
56
|
+
def self.verify(content:, signature_text:, signing_certificate:)
|
57
57
|
begin
|
58
58
|
signature = OpenSSL::PKCS7.new(signature_text)
|
59
59
|
|
@@ -76,9 +76,9 @@ module As2
|
|
76
76
|
#
|
77
77
|
# https://www.openssl.org/docs/manmaster/man3/PKCS7_verify.html
|
78
78
|
#
|
79
|
-
# we want this so we can be sure that the `
|
79
|
+
# we want this so we can be sure that the `signing_certificate` we supply
|
80
80
|
# was actually used to sign the message. otherwise we could get a positive
|
81
|
-
# verification even if `
|
81
|
+
# verification even if `signing_certificate` didn't sign the message
|
82
82
|
# we're checking.
|
83
83
|
#
|
84
84
|
# ## NOVERIFY
|
@@ -87,9 +87,9 @@ module As2
|
|
87
87
|
#
|
88
88
|
# ie: we won't attempt to connect signer (in the first param) to a root
|
89
89
|
# CA (in `store`, which is empty). alternately, we could instead remove
|
90
|
-
# this flag, and add `
|
91
|
-
# we'd only be verifying that `
|
92
|
-
valid = signature.verify([
|
90
|
+
# this flag, and add `signing_certificate` to `store`. but what's the point?
|
91
|
+
# we'd only be verifying that `signing_certificate` is connected to `signing_certificate`.
|
92
|
+
valid = signature.verify([signing_certificate], store, content, OpenSSL::PKCS7::NOVERIFY | OpenSSL::PKCS7::NOINTERN)
|
93
93
|
|
94
94
|
# when `signature.verify` fails, signature.error_string will be populated.
|
95
95
|
error = signature.error_string
|
@@ -121,7 +121,7 @@ module As2
|
|
121
121
|
@decrypted_message ||= @pkcs7.decrypt @private_key, @public_certificate
|
122
122
|
end
|
123
123
|
|
124
|
-
def valid_signature?(
|
124
|
+
def valid_signature?(partner_signing_certificate)
|
125
125
|
content_type = mail.header_fields.find { |h| h.name == 'Content-Type' }.content_type
|
126
126
|
# TODO: substantial overlap between this code & the fallback/rescue code in
|
127
127
|
# As2::Client#verify_mdn_signature
|
@@ -149,7 +149,7 @@ module As2
|
|
149
149
|
result = self.class.verify(
|
150
150
|
content: content,
|
151
151
|
signature_text: signature_text,
|
152
|
-
|
152
|
+
signing_certificate: partner_signing_certificate
|
153
153
|
)
|
154
154
|
|
155
155
|
output = result[:valid]
|
@@ -186,7 +186,7 @@ module As2
|
|
186
186
|
retry_output = self.class.verify(
|
187
187
|
content: content,
|
188
188
|
signature_text: signature_text,
|
189
|
-
|
189
|
+
signing_certificate: partner_signing_certificate
|
190
190
|
)
|
191
191
|
|
192
192
|
if retry_output[:valid]
|
data/lib/as2/server.rb
CHANGED
@@ -40,7 +40,7 @@ module As2
|
|
40
40
|
request = Rack::Request.new(env)
|
41
41
|
message = Message.new(request.body.read, @server_info.pkey, @server_info.certificate)
|
42
42
|
|
43
|
-
unless message.valid_signature?(partner.
|
43
|
+
unless message.valid_signature?(partner.signing_certificate)
|
44
44
|
if @signature_failure_handler
|
45
45
|
@signature_failure_handler.call({
|
46
46
|
env: env,
|
@@ -48,7 +48,7 @@ module As2
|
|
48
48
|
verification_error: message.verification_error
|
49
49
|
})
|
50
50
|
else
|
51
|
-
raise "Could not verify signature"
|
51
|
+
raise "Could not verify signature. #{message.verification_error}"
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
data/lib/as2/version.rb
CHANGED
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.10.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: 2023-
|
12
|
+
date: 2023-09-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: mail
|