signer 1.5.0 → 1.5.1
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 +4 -0
- data/README.md +6 -1
- data/lib/signer.rb +32 -5
- data/lib/signer/version.rb +1 -1
- data/spec/fixtures/output_2_with_ds_prefix.xml +31 -0
- data/spec/signer_spec.rb +22 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a37c55f9fdbf134383fd475503fbd47cee739f42
|
4
|
+
data.tar.gz: 60999a93aa7427c4a132c75985a915f7d18a2995
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 47fdf2988627bbf355ac5ab6a1ffe80bbe660d7bd6315ec65c3ed96978191653d1f3919270b960685364487910f846970e21f00738c456affea72b6d31695378
|
7
|
+
data.tar.gz: 00e6ba00e46ab22ef6a9029d0cc1f28b00c04a8b90cfd2a512a84b2d444bea9b627806d5059efd74f7f66312e8b0465adeb66716abb5733941268ab83b87dfb7
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -229,9 +229,14 @@ signer.sign! # No need to pass a :security_token option, as we already construct
|
|
229
229
|
|
230
230
|
If you need to use canonicalization with inclusive namespaces you can pass array of namespace prefixes in `:inclusive_namespaces` option in both `digest!` and `sign!` methods.
|
231
231
|
|
232
|
+
If you need `Signature` tags to be in explicit namespace (say, `<ds:Signature>`) instead of to be in implicit default namespace you can specify next option:
|
233
|
+
|
234
|
+
```ruby
|
235
|
+
signer.ds_namespace_prefix = 'ds'
|
236
|
+
```
|
232
237
|
|
233
238
|
Every new instance of signer has Nokogiri `noblanks` set as default in process of parsing xml file. If you need to disable it, pass opional argument `noblanks: false`.
|
234
239
|
|
235
|
-
```
|
240
|
+
```ruby
|
236
241
|
Signer.new(File.read("example.xml"), noblanks: false)
|
237
242
|
```
|
data/lib/signer.rb
CHANGED
@@ -7,12 +7,13 @@ require "signer/digester"
|
|
7
7
|
require "signer/version"
|
8
8
|
|
9
9
|
class Signer
|
10
|
-
attr_accessor :document, :private_key, :signature_algorithm_id
|
10
|
+
attr_accessor :document, :private_key, :signature_algorithm_id, :ds_namespace_prefix
|
11
11
|
attr_reader :cert
|
12
12
|
attr_writer :security_node, :signature_node, :security_token_id
|
13
13
|
|
14
14
|
WSU_NAMESPACE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
|
15
15
|
WSSE_NAMESPACE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
|
16
|
+
DS_NAMESPACE = 'http://www.w3.org/2000/09/xmldsig#'
|
16
17
|
|
17
18
|
def initialize(document, noblanks: true)
|
18
19
|
self.document = Nokogiri::XML(document.to_s) do |config|
|
@@ -81,10 +82,10 @@ class Signer
|
|
81
82
|
# <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
82
83
|
def signature_node
|
83
84
|
@signature_node ||= begin
|
84
|
-
@signature_node = security_node.at_xpath('ds:Signature', ds:
|
85
|
+
@signature_node = security_node.at_xpath('ds:Signature', ds: DS_NAMESPACE)
|
85
86
|
unless @signature_node
|
86
87
|
@signature_node = Nokogiri::XML::Node.new('Signature', document)
|
87
|
-
@signature_node
|
88
|
+
set_namespace_for_node(@signature_node, DS_NAMESPACE, ds_namespace_prefix)
|
88
89
|
security_node.add_child(@signature_node)
|
89
90
|
end
|
90
91
|
@signature_node
|
@@ -97,16 +98,19 @@ class Signer
|
|
97
98
|
# ...
|
98
99
|
# </SignedInfo>
|
99
100
|
def signed_info_node
|
100
|
-
node = signature_node.at_xpath('ds:SignedInfo', ds:
|
101
|
+
node = signature_node.at_xpath('ds:SignedInfo', ds: DS_NAMESPACE)
|
101
102
|
unless node
|
102
103
|
node = Nokogiri::XML::Node.new('SignedInfo', document)
|
103
104
|
signature_node.add_child(node)
|
105
|
+
set_namespace_for_node(node, DS_NAMESPACE, ds_namespace_prefix)
|
104
106
|
canonicalization_method_node = Nokogiri::XML::Node.new('CanonicalizationMethod', document)
|
105
107
|
canonicalization_method_node['Algorithm'] = 'http://www.w3.org/2001/10/xml-exc-c14n#'
|
106
108
|
node.add_child(canonicalization_method_node)
|
109
|
+
set_namespace_for_node(canonicalization_method_node, DS_NAMESPACE, ds_namespace_prefix)
|
107
110
|
signature_method_node = Nokogiri::XML::Node.new('SignatureMethod', document)
|
108
111
|
signature_method_node['Algorithm'] = self.signature_algorithm_id
|
109
112
|
node.add_child(signature_method_node)
|
113
|
+
set_namespace_for_node(signature_method_node, DS_NAMESPACE, ds_namespace_prefix)
|
110
114
|
end
|
111
115
|
node
|
112
116
|
end
|
@@ -136,6 +140,7 @@ class Signer
|
|
136
140
|
key_info_node = Nokogiri::XML::Node.new('KeyInfo', document)
|
137
141
|
security_token_reference_node = Nokogiri::XML::Node.new("#{wsse_ns}:SecurityTokenReference", document)
|
138
142
|
key_info_node.add_child(security_token_reference_node)
|
143
|
+
set_namespace_for_node(key_info_node, DS_NAMESPACE, ds_namespace_prefix)
|
139
144
|
reference_node = Nokogiri::XML::Node.new("#{wsse_ns}:Reference", document)
|
140
145
|
reference_node['ValueType'] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3'
|
141
146
|
reference_node['URI'] = "##{security_token_id}"
|
@@ -177,6 +182,13 @@ class Signer
|
|
177
182
|
|
178
183
|
signed_info_node.add_next_sibling(key_info_node)
|
179
184
|
|
185
|
+
set_namespace_for_node(key_info_node, DS_NAMESPACE, ds_namespace_prefix)
|
186
|
+
set_namespace_for_node(data_node, DS_NAMESPACE, ds_namespace_prefix)
|
187
|
+
set_namespace_for_node(issuer_serial_node, DS_NAMESPACE, ds_namespace_prefix)
|
188
|
+
set_namespace_for_node(cetificate_node, DS_NAMESPACE, ds_namespace_prefix)
|
189
|
+
set_namespace_for_node(issuer_name_node, DS_NAMESPACE, ds_namespace_prefix)
|
190
|
+
set_namespace_for_node(issuer_number_node, DS_NAMESPACE, ds_namespace_prefix)
|
191
|
+
|
180
192
|
data_node
|
181
193
|
end
|
182
194
|
|
@@ -215,11 +227,14 @@ class Signer
|
|
215
227
|
reference_node = Nokogiri::XML::Node.new('Reference', document)
|
216
228
|
reference_node['URI'] = id.to_s.size > 0 ? "##{id}" : ""
|
217
229
|
signed_info_node.add_child(reference_node)
|
230
|
+
set_namespace_for_node(reference_node, DS_NAMESPACE, ds_namespace_prefix)
|
218
231
|
|
219
232
|
transforms_node = Nokogiri::XML::Node.new('Transforms', document)
|
220
233
|
reference_node.add_child(transforms_node)
|
234
|
+
set_namespace_for_node(transforms_node, DS_NAMESPACE, ds_namespace_prefix)
|
221
235
|
|
222
236
|
transform_node = Nokogiri::XML::Node.new('Transform', document)
|
237
|
+
set_namespace_for_node(transform_node, DS_NAMESPACE, ds_namespace_prefix)
|
223
238
|
if options[:enveloped]
|
224
239
|
transform_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'
|
225
240
|
else
|
@@ -236,10 +251,12 @@ class Signer
|
|
236
251
|
digest_method_node = Nokogiri::XML::Node.new('DigestMethod', document)
|
237
252
|
digest_method_node['Algorithm'] = @digester.digest_id
|
238
253
|
reference_node.add_child(digest_method_node)
|
254
|
+
set_namespace_for_node(digest_method_node, DS_NAMESPACE, ds_namespace_prefix)
|
239
255
|
|
240
256
|
digest_value_node = Nokogiri::XML::Node.new('DigestValue', document)
|
241
257
|
digest_value_node.content = target_digest
|
242
258
|
reference_node.add_child(digest_value_node)
|
259
|
+
set_namespace_for_node(digest_value_node, DS_NAMESPACE, ds_namespace_prefix)
|
243
260
|
self
|
244
261
|
end
|
245
262
|
|
@@ -263,7 +280,7 @@ class Signer
|
|
263
280
|
end
|
264
281
|
|
265
282
|
if options[:inclusive_namespaces]
|
266
|
-
c14n_method_node = signed_info_node.at_xpath('ds:CanonicalizationMethod', ds:
|
283
|
+
c14n_method_node = signed_info_node.at_xpath('ds:CanonicalizationMethod', ds: DS_NAMESPACE)
|
267
284
|
inclusive_namespaces_node = Nokogiri::XML::Node.new('ec:InclusiveNamespaces', document)
|
268
285
|
inclusive_namespaces_node.add_namespace_definition('ec', c14n_method_node['Algorithm'])
|
269
286
|
inclusive_namespaces_node['PrefixList'] = options[:inclusive_namespaces].join(' ')
|
@@ -278,6 +295,7 @@ class Signer
|
|
278
295
|
signature_value_node = Nokogiri::XML::Node.new('SignatureValue', document)
|
279
296
|
signature_value_node.content = signature_value_digest
|
280
297
|
signed_info_node.add_next_sibling(signature_value_node)
|
298
|
+
set_namespace_for_node(signature_value_node, DS_NAMESPACE, ds_namespace_prefix)
|
281
299
|
self
|
282
300
|
end
|
283
301
|
|
@@ -306,4 +324,13 @@ class Signer
|
|
306
324
|
end
|
307
325
|
end
|
308
326
|
|
327
|
+
##
|
328
|
+
# Searches for namespace with given +href+ within +node+ ancestors and assigns it to this node.
|
329
|
+
# If there is no such namespace, it will create it with +desired_prefix+ if present or as default namespace otherwise.
|
330
|
+
# In most cases you should insert +node+ in the document tree before calling this method to avoid duplicating namespace definitions
|
331
|
+
def set_namespace_for_node(node, href, desired_prefix = nil)
|
332
|
+
return node.namespace if node.namespace && node.namespace.href == href # This node already in target namespace, done
|
333
|
+
namespace = node.namespace_scopes.find { |ns| ns.href == href }
|
334
|
+
node.namespace = namespace || node.add_namespace_definition(desired_prefix, href)
|
335
|
+
end
|
309
336
|
end
|
data/lib/signer/version.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
<?xml version="1.0"?>
|
2
|
+
<ApplicationRequest xmlns="http://bxd.fi/xmldata/">
|
3
|
+
<CustomerId>679155330</CustomerId>
|
4
|
+
<Command>GetUserInfo</Command>
|
5
|
+
<Timestamp>2010-05-10T13:22:19.847+03:00</Timestamp>
|
6
|
+
<Environment>PRODUCTION</Environment>
|
7
|
+
<SoftwareId>Petri</SoftwareId>
|
8
|
+
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
|
9
|
+
<ds:SignedInfo>
|
10
|
+
<ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
|
11
|
+
<ds:SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
|
12
|
+
<ds:Reference URI="">
|
13
|
+
<ds:Transforms>
|
14
|
+
<ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
|
15
|
+
</ds:Transforms>
|
16
|
+
<ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
|
17
|
+
<ds:DigestValue>U9tsT4lrRMp8ZdKMnblgeMCGfvI=</ds:DigestValue>
|
18
|
+
</ds:Reference>
|
19
|
+
</ds:SignedInfo>
|
20
|
+
<ds:SignatureValue>rOCe8McbIFa4Ul3pnzd/dBjFWoT4JtSghJgzZGLrz17K/j0W1JyaopcZeMD+8M5/GplAlQrJg3ZSkQvY9Sf7WpqZeLYHW17J0ZJpwas+/OOXUEdyUiec7q9OgWsFLH9DBNuJdLKE3CO6w/8tTKQ/kidYnPBXT6FKioNlSJVZsuI=</ds:SignatureValue>
|
21
|
+
<ds:KeyInfo>
|
22
|
+
<ds:X509Data>
|
23
|
+
<ds:X509IssuerSerial>
|
24
|
+
<ds:X509IssuerName>C=AU,ST=Some-State,O=Internet Widgits Pty Ltd</ds:X509IssuerName>
|
25
|
+
<ds:X509SerialNumber>16503368396260674861</ds:X509SerialNumber>
|
26
|
+
</ds:X509IssuerSerial>
|
27
|
+
<ds:X509Certificate>MIICsDCCAhmgAwIBAgIJAOUHvh4oho0tMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTIwNTAzMTMxODIyWhcNMTMwNTAzMTMxODIyWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvK5hMPv/R5IFmwWyJOyEaFUrF/ZsmN+Gip8hvR6rLP3YPNx9iFYvPcZllFmuVwyaz7YT2N5BsqTwLdyi5v4HY4fUtuz0p8jIPoSd6dfDvcnSpf4QLTOgOaL3ciPEbgDHH2tnIksukoWzqCYva+qFZ74NFl19swXotW9fA4Jzs4QIDAQABo4GnMIGkMB0GA1UdDgQWBBRU1WEHDnP8Hr7ZulxrSzEwOcYpMzB1BgNVHSMEbjBsgBRU1WEHDnP8Hr7ZulxrSzEwOcYpM6FJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAOUHvh4oho0tMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEASY/9SAOK57q9mGnNJJeyDbmyGrAHSJTod646xTHYkMvhUqwHyk9PTr5bdfmswpmyVn+AQ43U2tU5vnpTBmKpHWD2+HSHgGa92mMLrfBOd8EBZ329NL3N2HDPIaHr4NPGyhNrSK3QVOnAq2D0jlyrGYJlLli1NxHiBz7FCEJaVI8=</ds:X509Certificate>
|
28
|
+
</ds:X509Data>
|
29
|
+
</ds:KeyInfo>
|
30
|
+
</ds:Signature>
|
31
|
+
</ApplicationRequest>
|
data/spec/signer_spec.rb
CHANGED
@@ -139,6 +139,28 @@ describe Signer do
|
|
139
139
|
signer.to_xml.should == Nokogiri::XML(File.read(output_xml_file), &:noblanks).to_xml(:save_with => 0)
|
140
140
|
end
|
141
141
|
|
142
|
+
it "should sign simple XML with custom DS namespace prefix" do
|
143
|
+
input_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'input_2.xml')
|
144
|
+
cert_file = File.join(File.dirname(__FILE__), 'fixtures', 'cert.pem')
|
145
|
+
private_key_file = File.join(File.dirname(__FILE__), 'fixtures', 'key.pem')
|
146
|
+
|
147
|
+
signer = Signer.new(File.read(input_xml_file))
|
148
|
+
signer.cert = OpenSSL::X509::Certificate.new(File.read(cert_file))
|
149
|
+
signer.private_key = OpenSSL::PKey::RSA.new(File.read(private_key_file), "test")
|
150
|
+
signer.security_node = signer.document.root
|
151
|
+
signer.security_token_id = ""
|
152
|
+
signer.ds_namespace_prefix = 'ds'
|
153
|
+
signer.digest!(signer.document.root, :id => "", :enveloped => true)
|
154
|
+
signer.sign!(:issuer_serial => true)
|
155
|
+
|
156
|
+
# File.open(File.join(File.dirname(__FILE__), 'fixtures', 'output_2_with_ds_prefix.xml'), "w") do |f|
|
157
|
+
# f.write signer.document.to_s
|
158
|
+
# end
|
159
|
+
output_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'output_2_with_ds_prefix.xml')
|
160
|
+
|
161
|
+
signer.to_xml.should == Nokogiri::XML(File.read(output_xml_file), &:noblanks).to_xml(:save_with => 0)
|
162
|
+
end
|
163
|
+
|
142
164
|
it "should digest and sign SOAP XML with security node and digested binary token with noblanks diabled" do
|
143
165
|
input_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'input_4_with_nested_signatures.xml')
|
144
166
|
cert_file = File.join(File.dirname(__FILE__), 'fixtures', 'cert.pem')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: signer
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.5.
|
4
|
+
version: 1.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Edgars Beigarts
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-03-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -75,6 +75,7 @@ files:
|
|
75
75
|
- spec/fixtures/output_1_inclusive_namespaces.xml
|
76
76
|
- spec/fixtures/output_1_sha256.xml
|
77
77
|
- spec/fixtures/output_2.xml
|
78
|
+
- spec/fixtures/output_2_with_ds_prefix.xml
|
78
79
|
- spec/fixtures/output_3_c14n_comments.xml
|
79
80
|
- spec/fixtures/output_4_with_nested_signatures.xml
|
80
81
|
- spec/fixtures/output_4_with_nested_signatures_with_noblanks_disabled.xml
|
@@ -99,7 +100,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
99
100
|
version: '0'
|
100
101
|
requirements: []
|
101
102
|
rubyforge_project:
|
102
|
-
rubygems_version: 2.
|
103
|
+
rubygems_version: 2.6.8
|
103
104
|
signing_key:
|
104
105
|
specification_version: 4
|
105
106
|
summary: WS Security XML signer
|
@@ -114,6 +115,7 @@ test_files:
|
|
114
115
|
- spec/fixtures/output_1_inclusive_namespaces.xml
|
115
116
|
- spec/fixtures/output_1_sha256.xml
|
116
117
|
- spec/fixtures/output_2.xml
|
118
|
+
- spec/fixtures/output_2_with_ds_prefix.xml
|
117
119
|
- spec/fixtures/output_3_c14n_comments.xml
|
118
120
|
- spec/fixtures/output_4_with_nested_signatures.xml
|
119
121
|
- spec/fixtures/output_4_with_nested_signatures_with_noblanks_disabled.xml
|