signer 1.5.0 → 1.5.1

Sign up to get free protection for your applications and to get access to all the features.
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