xmldsig 0.6.5 → 0.6.6

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: a9796692edf2edbf8dc5b0b3e034e72c110b9632
4
- data.tar.gz: 987fa5579e92b79490237b25eb01bdea3fb9e7db
3
+ metadata.gz: df1410861d55968a7bca96a9c3ea4a3610938f91
4
+ data.tar.gz: 839b63410739fca62890f35bb03890523c192bf1
5
5
  SHA512:
6
- metadata.gz: 36cc6186cf9d51dbd483c2d64d31bd81f3c7411e53fa43be74463ca7613dd107efc679893fa9510f985230ad40289bc0fb50b73ae83d389d13e5e40482452f1e
7
- data.tar.gz: aafbdeb71da7b102eb054f6ae9db0e590ddda376cca8a85056279511d03b85a4b426a83fd1511c2cc6451a68b5d817c2665a9c89cd7c972edf1800009327dc6f
6
+ metadata.gz: f57cc44c4425d043a97d55af347f8bc9e4c89ae8352b5ff5c74b1fc44c6031ec6277775ea3eb097956d7e042c872c8ecb91b69c94d046e8c952174cd1f4dba59
7
+ data.tar.gz: a001df00e557acf52e267b4a267aa8e0ed69af44ee21a62b5e84310427024b8755efe240c90c9c15f28731ac1166a39e13b5ed28484d21938da839f737c84d2e
@@ -1,4 +1,8 @@
1
1
  # Changelog
2
+ v0.6.6
3
+ - Add support for cid references to external documents. (iterateNZ)
4
+ - Add support for http://www.w3.org/TR/1999/REC-xpath-19991116 transforms (iterateNZ)
5
+
2
6
  v0.6.5
3
7
  - Added inclusive namespace prefix list for canonicalization method (jmhooper)
4
8
 
data/README.md CHANGED
@@ -24,6 +24,9 @@ unsigned_xml = <<-XML
24
24
  <?xml version="1.0" encoding="UTF-8"?>
25
25
  <foo:Foo ID="foo" xmlns:foo="http://example.com/foo#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#">
26
26
  <foo:Bar>bar</foo:Bar>
27
+ <foo:Baz>
28
+ <foo:Qux>quuz</foo:Qux>
29
+ </foo:Baz>
27
30
  <ds:Signature>
28
31
  <ds:SignedInfo>
29
32
  <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
@@ -31,6 +34,9 @@ unsigned_xml = <<-XML
31
34
  <ds:Reference URI="#foo">
32
35
  <ds:Transforms>
33
36
  <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
37
+ <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
38
+ <ds:XPath>not(ancestor-or-self::foo:Baz)</ds:XPath>
39
+ </ds:Transform>
34
40
  <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
35
41
  <ec:InclusiveNamespaces PrefixList="foo"/>
36
42
  </ds:Transform>
@@ -25,6 +25,7 @@ require "xmldsig/signed_document"
25
25
  require "xmldsig/transforms/transform"
26
26
  require "xmldsig/transforms/canonicalize"
27
27
  require "xmldsig/transforms/enveloped_signature"
28
+ require "xmldsig/transforms/xpath"
28
29
  require "xmldsig/transforms"
29
30
  require "xmldsig/reference"
30
31
  require "xmldsig/signature"
@@ -5,10 +5,11 @@ module Xmldsig
5
5
  class ReferencedNodeNotFound < Exception;
6
6
  end
7
7
 
8
- def initialize(reference, id_attr = nil)
8
+ def initialize(reference, id_attr = nil, referenced_documents = {})
9
9
  @reference = reference
10
10
  @errors = []
11
11
  @id_attr = id_attr
12
+ @referenced_documents = referenced_documents
12
13
  end
13
14
 
14
15
  def document
@@ -21,16 +22,28 @@ module Xmldsig
21
22
 
22
23
  def referenced_node
23
24
  if reference_uri && reference_uri != ""
