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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ae216e81d9f7a7ee4d382887c57ac53a915e7173
4
- data.tar.gz: 01e67fcff1cbe03eafaa72e083d9849ddede5bb4
3
+ metadata.gz: a37c55f9fdbf134383fd475503fbd47cee739f42
4
+ data.tar.gz: 60999a93aa7427c4a132c75985a915f7d18a2995
5
5
  SHA512:
6
- metadata.gz: e9dc941878f1f90d72cf33deba4a2f1c82e84d94f108461a2187a1042520db896368322ed3d1e136bab90d1274fa5e3a4ef96fd10ada602b7878844ec59a642a
7
- data.tar.gz: 5ff0201e154fa6fd8174c10f1605a4a9f630362db0a8a4b37afed9f61da674b959a5f8cccfd326e1b40a9cc6d310cb5f88353bcb13986c6c395c69c3c1d9cd4e
6
+ metadata.gz: 47fdf2988627bbf355ac5ab6a1ffe80bbe660d7bd6315ec65c3ed96978191653d1f3919270b960685364487910f846970e21f00738c456affea72b6d31695378
7
+ data.tar.gz: 00e6ba00e46ab22ef6a9029d0cc1f28b00c04a8b90cfd2a512a84b2d444bea9b627806d5059efd74f7f66312e8b0465adeb66716abb5733941268ab83b87dfb7
@@ -1,3 +1,7 @@
1
+ ## 1.5.1 (2017-03-23)
2
+
3
+ - Allow to set up custom xmldsig namespace prefix for Signature node (#14, @Envek)
4
+
1
5
  ## 1.5.0 (2017-01-23)
2
6
 
3
7
  - Add posibility to disable noblanks method in Signer initialization (#16, @bpietraga)
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
  ```
@@ -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: 'http://www.w3.org/2000/09/xmldsig#')
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.default_namespace = 'http://www.w3.org/2000/09/xmldsig#'
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: 'http://www.w3.org/2000/09/xmldsig#')
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: 'http://www.w3.org/2000/09/xmldsig#')
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
@@ -1,3 +1,3 @@
1
1
  class Signer
2
- VERSION = '1.5.0'
2
+ VERSION = '1.5.1'
3
3
  end
@@ -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>
@@ -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.0
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-01-23 00:00:00.000000000 Z
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.4.3
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