xmldsig 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ .rvmrc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yaml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 1.8.7
5
+ - ree
data/Gemfile ADDED
@@ -0,0 +1,12 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in xmldsig.gemspec
4
+ gemspec
5
+
6
+ group :test, :development do
7
+ gem 'simplecov'
8
+ gem 'rspec'
9
+ gem 'guard-rspec'
10
+ gem 'rb-fsevent', '~> 0.9.1'
11
+ gem 'rake'
12
+ end
data/Guardfile ADDED
@@ -0,0 +1,24 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ guard 'rspec' do
5
+ watch(%r{^spec/.+_spec\.rb$})
6
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
7
+ watch('spec/spec_helper.rb') { "spec" }
8
+
9
+ # Rails example
10
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
11
+ watch(%r{^app/(.*)(\.erb|\.haml)$}) { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
12
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
13
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
14
+ watch('config/routes.rb') { "spec/routing" }
15
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
16
+
17
+ # Capybara features specs
18
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/features/#{m[1]}_spec.rb" }
19
+
20
+ # Turnip features and steps
21
+ watch(%r{^spec/acceptance/(.+)\.feature$})
22
+ watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$}) { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
23
+ end
24
+
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 benoist
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,76 @@
1
+ [![Build Status](https://secure.travis-ci.org/benoist/xmldsig.png?branch=master)](http://travis-ci.org/benoist/xmldsig)
2
+ # Xmldsig
3
+
4
+ This gem is a (partial) implementation of the XMLDsig specification (http://www.w3.org/TR/xmldsig-core)
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ gem 'xmldsig'
11
+
12
+ And then execute:
13
+
14
+ $ bundle
15
+
16
+ Or install it yourself as:
17
+
18
+ $ gem install xmldsig
19
+
20
+ ## Usage
21
+
22
+ ```ruby
23
+ unsigned_xml = <<-XML
24
+ <?xml version="1.0" encoding="UTF-8"?>
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
+ <foo:Bar>bar</foo:Bar>
27
+ <ds:Signature>
28
+ <ds:SignedInfo>
29
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
30
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
31
+ <ds:Reference URI="#foo">
32
+ <ds:Transforms>
33
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
34
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
35
+ <ec:InclusiveNamespaces PrefixList="foo"/>
36
+ </ds:Transform>
37
+ </ds:Transforms>
38
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
39
+ <ds:DigestValue></ds:DigestValue>
40
+ </ds:Reference>
41
+ </ds:SignedInfo>
42
+ <ds:SignatureValue></ds:SignatureValue>
43
+ </ds:Signature>
44
+ </foo:Foo>
45
+ XML
46
+
47
+ private_key = OpenSSL::PKey::RSA.new(File.read("key.pem"))
48
+ certificate = OpenSSL::X509::Certificate.new(File.read("certificate.cer"))
49
+
50
+ unsigned_document = Xmldsig::SignedDocument.new(unsigned_xml)
51
+ signed_xml = unsigned_document.sign(private_key)
52
+
53
+ # With block
54
+ signed_xml = unsigned_document.sign do |data|
55
+ private_key.sign(OpenSSL::Digest::SHA256.new, data)
56
+ end
57
+
58
+ # Validation
59
+
60
+ signed_document = Xmldsig::SignedDocument.new(signed_xml)
61
+ document.verify(certificate)
62
+
63
+ # With block
64
+ signed_document = Xmldsig::SignedDocument.new(signed_xml)
65
+ document.verify do |signature_value, data|
66
+ certificate.public_key.verify(OpenSSL::Digest::SHA256.new, signature_value, data)
67
+ end
68
+ ```
69
+
70
+ ## Contributing
71
+
72
+ 1. Fork it
73
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
74
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
75
+ 4. Push to the branch (`git push origin my-new-feature`)
76
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:core) do |spec|
7
+ spec.rspec_opts = ['--backtrace']
8
+ end
9
+
10
+ task :default => [:core]
data/lib/xmldsig.rb ADDED
@@ -0,0 +1,18 @@
1
+ require "nokogiri"
2
+ require "openssl"
3
+ require "base64"
4
+ require "xmldsig/version"
5
+ require "xmldsig/canonicalizer"
6
+ require "xmldsig/signed_document"
7
+ require "xmldsig/transforms/transform"
8
+ require "xmldsig/transforms/canonicalize"
9
+ require "xmldsig/transforms/enveloped_signature"
10
+ require "xmldsig/transforms"
11
+ require "xmldsig/signature"
12
+
13
+ module Xmldsig
14
+ NAMESPACES = {
15
+ "ds" => "http://www.w3.org/2000/09/xmldsig#",
16
+ "ec" => "http://www.w3.org/2001/10/xml-exc-c14n#"
17
+ }
18
+ end
@@ -0,0 +1,28 @@
1
+ module Xmldsig
2
+ class Canonicalizer
3
+ attr_accessor :node, :method, :inclusive_namespaces
4
+
5
+ def initialize(node, method, inclusive_namespaces = [])
6
+ @node = node
7
+ @method = method
8
+ @inclusive_namespaces = inclusive_namespaces
9
+ end
10
+
11
+ def canonicalize
12
+ node.canonicalize(mode(method), inclusive_namespaces)
13
+ end
14
+
15
+ private
16
+
17
+ def mode(method)
18
+ case method
19
+ when "http://www.w3.org/2001/10/xml-exc-c14n#"
20
+ Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
21
+ when "http://www.w3.org/TR/2001/REC-xml-c14n-20010315"
22
+ Nokogiri::XML::XML_C14N_1_0
23
+ when "http://www.w3.org/2006/12/xml-c14n11"
24
+ Nokogiri::XML::XML_C14N_1_1
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,126 @@
1
+ module Xmldsig
2
+ class Signature
3
+ attr_accessor :signature, :errors
4
+
5
+ def initialize(signature)
6
+ @signature = signature
7
+ @errors = []
8
+ end
9
+
10
+ def digest_value
11
+ Base64.decode64 signed_info.at_xpath("descendant::ds:DigestValue", NAMESPACES).content
12
+ end
13
+
14
+ def document
15
+ signature.document
16
+ end
17
+
18
+ def referenced_node
19
+ if reference_uri && reference_uri != ""
20
+ document.dup.at_xpath("//*[@ID='#{reference_uri[1..-1]}']")
21
+ else
22
+ document.dup.at_xpath(signature.parent.path)
23
+ end
24
+ end
25
+
26
+ def reference_uri
27
+ signature.at_xpath("descendant::ds:Reference", NAMESPACES).get_attribute("URI")
28
+ end
29
+
30
+ def sign(private_key = nil, &block)
31
+ self.digest_value = calculate_digest_value
32
+ self.signature_value = calculate_signature_value(private_key, &block)
33
+ end
34
+
35
+ def signed_info
36
+ signature.at_xpath("descendant::ds:SignedInfo", NAMESPACES)
37
+ end
38
+
39
+ def signature_value
40
+ Base64.decode64 signature.at_xpath("descendant::ds:SignatureValue", NAMESPACES).content
41
+ end
42
+
43
+ def valid?(certificate = nil, &block)
44
+ @errors = []
45
+ validate_digest_value
46
+ validate_signature_value(certificate, &block)
47
+ @errors.empty?
48
+ end
49
+
50
+ private
51
+
52
+ def calculate_digest_value
53
+ node = transforms.apply(referenced_node)
54
+ digest_method.digest node
55
+ end
56
+
57
+ def canonicalization_method
58
+ signed_info.at_xpath("descendant::ds:CanonicalizationMethod", NAMESPACES).get_attribute("Algorithm")
59
+ end
60
+
61
+ def canonicalized_signed_info
62
+ Canonicalizer.new(signed_info, canonicalization_method).canonicalize
63
+ end
64
+
65
+ def calculate_signature_value(private_key, &block)
66
+ if private_key
67
+ private_key.sign(signature_method.new, canonicalized_signed_info)
68
+ else
69
+ yield(canonicalized_signed_info)
70
+ end
71
+ end
72
+
73
+ def digest_method
74
+ algorithm = signed_info.at_xpath("descendant::ds:DigestMethod", NAMESPACES).get_attribute("Algorithm")
75
+ case algorithm
76
+ when "http://www.w3.org/2001/04/xmlenc#sha256"
77
+ Digest::SHA2
78
+ when "http://www.w3.org/2000/09/xmldsig#sha1"
79
+ Digest::SHA1
80
+ end
81
+ end
82
+
83
+ def digest_value=(digest_value)
84
+ signed_info.at_xpath("descendant::ds:DigestValue").content =
85
+ Base64.encode64(digest_value).chomp
86
+ end
87
+
88
+ def signature_method
89
+ algorithm = signed_info.at_xpath("descendant::ds:SignatureMethod", NAMESPACES).get_attribute("Algorithm")
90
+ algorithm = algorithm && algorithm =~ /sha(.*?)$/i && $1.to_i
91
+ case algorithm
92
+ when 256 then
93
+ OpenSSL::Digest::SHA256
94
+ else
95
+ OpenSSL::Digest::SHA1
96
+ end
97
+ end
98
+
99
+ def signature_value=(signature_value)
100
+ signature.at_xpath("descendant::ds:SignatureValue").content =
101
+ Base64.encode64(signature_value).chomp
102
+ end
103
+
104
+ def transforms
105
+ Transforms.new(signature.xpath("descendant::ds:Transform", NAMESPACES))
106
+ end
107
+
108
+ def validate_digest_value
109
+ unless digest_value == calculate_digest_value
110
+ errors << :digest_value
111
+ end
112
+ end
113
+
114
+ def validate_signature_value(certificate)
115
+ signature_valid = if certificate
116
+ certificate.public_key.verify(signature_method.new, signature_value, canonicalized_signed_info)
117
+ else
118
+ yield(signature_value, canonicalized_signed_info)
119
+ end
120
+
121
+ unless signature_valid
122
+ errors << :signature
123
+ end
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,26 @@
1
+ module Xmldsig
2
+ class SignedDocument
3
+ attr_accessor :document
4
+
5
+ def initialize(document, options = {})
6
+ @document = Nokogiri::XML::Document.parse(document)
7
+ end
8
+
9
+ def validate(certificate = nil, &block)
10
+ signatures.all? { |signature| signature.valid?(certificate, &block) }
11
+ end
12
+
13
+ def sign(private_key = nil, &block)
14
+ signatures.each { |signature| signature.sign(private_key, &block) }
15
+ @document.to_s
16
+ end
17
+
18
+ def signed_nodes
19
+ signatures.collect(&:referenced_node)
20
+ end
21
+
22
+ def signatures
23
+ document.xpath("//ds:Signature", NAMESPACES).collect { |node| Signature.new(node) } || []
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,26 @@
1
+ module Xmldsig
2
+ class Transforms < Array
3
+
4
+ def apply(node)
5
+ @node = node
6
+ each do |transform_node|
7
+ @node = get_transform(@node, transform_node).transform
8
+ end
9
+ @node
10
+ end
11
+
12
+ private
13
+
14
+ def get_transform(node, transform_node)
15
+ case transform_node.get_attribute("Algorithm")
16
+ when "http://www.w3.org/2000/09/xmldsig#enveloped-signature"
17
+ Transforms::EnvelopedSignature.new(node, transform_node)
18
+ when "http://www.w3.org/2001/10/xml-exc-c14n#",
19
+ "http://www.w3.org/TR/2001/REC-xml-c14n-20010315",
20
+ "http://www.w3.org/2006/12/xml-c14n11"
21
+ Transforms::Canonicalize.new(node, transform_node)
22
+ end
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,25 @@
1
+ module Xmldsig
2
+ class Transforms < Array
3
+ class Canonicalize < Transform
4
+ def transform
5
+ self.node = Canonicalizer.new(node, algorithm, inclusive_namespaces).canonicalize
6
+ node
7
+ end
8
+
9
+ private
10
+
11
+ def algorithm
12
+ transform_node.get_attribute("Algorithm")
13
+ end
14
+
15
+ def inclusive_namespaces
16
+ inclusive_namespaces = transform_node.at_xpath("descendant::ec:InclusiveNamespaces", Xmldsig::NAMESPACES)
17
+ if inclusive_namespaces && inclusive_namespaces.has_attribute?("PrefixList")
18
+ inclusive_namespaces.get_attribute("PrefixList").to_s.split(" ")
19
+ else
20
+ []
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,10 @@
1
+ module Xmldsig
2
+ class Transforms < Array
3
+ class EnvelopedSignature < Transform
4
+ def transform
5
+ node.xpath("descendant::ds:Signature", Xmldsig::NAMESPACES).remove
6
+ node
7
+ end
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,18 @@
1
+ module Xmldsig
2
+ class Transforms < Array
3
+ class Transform
4
+
5
+ attr_accessor :node, :transform_node
6
+
7
+ def initialize(node, transform_node)
8
+ @node = node
9
+ @transform_node = transform_node
10
+ end
11
+
12
+ def transform
13
+ warn("Transform called but not implemented!")
14
+ self
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Xmldsig
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,16 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICgjCCAeugAwIBAgIBADANBgkqhkiG9w0BAQUFADA6MQswCQYDVQQGEwJCRTEN
3
+ MAsGA1UECgwEVGVzdDENMAsGA1UECwwEVGVzdDENMAsGA1UEAwwEVGVzdDAeFw0x
4
+ MzAxMTMxNTMzNDNaFw0xNDAxMTMxNTMzNDNaMDoxCzAJBgNVBAYTAkJFMQ0wCwYD
5
+ VQQKDARUZXN0MQ0wCwYDVQQLDARUZXN0MQ0wCwYDVQQDDARUZXN0MIGfMA0GCSqG
6
+ SIb3DQEBAQUAA4GNADCBiQKBgQC37C0mhTmdr8iVfQPQuOKtzG/fhwG4ILuUX1Vk
7
+ 5uN9oSZJxhb5Kn8aBppny1BSekgk12wn4AE/6i7Jfix3SZWoqdaxpdDalvQSdNey
8
+ n6GmV2oP4lzp6XjXmtRxvOywgTYuhf/DBlpiq7B/vTF7kMwYgs0ahM3mRJG2V7LA
9
+ RTXUfwIDAQABo4GXMIGUMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFBRkMx3Z
10
+ wHO3Zog0pWdYNB38NRmWMGIGA1UdIwRbMFmAFBRkMx3ZwHO3Zog0pWdYNB38NRmW
11
+ oT6kPDA6MQswCQYDVQQGEwJCRTENMAsGA1UECgwEVGVzdDENMAsGA1UECwwEVGVz
12
+ dDENMAsGA1UEAwwEVGVzdIIBADANBgkqhkiG9w0BAQUFAAOBgQBs8voSBDgN7HL1
13
+ i5EP+G/ymWUVenpGvRZCnfkR9Wo4ORzj1Y7ohXHooOzDJ2oi0yDwatXnPpe3hauq
14
+ QDid6d4i7F1Wpgdo2MibqXP8/DPzhuBARvPSzip+yS6ITjqKN/YN4K+kpja2Sh7D
15
+ dxWND3opvVHZTXywjZpdF1OsmNhOCg==
16
+ -----END CERTIFICATE-----
@@ -0,0 +1,16 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIICgjCCAeugAwIBAgIBADANBgkqhkiG9w0BAQUFADA6MQswCQYDVQQGEwJCRTEN
3
+ MAsGA1UECgwEVGVzdDENMAsGA1UECwwEVGVzdDENMAsGA1UEAwwEVGVzdDAeFw0x
4
+ MzAxMTExNTI4MzdaFw0xNDAxMTExNTI4MzdaMDoxCzAJBgNVBAYTAkJFMQ0wCwYD
5
+ VQQKDARUZXN0MQ0wCwYDVQQLDARUZXN0MQ0wCwYDVQQDDARUZXN0MIGfMA0GCSqG
6
+ SIb3DQEBAQUAA4GNADCBiQKBgQDQnLpvMvXoPGcAsdk2j2AeLLPysVtFc1f6CSGA
7
+ fiIR2dzs8h/MN5R0bFBASDUGUGdYyr0QGcKNtqW/cd3Sr1rS2fh5Bopnq9YS6od6
8
+ J6P3AGIKwmJuIBwwfsvnX3eKGDYeOqmrIo5mdPRAob2D1+FhXbMxeYbRhGMmItC0
9
+ dle7LQIDAQABo4GXMIGUMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFM7pPtef
10
+ Oj5Og5wLqI0Lt5UUmw0uMGIGA1UdIwRbMFmAFM7pPtefOj5Og5wLqI0Lt5UUmw0u
11
+ oT6kPDA6MQswCQYDVQQGEwJCRTENMAsGA1UECgwEVGVzdDENMAsGA1UECwwEVGVz
12
+ dDENMAsGA1UEAwwEVGVzdIIBADANBgkqhkiG9w0BAQUFAAOBgQBTIt/4/sraPO4g
13
+ mmY2oSGG19I2Fs24pV/bX8xqI10iexpGsxnpCQIeiDTUHamo12vyXDPx8zANdVTh
14
+ FSAWHEESBMLrS8pybbAL7sU4ij4JmfxygGk6OEsc3jKY00NYom+Mg3JObIgtjOIK
15
+ YfrH7uvpm+AIXsef5vrst4MI6GhEAA==
16
+ -----END CERTIFICATE-----
@@ -0,0 +1,15 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIICXAIBAAKBgQC37C0mhTmdr8iVfQPQuOKtzG/fhwG4ILuUX1Vk5uN9oSZJxhb5
3
+ Kn8aBppny1BSekgk12wn4AE/6i7Jfix3SZWoqdaxpdDalvQSdNeyn6GmV2oP4lzp
4
+ 6XjXmtRxvOywgTYuhf/DBlpiq7B/vTF7kMwYgs0ahM3mRJG2V7LARTXUfwIDAQAB
5
+ AoGBAKDQkd3niSw2YiVLTQW4UwNyCLOioT80567g+JKkS28yc374BGhS3xWLhoCQ
6
+ xieHogMMlRX8iDsxcT1e5FRc88wtIh4vnpUeV++tU9nqpF9SAZV1HAHsOZwyrNUc
7
+ 0nZHgDcyyClirb2wbBG4L+SkrC2kS0MTlx+HiobGpMYsXMh5AkEA4EPrLY7fUaNl
8
+ bzbJb+Thb3M4UsoXzFuFm0Z/H8ty6aw9yi1pxuh8OiyGGFqPB/gl3zUE1LNdTzx5
9
+ xLt93Qdf8wJBANHy1EHwTcNbHJ935NQXF8RpllGyZG1X962NwtJ9x46MTPAhOceU
10
+ 9ZU+OCSOvl+7fKjjcw8TsLYiv4q+RMGZKEUCQHPaomOmqzdBceVCKE3lr5AjtbUP
11
+ Mbwgi6TrhkCmmXadxE3tp/dZotNqrNtn7Pvw9Z+ZhCVdg5arZzx6n0rPxIECQDFZ
12
+ oBUj1FOgXhkKCKrmBrsvipsHkN22+Mw971alJDxYtFkZpkhItnVvW6kUOKGuI35b
13
+ gJdBrJ8TieymDulnA/UCQGfl27mqPX4JTzN+RiZHqGyGSzBi1ggH3vsI2oXDQZ7k
14
+ uOAPiLSBR83eeHGkE2C5fn0QfQGgFNDFjC/6Su/Wvt4=
15
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,23 @@
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="#foo">
9
+ <ds:Transforms>
10
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
11
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
12
+ <ec:InclusiveNamespaces PrefixList="foo"/>
13
+ </ds:Transform>
14
+ </ds:Transforms>
15
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
16
+ <ds:DigestValue>ftoSYFdze1AWgGHF5N9i9SFKThXkqH2AdyzA3/epbJw=</ds:DigestValue>
17
+ </ds:Reference>
18
+ </ds:SignedInfo>
19
+ <ds:SignatureValue>E3yyqsSoxRkhYEuaEtR+SLg85gU5B4a7xUXA+d2Zn6j7F6z73dOd8iYHOusB
20
+ Ty3C/3ujbmPhHKg8uX9kUE8b+YoOqZt4z9pdxAq44nJEuijwi4doIPpHWirv
21
+ BnSoP5IoL0DYzGVrgj8udRzfAw5nNeV7wSrBZEn+yrxmUPJoUZc=</ds:SignatureValue>
22
+ </ds:Signature>
23
+ </foo:Foo>
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <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#">
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="#foo">
9
+ <ds:Transforms>
10
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
11
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
12
+ <ec:InclusiveNamespaces PrefixList="foo"/>
13
+ </ds:Transform>
14
+ </ds:Transforms>
15
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
16
+ <ds:DigestValue></ds:DigestValue>
17
+ </ds:Reference>
18
+ </ds:SignedInfo>
19
+ <ds:SignatureValue></ds:SignatureValue>
20
+ </ds:Signature>
21
+ </foo:Foo>
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <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#">
3
+ <foo:Bar>bar</foo:Bar>
4
+ <ds:Signature>
5
+ <ds:SignedInfo>
6
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
7
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
8
+ <ds:Reference URI="#foo">
9
+ <ds:Transforms>
10
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
11
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
12
+ </ds:Transforms>
13
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
14
+ <ds:DigestValue></ds:DigestValue>
15
+ </ds:Reference>
16
+ </ds:SignedInfo>
17
+ <ds:SignatureValue></ds:SignatureValue>
18
+ </ds:Signature>
19
+ </foo:Foo>
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <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#">
3
+ <foo:Bar>bar</foo:Bar>
4
+ <ds:Signature>
5
+ <ds:SignedInfo>
6
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2006/12/xml-c14n11"/>
7
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
8
+ <ds:Reference URI="#foo">
9
+ <ds:Transforms>
10
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
11
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
12
+ </ds:Transforms>
13
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
14
+ <ds:DigestValue></ds:DigestValue>
15
+ </ds:Reference>
16
+ </ds:SignedInfo>
17
+ <ds:SignatureValue></ds:SignatureValue>
18
+ </ds:Signature>
19
+ </foo:Foo>
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <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#">
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="#foo">
9
+ <ds:Transforms>
10
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
11
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
12
+ <ec:InclusiveNamespaces PrefixList="foo"/>
13
+ </ds:Transform>
14
+ </ds:Transforms>
15
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
16
+ <ds:DigestValue></ds:DigestValue>
17
+ </ds:Reference>
18
+ </ds:SignedInfo>
19
+ <ds:SignatureValue></ds:SignatureValue>
20
+ </ds:Signature>
21
+ </foo:Foo>
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <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#">
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/2000/09/xmldsig#rsa-sha1"/>
8
+ <ds:Reference URI="#foo">
9
+ <ds:Transforms>
10
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
11
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
12
+ <ec:InclusiveNamespaces PrefixList="foo"/>
13
+ </ds:Transform>
14
+ </ds:Transforms>
15
+ <ds:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
16
+ <ds:DigestValue></ds:DigestValue>
17
+ </ds:Reference>
18
+ </ds:SignedInfo>
19
+ <ds:SignatureValue></ds:SignatureValue>
20
+ </ds:Signature>
21
+ </foo:Foo>
@@ -0,0 +1,19 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <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#">
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="#foo">
9
+ <ds:Transforms>
10
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
11
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
12
+ </ds:Transforms>
13
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
14
+ <ds:DigestValue></ds:DigestValue>
15
+ </ds:Reference>
16
+ </ds:SignedInfo>
17
+ <ds:SignatureValue></ds:SignatureValue>
18
+ </ds:Signature>
19
+ </foo:Foo>
@@ -0,0 +1,21 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <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#">
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>
9
+ <ds:Transforms>
10
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
11
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
12
+ <ec:InclusiveNamespaces PrefixList="foo"/>
13
+ </ds:Transform>
14
+ </ds:Transforms>
15
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
16
+ <ds:DigestValue></ds:DigestValue>
17
+ </ds:Reference>
18
+ </ds:SignedInfo>
19
+ <ds:SignatureValue></ds:SignatureValue>
20
+ </ds:Signature>
21
+ </foo:Foo>
@@ -0,0 +1,40 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <foo:Foo ID="foo" xmlns:foo="http://example.com/foo#" xmlns:baz="http://example.com/baz#" xmlns:ds="http://www.w3.org/2000/09/xmldsig#" xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#">
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="#foo">
9
+ <ds:Transforms>
10
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
11
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
12
+ <ec:InclusiveNamespaces PrefixList="foo baz"/>
13
+ </ds:Transform>
14
+ </ds:Transforms>
15
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
16
+ <ds:DigestValue></ds:DigestValue>
17
+ </ds:Reference>
18
+ </ds:SignedInfo>
19
+ <ds:SignatureValue></ds:SignatureValue>
20
+ </ds:Signature>
21
+ <baz:Baz ID="baz">
22
+ <ds:Signature>
23
+ <ds:SignedInfo>
24
+ <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
25
+ <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/>
26
+ <ds:Reference URI="#baz">
27
+ <ds:Transforms>
28
+ <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
29
+ <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#">
30
+ <ec:InclusiveNamespaces PrefixList="foo baz"/>
31
+ </ds:Transform>
32
+ </ds:Transforms>
33
+ <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
34
+ <ds:DigestValue></ds:DigestValue>
35
+ </ds:Reference>
36
+ </ds:SignedInfo>
37
+ <ds:SignatureValue></ds:SignatureValue>
38
+ </ds:Signature>
39
+ </baz:Baz>
40
+ </foo:Foo>
@@ -0,0 +1,112 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xmldsig::Signature do
4
+ let(:certificate) { OpenSSL::X509::Certificate.new(File.read("spec/fixtures/certificate.cer")) }
5
+ let(:other_certificate) { OpenSSL::X509::Certificate.new(File.read("spec/fixtures/certificate2.cer")) }
6
+ let(:private_key) { OpenSSL::PKey::RSA.new(File.read("spec/fixtures/key.pem")) }
7
+ let(:document) { Nokogiri::XML::Document.parse File.read("spec/fixtures/signed.xml") }
8
+ let(:signature_node) { document.at_xpath("//ds:Signature", Xmldsig::NAMESPACES) }
9
+ let(:signature) { Xmldsig::Signature.new(signature_node) }
10
+
11
+ describe "#digest_value" do
12
+ it "returns the digest value in the xml" do
13
+ signature.digest_value.should == Base64.decode64("ftoSYFdze1AWgGHF5N9i9SFKThXkqH2AdyzA3/epbJw=")
14
+ end
15
+ end
16
+
17
+ describe "#document" do
18
+ it "returns the document" do
19
+ signature.document.should == document
20
+ end
21
+ end
22
+
23
+ describe "#referenced_node" do
24
+ it "returns the referenced_node by id" do
25
+ signature.referenced_node.to_s.should ==
26
+ document.at_xpath("//*[@ID='foo']").to_s
27
+ end
28
+
29
+ it "returns the referenced node by parent" do
30
+ signature.stub(:reference_uri).and_return("")
31
+ signature.referenced_node.to_s.should ==
32
+ document.at_xpath("//*[@ID='foo']").to_s
33
+ end
34
+ end
35
+
36
+ describe "#reference_uri" do
37
+ it "returns the reference uri" do
38
+ signature.reference_uri.should == "#foo"
39
+ end
40
+ end
41
+
42
+ describe "#sign" do
43
+ let(:document) { Nokogiri::XML::Document.parse File.read("spec/fixtures/unsigned.xml") }
44
+ let(:signature_node) { document.at_xpath("//ds:Signature", Xmldsig::NAMESPACES) }
45
+ let(:signature) { Xmldsig::Signature.new(signature_node) }
46
+
47
+ before :each do
48
+ signature.sign(private_key)
49
+ end
50
+
51
+ it "sets the digest value" do
52
+ signature.digest_value.should == Base64.decode64("ftoSYFdze1AWgGHF5N9i9SFKThXkqH2AdyzA3/epbJw=")
53
+ end
54
+
55
+ it "sets the signature value" do
56
+ signature.signature_value.should == Base64.decode64("
57
+ E3yyqsSoxRkhYEuaEtR+SLg85gU5B4a7xUXA+d2Zn6j7F6z73dOd8iYHOusB
58
+ Ty3C/3ujbmPhHKg8uX9kUE8b+YoOqZt4z9pdxAq44nJEuijwi4doIPpHWirv
59
+ BnSoP5IoL0DYzGVrgj8udRzfAw5nNeV7wSrBZEn+yrxmUPJoUZc=
60
+ ")
61
+ end
62
+
63
+ it "accepts a block" do
64
+ signature.sign do |data|
65
+ private_key.sign(OpenSSL::Digest::SHA256.new, data)
66
+ end
67
+ signature.signature_value.should == Base64.decode64("
68
+ E3yyqsSoxRkhYEuaEtR+SLg85gU5B4a7xUXA+d2Zn6j7F6z73dOd8iYHOusB
69
+ Ty3C/3ujbmPhHKg8uX9kUE8b+YoOqZt4z9pdxAq44nJEuijwi4doIPpHWirv
70
+ BnSoP5IoL0DYzGVrgj8udRzfAw5nNeV7wSrBZEn+yrxmUPJoUZc=
71
+ ")
72
+ end
73
+
74
+ end
75
+
76
+ describe "#signed_info" do
77
+ it "returns the canonicalized signed info element" do
78
+ signature.signed_info.to_s.should ==
79
+ document.at_xpath("//ds:SignedInfo", Xmldsig::NAMESPACES).to_s
80
+ end
81
+ end
82
+
83
+ describe "#signature_value" do
84
+ it "returns the signature value" do
85
+ signature.signature_value.should ==
86
+ Base64.decode64(document.at_xpath("//ds:SignatureValue", Xmldsig::NAMESPACES).content)
87
+ end
88
+ end
89
+
90
+ describe "#valid?" do
91
+ it "returns true with the correct certificate" do
92
+ signature.valid?(certificate).should be_true
93
+ end
94
+
95
+ it "returns false if the xml changed" do
96
+ signature.stub(:document).and_return(Nokogiri::XML::Document.parse(File.read("spec/fixtures/signed.xml").gsub("\s\s", "\s")))
97
+ signature.valid?(certificate)
98
+ signature.errors.should include(:digest_value)
99
+ end
100
+
101
+ it "returns false with a difference certificate" do
102
+ signature.valid?(other_certificate).should be_false
103
+ end
104
+
105
+ it "accepts a block" do
106
+ signature.valid? do |signature_value, data|
107
+ certificate.public_key.verify(OpenSSL::Digest::SHA256.new, signature_value, data)
108
+ end
109
+ signature.errors.should be_empty
110
+ end
111
+ end
112
+ end
@@ -0,0 +1,82 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xmldsig::SignedDocument do
4
+ let(:signed_xml) { File.read("spec/fixtures/signed.xml") }
5
+ let(:signed_document) { Xmldsig::SignedDocument.new(signed_xml) }
6
+ let(:unsigned_xml) { File.read("spec/fixtures/unsigned.xml") }
7
+ let(:unsigned_document) { Xmldsig::SignedDocument.new(unsigned_xml) }
8
+ let(:private_key) { OpenSSL::PKey::RSA.new(File.read("spec/fixtures/key.pem")) }
9
+ let(:certificate) { OpenSSL::X509::Certificate.new(File.read("spec/fixtures/certificate.cer")) }
10
+ let(:other_certificate) { OpenSSL::X509::Certificate.new(File.read("spec/fixtures/certificate2.cer")) }
11
+
12
+ describe "#initialize" do
13
+ it "sets the document to a nokogiri document" do
14
+ document = described_class.new(signed_xml)
15
+ document.document.should be_a(Nokogiri::XML::Document)
16
+ end
17
+ end
18
+
19
+ describe "#signatures" do
20
+ it "returns only the signed nodes" do
21
+ signed_document.signatures.should be_all { |signature| signature.is_a?(Xmldsig::Signature) }
22
+ end
23
+ end
24
+
25
+ describe "#signed_nodes" do
26
+ it "returns only the signed nodes" do
27
+ signed_document.signed_nodes.collect(&:name).should == %w(Foo)
28
+ end
29
+ end
30
+
31
+ describe "#validate" do
32
+ it "returns true if the signature and digest value are correct" do
33
+ signed_document.validate(certificate).should be_true
34
+ end
35
+
36
+ it "returns false if the certificate is not valid" do
37
+ signed_document.validate(other_certificate).should be_false
38
+ end
39
+
40
+ it "accepts a block" do
41
+ signed_document.validate do |signature_value, data|
42
+ certificate.public_key.verify(OpenSSL::Digest::SHA256.new, signature_value, data)
43
+ end.should be_true
44
+ end
45
+ end
46
+
47
+ describe "#sign" do
48
+ it "returns a signed document" do
49
+ signed_document = unsigned_document.sign(private_key)
50
+ Xmldsig::SignedDocument.new(signed_document).validate(certificate).should be_true
51
+ end
52
+
53
+ it "accepts a block" do
54
+ signed_document = unsigned_document.sign do |data|
55
+ private_key.sign(OpenSSL::Digest::SHA256.new, data)
56
+ end
57
+ Xmldsig::SignedDocument.new(signed_document).validate(certificate).should be_true
58
+ end
59
+ end
60
+
61
+
62
+ describe "Nested Signatures" do
63
+ let(:unsigned_xml) { File.read("spec/fixtures/unsigned_nested_signature.xml") }
64
+ let(:unsigned_document) { Xmldsig::SignedDocument.new(unsigned_xml) }
65
+ let(:signed_document) { unsigned_document.sign(private_key) }
66
+
67
+ it "when signed should be valid" do
68
+ Xmldsig::SignedDocument.new(signed_document).validate(certificate).should be_true
69
+ end
70
+
71
+ it "should sign 2 elements" do
72
+ unsigned_document.signed_nodes.count.should == 2
73
+ end
74
+
75
+ it "allows individual signs" do
76
+ unsigned_document.signatures.last.sign(private_key)
77
+ unsigned_document.validate(certificate).should be_false
78
+ unsigned_document.signatures.last.valid?(certificate).should be_true
79
+ end
80
+ end
81
+
82
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xmldsig::Transforms::Transform do
4
+
5
+ it "raises a warning when transform is called" do
6
+ described_class.any_instance.should_receive(:warn)
7
+ described_class.new(nil,nil).transform
8
+ end
9
+
10
+ end
@@ -0,0 +1,29 @@
1
+ require 'spec_helper'
2
+
3
+ describe Xmldsig do
4
+ let(:private_key) { OpenSSL::PKey::RSA.new(File.read("spec/fixtures/key.pem")) }
5
+ let(:certificate) { OpenSSL::X509::Certificate.new(File.read("spec/fixtures/certificate.cer")) }
6
+
7
+ describe "Sign unsigned documents" do
8
+
9
+ %w(
10
+ canonicalizer_1_0
11
+ canonicalizer_1_1
12
+ canonicalizer_exc
13
+ digest_sha1
14
+ without_namespace_prefix
15
+ without_reference_uri
16
+ ).each do |document|
17
+ describe "#{document}" do
18
+ let(:unsigned_xml) { File.read("spec/fixtures/unsigned/#{document}.xml") }
19
+ let(:unsigned_document) { Xmldsig::SignedDocument.new(unsigned_xml) }
20
+
21
+ it "should be signable an validateable" do
22
+ signed_document = unsigned_document.sign(private_key)
23
+ Xmldsig::SignedDocument.new(signed_document).validate(certificate).should be_true
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+ end
@@ -0,0 +1,22 @@
1
+ require 'simplecov'
2
+ SimpleCov.start
3
+ # This file was generated by the `rspec --init` command. Conventionally, all
4
+ # specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
5
+ # Require this file using `require "spec_helper"` to ensure that it is only
6
+ # loaded once.
7
+ #
8
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
9
+
10
+ require 'xmldsig'
11
+
12
+ RSpec.configure do |config|
13
+ config.treat_symbols_as_metadata_keys_with_true_values = true
14
+ config.run_all_when_everything_filtered = true
15
+ config.filter_run :focus
16
+
17
+ # Run specs in random order to surface order dependencies. If you find an
18
+ # order dependency and want to debug it, you can fix the order by providing
19
+ # the seed, which is printed after each run.
20
+ # --seed 1234
21
+ config.order = 'random'
22
+ end
data/xmlsec.gemspec ADDED
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/xmldsig/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["benoist"]
6
+ gem.email = ["benoist.claassen@gmail.com"]
7
+ gem.description = %q{This gem is a (partial) implementation of the XMLDsig specification}
8
+ gem.summary = %q{This gem is a (partial) implementation of the XMLDsig specification (http://www.w3.org/TR/xmldsig-core)}
9
+ gem.homepage = "https://github.com/benoist/xmldsig"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "xmldsig"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = Xmldsig::VERSION
17
+
18
+ gem.add_dependency("nokogiri")
19
+ end
metadata ADDED
@@ -0,0 +1,113 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: xmldsig
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - benoist
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-13 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: nokogiri
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ description: This gem is a (partial) implementation of the XMLDsig specification
31
+ email:
32
+ - benoist.claassen@gmail.com
33
+ executables: []
34
+ extensions: []
35
+ extra_rdoc_files: []
36
+ files:
37
+ - .gitignore
38
+ - .rspec
39
+ - .travis.yaml
40
+ - Gemfile
41
+ - Guardfile
42
+ - LICENSE
43
+ - README.md
44
+ - Rakefile
45
+ - lib/xmldsig.rb
46
+ - lib/xmldsig/canonicalizer.rb
47
+ - lib/xmldsig/signature.rb
48
+ - lib/xmldsig/signed_document.rb
49
+ - lib/xmldsig/transforms.rb
50
+ - lib/xmldsig/transforms/canonicalize.rb
51
+ - lib/xmldsig/transforms/enveloped_signature.rb
52
+ - lib/xmldsig/transforms/transform.rb
53
+ - lib/xmldsig/version.rb
54
+ - spec/fixtures/certificate.cer
55
+ - spec/fixtures/certificate2.cer
56
+ - spec/fixtures/key.pem
57
+ - spec/fixtures/signed.xml
58
+ - spec/fixtures/unsigned.xml
59
+ - spec/fixtures/unsigned/canonicalizer_1_0.xml
60
+ - spec/fixtures/unsigned/canonicalizer_1_1.xml
61
+ - spec/fixtures/unsigned/canonicalizer_exc.xml
62
+ - spec/fixtures/unsigned/digest_sha1.xml
63
+ - spec/fixtures/unsigned/without_namespace_prefix.xml
64
+ - spec/fixtures/unsigned/without_reference_uri.xml
65
+ - spec/fixtures/unsigned_nested_signature.xml
66
+ - spec/lib/xmldsig/signature_spec.rb
67
+ - spec/lib/xmldsig/signed_document_spec.rb
68
+ - spec/lib/xmldsig/transforms/transform_spec.rb
69
+ - spec/lib/xmldsig_spec.rb
70
+ - spec/spec_helper.rb
71
+ - xmlsec.gemspec
72
+ homepage: https://github.com/benoist/xmldsig
73
+ licenses: []
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ none: false
80
+ requirements:
81
+ - - ! '>='
82
+ - !ruby/object:Gem::Version
83
+ version: '0'
84
+ required_rubygems_version: !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ requirements: []
91
+ rubyforge_project:
92
+ rubygems_version: 1.8.24
93
+ signing_key:
94
+ specification_version: 3
95
+ summary: This gem is a (partial) implementation of the XMLDsig specification (http://www.w3.org/TR/xmldsig-core)
96
+ test_files:
97
+ - spec/fixtures/certificate.cer
98
+ - spec/fixtures/certificate2.cer
99
+ - spec/fixtures/key.pem
100
+ - spec/fixtures/signed.xml
101
+ - spec/fixtures/unsigned.xml
102
+ - spec/fixtures/unsigned/canonicalizer_1_0.xml
103
+ - spec/fixtures/unsigned/canonicalizer_1_1.xml
104
+ - spec/fixtures/unsigned/canonicalizer_exc.xml
105
+ - spec/fixtures/unsigned/digest_sha1.xml
106
+ - spec/fixtures/unsigned/without_namespace_prefix.xml
107
+ - spec/fixtures/unsigned/without_reference_uri.xml
108
+ - spec/fixtures/unsigned_nested_signature.xml
109
+ - spec/lib/xmldsig/signature_spec.rb
110
+ - spec/lib/xmldsig/signed_document_spec.rb
111
+ - spec/lib/xmldsig/transforms/transform_spec.rb
112
+ - spec/lib/xmldsig_spec.rb
113
+ - spec/spec_helper.rb