24
- id = reference_uri[1..-1]
25
- referenced_node_xpath = @id_attr ? "//*[@#{@id_attr}=$uri]" : "//*[@ID=$uri or @wsu:Id=$uri]"
26
- variable_bindings = { 'uri' => id }
27
- if ref = document.dup.at_xpath(referenced_node_xpath, NAMESPACES, variable_bindings)
28
- ref
25
+ if @id_attr.nil? && reference_uri.start_with?("cid:")
26
+ content_id = reference_uri[4..-1]
27
+ if @referenced_documents.has_key?(content_id)
28
+ @referenced_documents[content_id].dup
29
+ else
30
+ raise(
31
+ ReferencedNodeNotFound,
32
+ "Could not find referenced document with ContentId #{content_id}"
33
+ )
34
+ end
29
35
  else
30
- raise(
31
- ReferencedNodeNotFound,
32
- "Could not find the referenced node #{id}'"
33
- )
36
+ id = reference_uri[1..-1]
37
+ referenced_node_xpath = @id_attr ? "//*[@#{@id_attr}=$uri]" : "//*[@ID=$uri or @wsu:Id=$uri]"
38
+ variable_bindings = { 'uri' => id }
39
+ if ref = document.dup.at_xpath(referenced_node_xpath, NAMESPACES, variable_bindings)
40
+ ref
41
+ else
42
+ raise(
43
+ ReferencedNodeNotFound,
44
+ "Could not find the referenced node #{id}'"
45
+ )
46
+ end
34
47
  end
35
48
  else
36
49
  document.dup.root
@@ -2,14 +2,15 @@ module Xmldsig
2
2
  class Signature
3
3
  attr_accessor :signature
4
4
 
5
- def initialize(signature, id_attr = nil)
5
+ def initialize(signature, id_attr = nil, referenced_documents = {})
6
6
  @signature = signature
7
7
  @id_attr = id_attr
8
+ @referenced_documents = referenced_documents
8
9
  end
9
10
 
10
11
  def references
11
12
  @references ||= signature.xpath("descendant::ds:Reference", NAMESPACES).map do |node|
12
- Reference.new(node, @id_attr)
13
+ Reference.new(node, @id_attr, @referenced_documents)
13
14
  end
14
15
  end
15
16
 
@@ -1,6 +1,6 @@
1
1
  module Xmldsig
2
2
  class SignedDocument
3
- attr_accessor :document, :id_attr, :force
3
+ attr_accessor :document, :id_attr, :force, :referenced_documents
4
4
 
5
5
  def initialize(document, options = {})
6
6
  @document = if document.kind_of?(Nokogiri::XML::Document)
@@ -10,6 +10,7 @@ module Xmldsig
10
10
  end
11
11
  @id_attr = options[:id_attr] if options[:id_attr]
12
12
  @force = options[:force]
13
+ @referenced_documents = options.fetch(:referenced_documents, {})
13
14
  end
14
15
 
15
16
  def validate(certificate = nil, schema = nil, &block)
@@ -35,7 +36,7 @@ module Xmldsig
35
36
  def signatures
36
37
  document.xpath("//ds:Signature", NAMESPACES).
37
38
  sort { |left, right| left.ancestors.size <=> right.ancestors.size }.
38
- collect { |node| Signature.new(node, @id_attr) } || []
39
+ collect { |node| Signature.new(node, @id_attr, referenced_documents) } || []
39
40
  end
40
41
  end
41
42
  end
@@ -21,6 +21,8 @@ module Xmldsig
21
21
  Transforms::Canonicalize.new(node, transform_node)
22
22
  when "http://www.w3.org/2001/10/xml-exc-c14n#WithComments"
23
23
  Transforms::Canonicalize.new(node, transform_node, true)
24
+ when "http://www.w3.org/TR/1999/REC-xpath-19991116"
25
+ Transforms::XPath.new(node, transform_node)
24
26
  end
25
27
  end
26
28
 
@@ -0,0 +1,22 @@
1
+ module Xmldsig
2
+ class Transforms < Array
3
+ class XPath < Transform
4
+ attr_reader :xpath_query
5
+
6
+ REC_XPATH_1991116_QUERY = "(//. | //@* | //namespace::*)"
7
+
8
+ def initialize(node, transform_node)
9
+ @xpath_query = transform_node.at_xpath("ds:XPath", NAMESPACES).text
10
+ super(node, transform_node)
11
+ end
12
+
13
+ def transform
14
+ node.xpath(REC_XPATH_1991116_QUERY)
15
+ .reject { |n| !n.respond_to?(:xpath) }
16
+ .reject { |n| n.xpath(@xpath_query, node.namespaces) }
17
+ .each(&:remove)
18
+ node
19
+ end
20
+ end
21
+ end
22
+ end
@@ -1,3 +1,3 @@
1
1
  module Xmldsig
