signer 1.0.0 → 1.1.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.
data/README.md CHANGED
@@ -27,7 +27,7 @@ signer.document.xpath("//a:To", { "a" => "http://www.w3.org/2005/08/addressing"
27
27
  signer.digest!(node)
28
28
  end
29
29
 
30
- signer.sign!
30
+ signer.sign!(:security_token => true)
31
31
 
32
32
  signer.to_xml
33
33
  ```
data/lib/signer.rb CHANGED
@@ -7,6 +7,7 @@ require "signer/version"
7
7
 
8
8
  class Signer
9
9
  attr_accessor :document, :cert, :private_key
10
+ attr_writer :security_node, :security_token_id
10
11
 
11
12
  def initialize(document)
12
13
  self.document = Nokogiri::XML(document.to_s, &:noblanks)
@@ -17,11 +18,15 @@ class Signer
17
18
  end
18
19
 
19
20
  def security_token_id
20
- "uuid-639b8970-7644-4f9e-9bc4-9c2e367808fc-1"
21
+ @security_token_id ||= "uuid-639b8970-7644-4f9e-9bc4-9c2e367808fc-1"
21
22
  end
22
23
 
23
24
  def security_node
24
- document.xpath("//o:Security", "o" => "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd").first
25
+ @security_node ||= document.xpath("//o:Security", "o" => "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd").first
26
+ end
27
+
28
+ def canonicalize(node = document)
29
+ node.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
25
30
  end
26
31
 
27
32
  # <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
@@ -74,7 +79,7 @@ class Signer
74
79
  node['ValueType'] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3'
75
80
  node['EncodingType'] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary'
76
81
  node.content = Base64.encode64(cert.to_der).gsub("\n", '')
77
- security_node.add_child(node)
82
+ signature_node.add_previous_sibling(node)
78
83
  key_info_node = Nokogiri::XML::Node.new('KeyInfo', document)
79
84
  security_token_reference_node = Nokogiri::XML::Node.new('o:SecurityTokenReference', document)
80
85
  key_info_node.add_child(security_token_reference_node)
@@ -87,6 +92,41 @@ class Signer
87
92
  node
88
93
  end
89
94
 
95
+ # <KeyInfo>
96
+ # <X509Data>
97
+ # <X509IssuerSerial>
98
+ # <X509IssuerName>System.Security.Cryptography.X509Certificates.X500DistinguishedName</X509IssuerName>
99
+ # <X509SerialNumber>13070789</X509SerialNumber>
100
+ # </X509IssuerSerial>
101
+ # <X509Certificate>MIID+jCCAuKgAwIBAgIEAMdxxTANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQGEwJTRTEeMBwGA1UEChMVTm9yZGVhIEJhbmsgQUIgKHB1YmwpMScwJQYDVQQDEx5Ob3JkZWEgcm9sZS1jZXJ0aWZpY2F0ZXMgQ0EgMDExFDASBgNVBAUTCzUxNjQwNi0wMTIwMB4XDTA5MDYxMTEyNTAxOVoXDTExMDYxMTEyNTAxOVowcjELMAkGA1UEBhMCU0UxIDAeBgNVBAMMF05vcmRlYSBEZW1vIENlcnRpZmljYXRlMRQwEgYDVQQEDAtDZXJ0aWZpY2F0ZTEUMBIGA1UEKgwLTm9yZGVhIERlbW8xFTATBgNVBAUTDDAwOTU1NzI0Mzc3MjCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwcgz5AzbxTbsCE51No7fPnSqmQBIMW9OiPkiHotwYQTl+H9qwDvQRyBqHN26tnw7hNvEShd1ZRGUg4drMEXDV5CmKqsAevs9lauWDaHnGKPNHZJ1hNNYXHwymksEz5zMnG8eqRdhb4vOV2FzreJeYpsgx31Bv0aTofHcHVz4uGcCAwEAAaOCASAwggEcMAkGA1UdEwQCMAAwEQYDVR0OBAoECEj6Y9/vU03WMBMGA1UdIAQMMAowCAYGKoVwRwEDMBMGA1UdIwQMMAqACEIFjfLBeTpRMDcGCCsGAQUFBwEBBCswKTAnBggrBgEFBQcwAYYbaHR0cDovL29jc3Aubm9yZGVhLnNlL1JDQTAxMA4GA1UdDwEB/wQEAwIGQDCBiAYDVR0fBIGAMH4wfKB6oHiGdmxkYXA6Ly9sZGFwLm5iLnNlL2NuPU5vcmRlYSUyMHJvbGUtY2VydGlmaWNhdGVzJTIwQ0ElMjAwMSxvPU5vcmRlYSUyMEJhbmslMjBBQiUyMChwdWJsKSxjPVNFP2NlcnRpZmljYXRlcmV2b2NhdGlvbmxpc3QwDQYJKoZIhvcNAQEFBQADggEBAEXUv87VpHk51y3TqkMb1MYDqeKvQRE1cNcvhEJhIzdDpXMA9fG0KqvSTT1e0ZI2r78mXDvtTZnpic44jX2XMSmKO6n+1taAXq940tJUhF4arYMUxwDKOso0Doanogug496gipqMlpLgvIhGt06sWjNrvHzp2eGydUFdCsLr2ULqbDcut7g6eMcmrsnrOntjEU/J3hO8gyCeldJ+fI81qarrK/I0MZLR5LWCyVG/SKduoxHLX7JohsbIGyK1qAh9fi8l6X1Rcu80v5inpu71E/DnjbkAZBo7vsj78zzdk7KNliBIqBcIszdJ3dEHRWSI7FspRxyiR0NDm4lpyLwFtfw=</X509Certificate>
102
+ # </X509Data>
103
+ # </KeyInfo>
104
+ def x509_data_node
105
+ issuer_name_node = Nokogiri::XML::Node.new('X509IssuerName', document)
106
+ issuer_name_node.content = "System.Security.Cryptography.X509Certificates.X500DistinguishedName"
107
+
108
+ issuer_number_node = Nokogiri::XML::Node.new('X509SerialNumber', document)
109
+ issuer_number_node.content = cert.serial
110
+
111
+ issuer_serial_node = Nokogiri::XML::Node.new('X509IssuerSerial', document)
112
+ issuer_serial_node.add_child(issuer_name_node)
113
+ issuer_serial_node.add_child(issuer_number_node)
114
+
115
+ cetificate_node = Nokogiri::XML::Node.new('X509Certificate', document)
116
+ cetificate_node.content = Base64.encode64(cert.to_der).gsub("\n", '')
117
+
118
+ data_node = Nokogiri::XML::Node.new('X509Data', document)
119
+ data_node.add_child(issuer_serial_node)
120
+ data_node.add_child(cetificate_node)
121
+
122
+ key_info_node = Nokogiri::XML::Node.new('KeyInfo', document)
123
+ key_info_node.add_child(data_node)
124
+
125
+ signed_info_node.add_next_sibling(key_info_node)
126
+
127
+ data_node
128
+ end
129
+
90
130
  # <Reference URI="#_0">
91
131
  # <Transforms>
92
132
  # <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
@@ -94,14 +134,14 @@ class Signer
94
134
  # <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
95
135
  # <DigestValue>aeqXriJuUCk4tPNPAGDXGqHj6ao=</DigestValue>
96
136
  # </Reference>
97
- def digest!(target_node)
98
- binary_security_token_node
99
-
100
- id = "_#{Digest::SHA1.hexdigest(target_node.to_s)}"
101
- target_node['u:Id'] = id
137
+ def digest!(target_node, options = {})
138
+ id = options[:id] || "_#{Digest::SHA1.hexdigest(target_node.to_s)}"
139
+ target_node['u:Id'] = id if id.size > 0
140
+ target_canon = canonicalize(target_node)
141
+ target_digest = Base64.encode64(OpenSSL::Digest::SHA1.digest(target_canon)).strip
102
142
 
103
143
  reference_node = Nokogiri::XML::Node.new('Reference', document)
104
- reference_node['URI'] = "##{id}"
144
+ reference_node['URI'] = id.size > 0 ? "##{id}" : ""
105
145
  signed_info_node.add_child(reference_node)
106
146
 
107
147
  transforms_node = Nokogiri::XML::Node.new('Transforms', document)
@@ -116,16 +156,22 @@ class Signer
116
156
  reference_node.add_child(digest_method_node)
117
157
 
118
158
  digest_value_node = Nokogiri::XML::Node.new('DigestValue', document)
119
- target_canon = target_node.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
120
- target_digest = Base64.encode64(OpenSSL::Digest::SHA1.digest(target_canon)).strip
121
159
  digest_value_node.content = target_digest
122
160
  reference_node.add_child(digest_value_node)
123
161
  self
124
162
  end
125
163
 
126
164
  # <SignatureValue>...</SignatureValue>
127
- def sign!
128
- signed_info_canon = signed_info_node.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0)
165
+ def sign!(options = {})
166
+ if options[:security_token]
167
+ binary_security_token_node
168
+ end
169
+
170
+ if options[:issuer_serial]
171
+ x509_data_node
172
+ end
173
+
174
+ signed_info_canon = canonicalize(signed_info_node)
129
175
 
130
176
  signature = private_key.sign(OpenSSL::Digest::SHA1.new, signed_info_canon)
131
177
  signature_value_digest = Base64.encode64(signature).gsub("\n", '')
@@ -1,3 +1,3 @@
1
1
  class Signer
2
- VERSION = "1.0.0"
2
+ VERSION = "1.1.0"
3
3
  end
File without changes
@@ -0,0 +1,7 @@
1
+ <ApplicationRequest xmlns="http://bxd.fi/xmldata/">
2
+ <CustomerId>679155330</CustomerId>
3
+ <Command>GetUserInfo</Command>
4
+ <Timestamp>2010-05-10T13:22:19.847+03:00</Timestamp>
5
+ <Environment>PRODUCTION</Environment>
6
+ <SoftwareId>Petri</SoftwareId>
7
+ </ApplicationRequest>
File without changes
@@ -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
+ <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
9
+ <SignedInfo>
10
+ <CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
11
+ <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
12
+ <Reference URI="">
13
+ <Transforms>
14
+ <Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/>
15
+ </Transforms>
16
+ <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
17
+ <DigestValue>U9tsT4lrRMp8ZdKMnblgeMCGfvI=</DigestValue>
18
+ </Reference>
19
+ </SignedInfo>
20
+ <SignatureValue>GoikOue0l0ZZBkEoZ+kDvFJ0YJl1nW4zFLe8IsMcqPFFE2xOK1lO/YHKpc49CNQFs2ZhOiGwCseOg0F/8FUWp9hiAOTLlYrKVd61FErifakLw/mirP2SB3J9npPh6Idt9LMQWU+O+aRdyJMF7HLpx03GML2IF9ejKVUBTWTrcpU=</SignatureValue>
21
+ <KeyInfo>
22
+ <X509Data>
23
+ <X509IssuerSerial>
24
+ <X509IssuerName>System.Security.Cryptography.X509Certificates.X500DistinguishedName</X509IssuerName>
25
+ <X509SerialNumber>16503368396260674861</X509SerialNumber>
26
+ </X509IssuerSerial>
27
+ <X509Certificate>MIICsDCCAhmgAwIBAgIJAOUHvh4oho0tMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkFVMRMwEQYDVQQIEwpTb21lLVN0YXRlMSEwHwYDVQQKExhJbnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQwHhcNMTIwNTAzMTMxODIyWhcNMTMwNTAzMTMxODIyWjBFMQswCQYDVQQGEwJBVTETMBEGA1UECBMKU29tZS1TdGF0ZTEhMB8GA1UEChMYSW50ZXJuZXQgV2lkZ2l0cyBQdHkgTHRkMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvK5hMPv/R5IFmwWyJOyEaFUrF/ZsmN+Gip8hvR6rLP3YPNx9iFYvPcZllFmuVwyaz7YT2N5BsqTwLdyi5v4HY4fUtuz0p8jIPoSd6dfDvcnSpf4QLTOgOaL3ciPEbgDHH2tnIksukoWzqCYva+qFZ74NFl19swXotW9fA4Jzs4QIDAQABo4GnMIGkMB0GA1UdDgQWBBRU1WEHDnP8Hr7ZulxrSzEwOcYpMzB1BgNVHSMEbjBsgBRU1WEHDnP8Hr7ZulxrSzEwOcYpM6FJpEcwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgTClNvbWUtU3RhdGUxITAfBgNVBAoTGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZIIJAOUHvh4oho0tMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEASY/9SAOK57q9mGnNJJeyDbmyGrAHSJTod646xTHYkMvhUqwHyk9PTr5bdfmswpmyVn+AQ43U2tU5vnpTBmKpHWD2+HSHgGa92mMLrfBOd8EBZ329NL3N2HDPIaHr4NPGyhNrSK3QVOnAq2D0jlyrGYJlLli1NxHiBz7FCEJaVI8=</X509Certificate>
28
+ </X509Data>
29
+ </KeyInfo>
30
+ </Signature>
31
+ </ApplicationRequest>
data/spec/signer_spec.rb CHANGED
@@ -1,8 +1,8 @@
1
1
  require "spec_helper"
2
2
 
3
3
  describe Signer do
4
- it "should digest and sign the XML" do
5
- input_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'input.xml')
4
+ it "should digest and sign SOAP XML with security node and binary token" do
5
+ input_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'input_1.xml')
6
6
  cert_file = File.join(File.dirname(__FILE__), 'fixtures', 'cert.pem')
7
7
  private_key_file = File.join(File.dirname(__FILE__), 'fixtures', 'key.pem')
8
8
 
@@ -18,12 +18,33 @@ describe Signer do
18
18
  signer.digest!(node)
19
19
  end
20
20
 
21
- signer.sign!
21
+ signer.sign!(:security_token => true)
22
22
 
23
- # File.open(File.join(File.dirname(__FILE__), 'fixtures', 'output.xml'), "w") do |f|
23
+ # File.open(File.join(File.dirname(__FILE__), 'fixtures', 'output_1.xml'), "w") do |f|
24
24
  # f.write signer.document.to_s
25
25
  # end
26
- output_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'output.xml')
26
+ output_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'output_1.xml')
27
+
28
+ signer.to_xml.should == Nokogiri::XML(File.read(output_xml_file), &:noblanks).to_xml(:save_with => 0)
29
+ end
30
+
31
+ it "should sign simple XML" do
32
+ input_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'input_2.xml')
33
+ cert_file = File.join(File.dirname(__FILE__), 'fixtures', 'cert.pem')
34
+ private_key_file = File.join(File.dirname(__FILE__), 'fixtures', 'key.pem')
35
+
36
+ signer = Signer.new(File.read(input_xml_file))
37
+ signer.cert = OpenSSL::X509::Certificate.new(File.read(cert_file))
38
+ signer.private_key = OpenSSL::PKey::RSA.new(File.read(private_key_file), "test")
39
+ signer.security_node = signer.document.root
40
+ signer.security_token_id = ""
41
+ signer.digest!(signer.document, :id => "")
42
+ signer.sign!(:issuer_serial => true)
43
+
44
+ # File.open(File.join(File.dirname(__FILE__), 'fixtures', 'output_2.xml'), "w") do |f|
45
+ # f.write signer.document.to_s
46
+ # end
47
+ output_xml_file = File.join(File.dirname(__FILE__), 'fixtures', 'output_2.xml')
27
48
 
28
49
  signer.to_xml.should == Nokogiri::XML(File.read(output_xml_file), &:noblanks).to_xml(:save_with => 0)
29
50
  end
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.0.0
4
+ version: 1.1.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-05-03 00:00:00.000000000 Z
12
+ date: 2012-06-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -71,9 +71,11 @@ files:
71
71
  - README.md
72
72
  - LICENSE
73
73
  - spec/fixtures/cert.pem
74
- - spec/fixtures/input.xml
74
+ - spec/fixtures/input_1.xml
75
+ - spec/fixtures/input_2.xml
75
76
  - spec/fixtures/key.pem
76
- - spec/fixtures/output.xml
77
+ - spec/fixtures/output_1.xml
78
+ - spec/fixtures/output_2.xml
77
79
  - spec/signer_spec.rb
78
80
  - spec/spec_helper.rb
79
81
  homepage: ''
@@ -96,15 +98,16 @@ required_rubygems_version: !ruby/object:Gem::Requirement
96
98
  version: '0'
97
99
  requirements: []
98
100
  rubyforge_project:
99
- rubygems_version: 1.8.21
101
+ rubygems_version: 1.8.24
100
102
  signing_key:
101
103
  specification_version: 3
102
104
  summary: WS Security XML signer
103
105
  test_files:
104
106
  - spec/fixtures/cert.pem
105
- - spec/fixtures/input.xml
107
+ - spec/fixtures/input_1.xml
108
+ - spec/fixtures/input_2.xml
106
109
  - spec/fixtures/key.pem
107
- - spec/fixtures/output.xml
110
+ - spec/fixtures/output_1.xml
111
+ - spec/fixtures/output_2.xml
108
112
  - spec/signer_spec.rb
109
113
  - spec/spec_helper.rb
110
- has_rdoc: