signer 1.3.1 → 1.4.0

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