2
- VERSION = '0.6.5'
2
+ VERSION = '0.6.6'
3
3
  end
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <foo:Foo xmlns:foo="http://example.com/foo#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" ID="foo">
3
+ <foo:Bar>bar</foo:Bar>
4
+ <ds:Signature>
5
+ <ds:SignedInfo>
6
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
7
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
8
+ <ds:Reference URI="cid:fooDocument">
9
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
10
+ <ds:DigestValue>tdQEXD9Gb6kf4sxqvnkjKhpXzfEE96JucW4KHieJ33g=</ds:DigestValue>
11
+ </ds:Reference>
12
+ </ds:SignedInfo>
13
+ <ds:SignatureValue>JI5XLfznf8BsNA5vtm0kPG5kni983qrJV1EFx4oZnb6tPvARvPbtR1oEaxnB5ROQJ6xzBuuxDsUFT1BNNUR8vL1S2qPk80USXwNhl0Cfa4mDULNw1rRhN6q82VEvAC/Hb32mvgKDLlJZymdafZhUUeEmaQj+YHsTU54kPCY5w+E=</ds:SignatureValue>
14
+ </ds:Signature>
15
+ </foo:Foo>
@@ -0,0 +1,35 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol">
3
+ <soapenv:Body>
4
+ <samlp:ArtifactResponse xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" ID="_91e79cb2e8cded9a7fd4d68dc480b49d2d1adf88" Version="2.0" IssueInstant="2013-01-17T09:02:44Z">
5
+ <ds:Signature>
6
+ <ds:SignedInfo>
7
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
8
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
9
+ <ds:Reference>
10
+ <ds:Transforms>
11
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
12
+ <ds:Transform Algorithm="http://www.w3.org/TR/1999/REC-xpath-19991116">
13
+ <ds:XPath>not(ancestor-or-self::samlp:Status)</ds:XPath>
14
+ </ds:Transform>
15
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
16
+ <ec:InclusiveNamespaces PrefixList="ds saml samlp xs"/>
17
+ </ds:Transform>
18
+ </ds:Transforms>
19
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
20
+ <ds:DigestValue></ds:DigestValue>
21
+ </ds:Reference>
22
+ </ds:SignedInfo>
23
+ <ds:SignatureValue></ds:SignatureValue>
24
+ </ds:Signature>
25
+ <samlp:Status>
26
+ <samlp:StatusCode/>
27
+ </samlp:Status>
28
+ <samlp:Response ID="_5a88b4aeb1d290c86073874278e5ef302da66739" Version="2.0" IssueInstant="2013-01-17T09:02:44Z">
29
+ <samlp:Status>
30
+ <samlp:StatusCode/>
31
+ </samlp:Status>
32
+ </samlp:Response>
33
+ </samlp:ArtifactResponse>
34
+ </soapenv:Body>
35
+ </soapenv:Envelope>
@@ -0,0 +1,15 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <foo:Foo xmlns:foo="http://example.com/foo#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" ID="foo">
3
+ <foo:Bar>bar</foo:Bar>
4
+ <ds:Signature>
5
+ <ds:SignedInfo>
6
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
7
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
8
+ <ds:Reference URI="cid:fooDocument">
9
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
10
+ <ds:DigestValue></ds:DigestValue>
11
+ </ds:Reference>
12
+ </ds:SignedInfo>
13
+ <ds:SignatureValue></ds:SignatureValue>
14
+ </ds:Signature>
15
+ </foo:Foo>
@@ -78,6 +78,30 @@ describe Xmldsig::Reference do
78
78
  expect { malicious_reference.referenced_node }.
79
79
  to raise_error(Xmldsig::Reference::ReferencedNodeNotFound)
80
80
  end
81
+
82
+ context "when the referenced node is prefixed with 'cid:'" do
83
+ let(:document) { Nokogiri::XML::Document.parse File.read("spec/fixtures/unsigned_with_cid_reference.xml") }
84
+ let(:foo_document) { "<test><ing>present</ing></test>" }
85
+ let(:referenced_documents) { { "fooDocument" => foo_document } }
86
+ let(:reference) { Xmldsig::Reference.new(document.at_xpath('//ds:Reference', Xmldsig::NAMESPACES), nil, referenced_documents) }
87
+
88
+ it "has the correct reference_uri" do
89
+ expect(reference.reference_uri).to eq "cid:fooDocument"
90
+ end
91
+
92
+ it "returns the document referenced by the content id" do
93
+ expect(reference.referenced_node).to eq foo_document
94
+ end
95
+
96
+ context "when the document has no referenced_documents matching the referenced name" do
97
+ let(:referenced_documents) { Hash.new }
98
+
99
+ it "raises ReferencedNodeNotFound" do
100
+ expect { reference.referenced_node }.
101
+ to raise_error(Xmldsig::Reference::ReferencedNodeNotFound)
102
+ end
103
+ end
104
+ end
81
105
  end
82
106
 
83
107
  describe "#reference_uri" do
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xmldsig::Transforms::XPath do
4
+ let(:expected_xpath_query) { "not(ancestor-or-self::samlp:Status)" }
5
+ let(:unsigned_xml) { File.read('spec/fixtures/unsigned/with_xpath_algorithm.xml') }
6
+ let(:unsigned_document) { Xmldsig::SignedDocument.new(unsigned_xml) }
7
+ let(:transform_node) { unsigned_document.signatures.first.references.first.transforms[1] }
8
+ subject(:xpath_transform) { described_class.new(unsigned_document.document, transform_node) }
9
+
10
+ it 'reads the xpath' do
11
+ expect(xpath_transform.xpath_query).to eq expected_xpath_query
12
+ end
13
+
14
+ it 'filters out the nodes matching the xpath expression' do
15
+ transformed_node = xpath_transform.transform
16
+ expect(transform_node.children).to all(satisfy { |n| n.xpath(expected_xpath_query, unsigned_document.document.namespaces) })
17
+ end
18
+ end
@@ -81,4 +81,31 @@ describe Xmldsig do
81
81
  end
82
82
  end
83
83
  end
84
+
85
+ describe "Allows passing referenced documents" do
86
+ let(:referenced_documents) { { 'fooDocument' => 'ABC' } }
87
+
88
+ describe "an unsigned document" do
89
+ let(:unsigned_xml) { File.read("spec/fixtures/unsigned_with_cid_reference.xml") }
90
+ let(:unsigned_document) { Xmldsig::SignedDocument.new(unsigned_xml, referenced_documents: referenced_documents) }
91
+ let(:signed_document) { unsigned_document.sign(private_key) }
92
+
93
+ it "should be signable an validateable" do
94
+ expect(Xmldsig::SignedDocument.new(signed_document, referenced_documents: referenced_documents).validate(certificate)).to eq(true)
95
+ end
96
+
97
+ it 'should have at least 1 signature element' do
98
+ expect(Xmldsig::SignedDocument.new(signed_document).signatures.count).to be >= 1
99
+ end
100
+ end
101
+
102
+ context "a signed document" do
103
+ let(:signed_xml) { File.read("spec/fixtures/signed_with_cid_reference.xml") }
104
+ let(:signed_document) { Xmldsig::SignedDocument.new(signed_xml, referenced_documents: referenced_documents) }
105
+
106
+ it "should be validateable" do
107
+ expect(signed_document.validate(certificate)).to eq(true)
108
+ end
109
+ end
110
+ end
84
111
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xmldsig
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.5
4
+ version: 0.6.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - benoist
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-30 00:00:00.000000000 Z
11
+ date: 2018-03-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -55,6 +55,7 @@ files:
55
55
  - lib/xmldsig/transforms/canonicalize.rb
56
56
  - lib/xmldsig/transforms/enveloped_signature.rb
57
57
  - lib/xmldsig/transforms/transform.rb
58
+ - lib/xmldsig/transforms/xpath.rb
58
59
  - lib/xmldsig/version.rb
59
60
  - lib/xmldsig/xmldsig-core-schema-x509-serial-fix.xsd
60
61
  - lib/xmldsig/xmldsig-core-schema.xsd
