signer 1.3.1 → 1.4.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 CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MjdkYWY0NGIxMWEwZWEyNDEwNDkwN2E2ZDA0NWZlODcxNGVhMmM3Zg==
5
- data.tar.gz: !binary |-
6
- M2M3Njg5MTE1ZDQ4NTM4ZGU5YjI0OWNjY2IzMmNiMDVhYjE0NjEzYQ==
2
+ SHA1:
3
+ metadata.gz: 90bf367f95fe6b6176fc18f58e91eed7c5c27d84
4
+ data.tar.gz: 85539298e638c7bf0824fa2f537565286603c9c5
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- Zjg3YjhhMzAwZjJmZTM4M2Y1MGIwODM5ZmE4OGFlMTM3ZTYwODM4YjA0ODJl
10
- ZWI2MWNkYThkMjNhOTEwNzhkZGI3MmE1MzQ4MDMzMmQ4ZDgyOWZmMDc5MDNi
11
- YzY3ZTY2NmY2NDdhODFhMjAxOGE2M2I5Y2UyMjNkODc1MjM4MGI=
12
- data.tar.gz: !binary |-
13
- YjIwOWQ4YmJiMjAzZDhmNTRiMjYxNDljMzQzMGEwNzA4N2U0ZTgwNTZjZmVj
14
- ZTgxMDg5MzBlOGY4NmZjYWE2YmEzNTgwZDA3NTM4NzQ4ZWU4MGFkY2RiNzYz
15
- Nzc1MGYzMTM0NTg4OWRmOTliMmI2NWFkODZhMzcwNjllN2RlN2M=
6
+ metadata.gz: f8ee8286d29dde4704486e7b4b70ffe5242234b159e3b7929e9a9997d71779b0303d0838bb3fb6dd9fe0803363d416a5d3a071974a4f9762b2c63f19c964f9ea
7
+ data.tar.gz: af759eb3935fb4968e04f6b821544ff04e932e413c837b28b1b36f1b687e845f5e86eb6e18cbac8f96491c0a2627fc1f340d02636bc2143e6a40f30c166d421b
@@ -1,3 +1,7 @@
1
+ ## 1.4.0 (2014-06-24)
2
+
3
+ - Support signing and digesting with inclusive namespaces (#5, @Envek)
4
+
1
5
  ## 1.3.1 (2014-06-24)
2
6
 
3
7
  - Fix namespace issue for SecurityTokenReference tag (#4, #@Envek)
data/README.md CHANGED
@@ -225,3 +225,5 @@ If you need to digest a `BinarySecurityToken` tag, you need to construct it your
225
225
  signer.digest!(signer.binary_security_token_node) # Constructing tag and digesting it
226
226
  signer.sign! # No need to pass a :security_token option, as we already constructed and inserted this node
227
227
  ```
228
+
229
+ 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.
@@ -72,8 +72,8 @@ class Signer
72
72
  @security_node ||= document.xpath('//wsse:Security', wsse: WSSE_NAMESPACE).first
73
73
  end
74
74
 
75
- def canonicalize(node = document)
76
- node.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0, nil, nil) # The last argument should be exactly +nil+ to remove comments from result
75
+ def canonicalize(node = document, inclusive_namespaces=nil)
76
+ node.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0, inclusive_namespaces, nil) # The last argument should be exactly +nil+ to remove comments from result
77
77
  end
78
78
 
79
79
  # <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
@@ -176,13 +176,27 @@ class Signer
176
176
  data_node
177
177
  end
178
178
 
179
- # <Reference URI="#_0">
180
- # <Transforms>
181
- # <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
182
- # </Transforms>
183
- # <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
184
- # <DigestValue>aeqXriJuUCk4tPNPAGDXGqHj6ao=</DigestValue>
185
- # </Reference>
179
+ ##
180
+ # Digests some +target_node+, which integrity you wish to track. Any changes in digested node will invalidate signed message.
181
+ # All digest should be calculated **before** signing.
182
+ #
183
+ # Available options:
184
+ # * [+:id+] Id for the node, if you don't want to use automatically calculated one
185
+ # * [+:inclusive_namespaces+] Array of namespace prefixes which definitions should be added to node during canonicalization
186
+ # * [+:enveloped+]
187
+ #
188
+ # Example of XML that will be inserted in message for call like <tt>digest!(node, inclusive_namespaces: ['soap'])</tt>:
189
+ #
190
+ # <Reference URI="#_0">
191
+ # <Transforms>
192
+ # <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
193
+ # <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap" />
194
+ # </Transform>
195
+ # </Transforms>
196
+ # <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
197
+ # <DigestValue>aeqXriJuUCk4tPNPAGDXGqHj6ao=</DigestValue>
198
+ # </Reference>
199
+
186
200
  def digest!(target_node, options = {})
187
201
  wsu_ns = namespace_prefix(target_node, WSU_NAMESPACE)
188
202
  current_id = target_node["#{wsu_ns}:Id"] if wsu_ns
@@ -191,7 +205,7 @@ class Signer
191
205
  wsu_ns ||= namespace_prefix(target_node, WSU_NAMESPACE, 'wsu')
192
206
  target_node["#{wsu_ns}:Id"] = id.to_s
193
207
  end
194
- target_canon = canonicalize(target_node)
208
+ target_canon = canonicalize(target_node, options[:inclusive_namespaces])
195
209
  target_digest = Base64.encode64(@digester.digest(target_canon)).strip
196
210
 
197
211
  reference_node = Nokogiri::XML::Node.new('Reference', document)
@@ -207,6 +221,12 @@ class Signer
207
221
  else
208
222
  transform_node['Algorithm'] = 'http://www.w3.org/2001/10/xml-exc-c14n#'
209
223
  end
224
+ if options[:inclusive_namespaces]
225
+ inclusive_namespaces_node = Nokogiri::XML::Node.new('ec:InclusiveNamespaces', document)
226
+ inclusive_namespaces_node.add_namespace_definition('ec', transform_node['Algorithm'])
227
+ inclusive_namespaces_node['PrefixList'] = options[:inclusive_namespaces].join(' ')
228
+ transform_node.add_child(inclusive_namespaces_node)
229
+ end
210
230
  transforms_node.add_child(transform_node)
211
231
 
212
232
  digest_method_node = Nokogiri::XML::Node.new('DigestMethod', document)
@@ -219,7 +239,16 @@ class Signer
219
239
  self
220
240
  end
221
241
 
222
- # <SignatureValue>...</SignatureValue>
242
+ ##
243
+ # Sign document with provided certificate, private key and other options
244
+ #
245
+ # This should be very last action before calling +to_xml+, all the required nodes should be digested with +digest!+ **before** signing.
246
+ #
247
+ # Available options:
248
+ # * [+:security_token+] Serializes certificate in DER format, encodes it with Base64 and inserts it within +<BinarySecurityToken>+ tag
249
+ # * [+:issuer_serial+]
250
+ # * [+:inclusive_namespaces+] Array of namespace prefixes which definitions should be added to signed info node during canonicalization
251
+
223
252
  def sign!(options = {})
224
253
  if options[:security_token]
225
254
  binary_security_token_node
@@ -229,7 +258,15 @@ class Signer
229
258
  x509_data_node
230
259
  end
231
260
 
232
- signed_info_canon = canonicalize(signed_info_node)
261
+ if options[:inclusive_namespaces]
262
+ c14n_method_node = signed_info_node.at_xpath('ds:CanonicalizationMethod', ds: 'http://www.w3.org/2000/09/xmldsig#')
263
+ inclusive_namespaces_node = Nokogiri::XML::Node.new('ec:InclusiveNamespaces', document)
264
+ inclusive_namespaces_node.add_namespace_definition('ec', c14n_method_node['Algorithm'])
265
+ inclusive_namespaces_node['PrefixList'] = options[:inclusive_namespaces].join(' ')
266
+ c14n_method_node.add_child(inclusive_namespaces_node)
267
+ end
268
+
269
+ signed_info_canon = canonicalize(signed_info_node, options[:inclusive_namespaces])
233
270
 
234
271
  signature = private_key.sign(@sign_digester.digester, signed_info_canon)
235
272
  signature_value_digest = Base64.encode64(signature).gsub("\n", '')
@@ -1,3 +1,3 @@
1
1
  class Signer
2
- VERSION = "1.3.1"
2
+ VERSION = '1.4.0'
3
3
  end
@@ -0,0 +1,48 @@
1
+ <?xml version="1.0"?>
2
+ <s:Envelope xmlns:s="http://www.w3.org/2003/05/soap-envelope" xmlns:a="http://www.w3.org/2005/08/addressing" xmlns:wsurandom="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd">
3
+ <s:Header>
4
+ <a:Action s:mustUnderstand="1">http://tempuri.org/IDocumentService/SearchDocuments</a:Action>
5
+ <a:MessageID>urn:uuid:30db5d4f-ab84-46be-907c-be690a92979b</a:MessageID>
6
+ <a:ReplyTo>
7
+ <a:Address>http://www.w3.org/2005/08/addressing/anonymous</a:Address>
8
+ </a:ReplyTo>
9
+ <To xmlns="http://www.w3.org/2005/08/addressing" xmlns:a="http://www.w3.org/2003/05/soap-envelope" a:mustUnderstand="1">http://tempuri.org/PublicServices/Test/1.0.12/PublicServices/DocumentService.svc</To>
10
+ <wsse:Security xmlns:wsse="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" s:mustUnderstand="1">
11
+ <wsurandom:Timestamp>
12
+ <wsurandom:Created>2012-05-02T18:17:14.467Z</wsurandom:Created>
13
+ <wsurandom:Expires>2012-05-02T18:22:14.467Z</wsurandom:Expires>
14
+ </wsurandom:Timestamp>
15
+ <wsse:BinarySecurityToken ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" EncodingType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary" wsurandom:Id="uuid-639b8970-7644-4f9e-9bc4-9c2e367808fc-1">MIICsDCCAhmgAwIBAgIJAOUHvh4oho0tMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTIwNTAzMTMxODIyWhcNMTMwNTAzMTMxODIyWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvK5hMPv/R5IFmwWyJOyEaFUrF/ZsmN+Gip8hvR6rLP3YPNx9iFYvPcZllFmuVwyaz7YT2N5BsqTwLdyi5v4HY4fUtuz0p8jIPoSd6dfDvcnSpf4QLTOgOaL3ciPEbgDHH2tnIksukoWzqCYva+qFZ74NFl19swXotW9fA4Jzs4QIDAQABo4GnMIGkMB0GA1UdDgQWBBRU1WEHDnP8Hr7ZulxrSzEwOcYpMzB1BgNVHSMEbjBsgBRU1WEHDnP8Hr7ZulxrSzEwOcYpM6FJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAOUHvh4oho0tMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEASY/9SAOK57q9mGnNJJeyDbmyGrAHSJTod646xTHYkMvhUqwHyk9PTr5bdfmswpmyVn+AQ43U2tU5vnpTBmKpHWD2+HSHgGa92mMLrfBOd8EBZ329NL3N2HDPIaHr4NPGyhNrSK3QVOnAq2D0jlyrGYJlLli1NxHiBz7FCEJaVI8=</wsse:BinarySecurityToken>
16
+ <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
17
+ <SignedInfo>
18
+ <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
19
+ <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="s"/>
20
+ </CanonicalizationMethod>
21
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
22
+ <Reference URI="#_846355fa6c1fbadc2f04c0e0a86eda85d9cbfa31">
23
+ <Transforms>
24
+ <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
25
+ <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="s"/>
26
+ </Transform>
27
+ </Transforms>
28
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
29
+ <DigestValue>lXzKYCXgcLpnf/2Q8ieQqj3Er7I=</DigestValue>
30
+ </Reference>
31
+ </SignedInfo>
32
+ <SignatureValue>Bs6O0JuOix9vzDX7gTUMWJ+xzB4IfIWI7l/HjMnE4MnfnFlDQeU1a+0OuqiWiesdzImDLZvqjAeSBUPQOnP4eil2O9qTEd4FvTAUm6DldBV+4ECSXozDiLyPaHMSrm4JZyuePF6d3IOroDYn7ZREWBYgBGHiga7F7+h4s9ZW2XQ=</SignatureValue>
33
+ <KeyInfo>
34
+ <wsse:SecurityTokenReference>
35
+ <wsse:Reference ValueType="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3" URI="#uuid-639b8970-7644-4f9e-9bc4-9c2e367808fc-1"/>
36
+ </wsse:SecurityTokenReference>
37
+ </KeyInfo>
38
+ </Signature>
39
+ </wsse:Security>
40
+ </s:Header>
41
+ <s:Body wsurandom:Id="_846355fa6c1fbadc2f04c0e0a86eda85d9cbfa31">
42
+ <SearchDocuments xmlns="http://tempuri.org/">
43
+ <searchCriteria xmlns:b="http://schemas.datacontract.org/2004/07/BusinessLogic.Data.Documents.Integration" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
44
+ <b:RegistrationNo>1</b:RegistrationNo>
45
+ </searchCriteria>
46
+ </SearchDocuments>
47
+ </s:Body>
48
+ </s:Envelope>
@@ -68,6 +68,26 @@ describe Signer do
68
68
  signer.to_xml.should == Nokogiri::XML(File.read(output_xml_file), &:noblanks).to_xml(:save_with => 0)
69
69
  end
70
70
 
71
+ it "should digest and sign SOAP XML with inclusive namespaces" do
72
+ input_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'input_1.xml')
73
+ cert_file = File.join(File.dirname(__FILE__), 'fixtures', 'cert.pem')
74
+ private_key_file = File.join(File.dirname(__FILE__), 'fixtures', 'key.pem')
75
+
76
+ signer = Signer.new(File.read(input_xml_file))
77
+ signer.cert = OpenSSL::X509::Certificate.new(File.read(cert_file))
78
+ signer.private_key = OpenSSL::PKey::RSA.new(File.read(private_key_file), "test")
79
+
80
+ signer.document.xpath("//soap:Body", { "soap" => "http://www.w3.org/2003/05/soap-envelope" }).each do |node|
81
+ signer.digest!(node, inclusive_namespaces: ['s'])
82
+ end
83
+
84
+ signer.sign!(security_token: true, inclusive_namespaces: ['s'])
85
+
86
+ output_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'output_1_inclusive_namespaces.xml')
87
+
88
+ signer.to_xml.should == Nokogiri::XML(File.read(output_xml_file), &:noblanks).to_xml(:save_with => 0)
89
+ end
90
+
71
91
  it "should sign simple XML" do
72
92
  input_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'input_2.xml')
73
93
  cert_file = File.join(File.dirname(__FILE__), 'fixtures', 'cert.pem')
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: signer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.3.1
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edgars Beigarts
@@ -11,47 +11,47 @@ cert_chain: []
11
11
  date: 2014-06-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- version_requirements: !ruby/object:Gem::Requirement
15
- requirements:
16
- - - ! '>='
17
- - !ruby/object:Gem::Version
18
- version: '0'
19
14
  name: rake
20
- type: :development
21
15
  requirement: !ruby/object:Gem::Requirement
22
16
  requirements:
23
- - - ! '>='
17
+ - - ">="
24
18
  - !ruby/object:Gem::Version
25
19
  version: '0'
20
+ type: :development
26
21
  prerelease: false
27
- - !ruby/object:Gem::Dependency
28
22
  version_requirements: !ruby/object:Gem::Requirement
29
23
  requirements:
30
- - - ! '>='
24
+ - - ">="
31
25
  - !ruby/object:Gem::Version
32
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
33
28
  name: rspec
34
- type: :development
35
29
  requirement: !ruby/object:Gem::Requirement
36
30
  requirements:
37
- - - ! '>='
31
+ - - ">="
38
32
  - !ruby/object:Gem::Version
39
33
  version: '0'
34
+ type: :development
40
35
  prerelease: false
41
- - !ruby/object:Gem::Dependency
42
36
  version_requirements: !ruby/object:Gem::Requirement
43
37
  requirements:
44
- - - ! '>='
38
+ - - ">="
45
39
  - !ruby/object:Gem::Version
46
- version: 1.5.1
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
47
42
  name: nokogiri
48
- type: :runtime
49
43
  requirement: !ruby/object:Gem::Requirement
50
44
  requirements:
51
- - - ! '>='
45
+ - - ">="
52
46
  - !ruby/object:Gem::Version
53
47
  version: 1.5.1
48
+ type: :runtime
54
49
  prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: 1.5.1
55
55
  description: WS Security XML signer
56
56
  email:
57
57
  - edgars.beigarts@gmail.com
@@ -59,18 +59,19 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
- - lib/signer/digester.rb
63
- - lib/signer/version.rb
64
- - lib/signer.rb
65
- - README.md
66
62
  - CHANGELOG.md
67
63
  - LICENSE
64
+ - README.md
65
+ - lib/signer.rb
66
+ - lib/signer/digester.rb
67
+ - lib/signer/version.rb
68
68
  - spec/fixtures/cert.pem
69
69
  - spec/fixtures/input_1.xml
70
70
  - spec/fixtures/input_2.xml
71
71
  - spec/fixtures/input_3_c14n_comments.xml
72
72
  - spec/fixtures/key.pem
73
73
  - spec/fixtures/output_1.xml
74
+ - spec/fixtures/output_1_inclusive_namespaces.xml
74
75
  - spec/fixtures/output_1_sha256.xml
75
76
  - spec/fixtures/output_2.xml
76
77
  - spec/fixtures/output_3_c14n_comments.xml
@@ -85,17 +86,17 @@ require_paths:
85
86
  - lib
86
87
  required_ruby_version: !ruby/object:Gem::Requirement
87
88
  requirements:
88
- - - ! '>='
89
+ - - ">="
89
90
  - !ruby/object:Gem::Version
90
91
  version: '0'
91
92
  required_rubygems_version: !ruby/object:Gem::Requirement
92
93
  requirements:
93
- - - ! '>='
94
+ - - ">="
94
95
  - !ruby/object:Gem::Version
95
96
  version: '0'
96
97
  requirements: []
97
98
  rubyforge_project:
98
- rubygems_version: 2.1.11
99
+ rubygems_version: 2.2.2
99
100
  signing_key:
100
101
  specification_version: 4
101
102
  summary: WS Security XML signer
@@ -106,6 +107,7 @@ test_files:
106
107
  - spec/fixtures/input_3_c14n_comments.xml
107
108
  - spec/fixtures/key.pem
108
109
  - spec/fixtures/output_1.xml
110
+ - spec/fixtures/output_1_inclusive_namespaces.xml
109
111
  - spec/fixtures/output_1_sha256.xml
110
112
  - spec/fixtures/output_2.xml
111
113
  - spec/fixtures/output_3_c14n_comments.xml