@@ -70,6 +71,7 @@ files:
70
71
  - spec/fixtures/signed/shib.xml
71
72
  - spec/fixtures/signed_custom_attribute_id.xml
72
73
  - spec/fixtures/signed_signature_namespace.xml
74
+ - spec/fixtures/signed_with_cid_reference.xml
73
75
  - spec/fixtures/signed_xml-exc-c14n#with_comments.xml
74
76
  - spec/fixtures/unsigned-invalid.xml
75
77
  - spec/fixtures/unsigned-malicious.xml
@@ -87,6 +89,7 @@ files:
87
89
  - spec/fixtures/unsigned/unsigned_nested_signature_at_bottom.xml
88
90
  - spec/fixtures/unsigned/unsigned_nested_signature_at_top.xml
89
91
  - spec/fixtures/unsigned/with_soap_envelope.xml
92
+ - spec/fixtures/unsigned/with_xpath_algorithm.xml
90
93
  - spec/fixtures/unsigned/without_canonicalization.xml
91
94
  - spec/fixtures/unsigned/without_namespace_prefix.xml
92
95
  - spec/fixtures/unsigned/without_reference_uri.xml
@@ -95,11 +98,13 @@ files:
95
98
  - spec/fixtures/unsigned_nested_signature.xml
96
99
  - spec/fixtures/unsigned_nested_signed_signature.xml
97
100
  - spec/fixtures/unsigned_signature_namespace.xml
101
+ - spec/fixtures/unsigned_with_cid_reference.xml
98
102
  - spec/lib/xmldsig/reference_spec.rb
99
103
  - spec/lib/xmldsig/signature_spec.rb
100
104
  - spec/lib/xmldsig/signed_document_spec.rb
101
105
  - spec/lib/xmldsig/transforms/enveloped_signature_spec.rb
102
106
  - spec/lib/xmldsig/transforms/transform_spec.rb
107
+ - spec/lib/xmldsig/transforms/xpath_spec.rb
103
108
  - spec/lib/xmldsig_spec.rb
104
109
  - spec/spec_helper.rb
105
110
  - xmldsig.gemspec
@@ -139,6 +144,7 @@ test_files:
139
144
  - spec/fixtures/signed/shib.xml
140
145
  - spec/fixtures/signed_custom_attribute_id.xml
141
146
  - spec/fixtures/signed_signature_namespace.xml
147
+ - spec/fixtures/signed_with_cid_reference.xml
142
148
  - spec/fixtures/signed_xml-exc-c14n#with_comments.xml
143
149
  - spec/fixtures/unsigned-invalid.xml
144
150
  - spec/fixtures/unsigned-malicious.xml
@@ -156,6 +162,7 @@ test_files:
156
162
  - spec/fixtures/unsigned/unsigned_nested_signature_at_bottom.xml
157
163
  - spec/fixtures/unsigned/unsigned_nested_signature_at_top.xml
158
164
  - spec/fixtures/unsigned/with_soap_envelope.xml
165
+ - spec/fixtures/unsigned/with_xpath_algorithm.xml
159
166
  - spec/fixtures/unsigned/without_canonicalization.xml
160
167
  - spec/fixtures/unsigned/without_namespace_prefix.xml
161
168
  - spec/fixtures/unsigned/without_reference_uri.xml
@@ -164,10 +171,12 @@ test_files:
164
171
  - spec/fixtures/unsigned_nested_signature.xml
165
172
  - spec/fixtures/unsigned_nested_signed_signature.xml
166
173
  - spec/fixtures/unsigned_signature_namespace.xml
174
+ - spec/fixtures/unsigned_with_cid_reference.xml
167
175
  - spec/lib/xmldsig/reference_spec.rb
168
176
  - spec/lib/xmldsig/signature_spec.rb
169
177
  - spec/lib/xmldsig/signed_document_spec.rb
170
178
  - spec/lib/xmldsig/transforms/enveloped_signature_spec.rb
171
179
  - spec/lib/xmldsig/transforms/transform_spec.rb
180
+ - spec/lib/xmldsig/transforms/xpath_spec.rb
172
181
  - spec/lib/xmldsig_spec.rb
173
182
  - spec/spec_helper.rb