kiji 0.1.2
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 +7 -0
- data/.gitignore +11 -0
- data/.rspec +2 -0
- data/.rubocop.yml +7 -0
- data/.rubocop_todo.yml +48 -0
- data/.travis.yml +3 -0
- data/Gemfile +4 -0
- data/Guardfile +48 -0
- data/LICENSE.md +7 -0
- data/README.md +217 -0
- data/Rakefile +1 -0
- data/bin/console +14 -0
- data/bin/setup +7 -0
- data/egov.gemspec +42 -0
- data/lib/kiji.rb +3 -0
- data/lib/kiji/access.rb +114 -0
- data/lib/kiji/api.rb +9 -0
- data/lib/kiji/authentication.rb +82 -0
- data/lib/kiji/client.rb +56 -0
- data/lib/kiji/digester.rb +77 -0
- data/lib/kiji/format/900A01020000100001.xml +126 -0
- data/lib/kiji/format/kousei.xml +174 -0
- data/lib/kiji/signer.rb +341 -0
- data/lib/kiji/version.rb +3 -0
- data/lib/kiji/zipper.rb +47 -0
- metadata +292 -0
@@ -0,0 +1,174 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8" ?>
|
2
|
+
<?xml-stylesheet href="999000000000000001.xsl" type="text/xsl"?>
|
3
|
+
<DataRoot>
|
4
|
+
<様式ID>999000000000000001</様式ID>
|
5
|
+
<様式バージョン>0001</様式バージョン>
|
6
|
+
<STYLESHEET>999000000000000001.xsl</STYLESHEET>
|
7
|
+
<構成情報 ID="構成情報">
|
8
|
+
<管理情報>
|
9
|
+
<手続番号>
|
10
|
+
<受付行政機関ID>1</受付行政機関ID>
|
11
|
+
<手続ID>aaa</手続ID>
|
12
|
+
</手続番号>
|
13
|
+
<手続名称>あ</手続名称>
|
14
|
+
<初回受付番号>aaa</初回受付番号>
|
15
|
+
<申請種別>新規申請</申請種別>
|
16
|
+
<申請者連絡先情報>
|
17
|
+
<申請者情報>
|
18
|
+
<氏名>あ</氏名>
|
19
|
+
<氏名フリガナ>あ</氏名フリガナ>
|
20
|
+
<役職>あ</役職>
|
21
|
+
<法人団体名>あ</法人団体名>
|
22
|
+
<法人団体名フリガナ>あ</法人団体名フリガナ>
|
23
|
+
<部門名>あ</部門名>
|
24
|
+
<部門名フリガナ>あ</部門名フリガナ>
|
25
|
+
<郵便番号>x</郵便番号>
|
26
|
+
<住所>あ</住所>
|
27
|
+
<住所フリガナ>あ</住所フリガナ>
|
28
|
+
<電話番号>x</電話番号>
|
29
|
+
<FAX番号>x</FAX番号>
|
30
|
+
<電子メールアドレス>x</電子メールアドレス>
|
31
|
+
</申請者情報>
|
32
|
+
<連絡先情報>
|
33
|
+
<氏名>あ</氏名>
|
34
|
+
<氏名フリガナ>あ</氏名フリガナ>
|
35
|
+
<役職>あ</役職>
|
36
|
+
<法人団体名>あ</法人団体名>
|
37
|
+
<法人団体名フリガナ>あ</法人団体名フリガナ>
|
38
|
+
<部門名>あ</部門名>
|
39
|
+
<部門名フリガナ>あ</部門名フリガナ>
|
40
|
+
<郵便番号>x</郵便番号>
|
41
|
+
<住所>あ</住所>
|
42
|
+
<住所フリガナ>あ</住所フリガナ>
|
43
|
+
<電話番号>x</電話番号>
|
44
|
+
<FAX番号>x</FAX番号>
|
45
|
+
<電子メールアドレス>x</電子メールアドレス></連絡先情報>
|
46
|
+
<委任登録票添付情報>
|
47
|
+
<発行番号></発行番号>
|
48
|
+
<委任登録票名称></委任登録票名称>
|
49
|
+
<委任登録票ファイル名称></委任登録票ファイル名称>
|
50
|
+
</委任登録票添付情報>
|
51
|
+
</申請者連絡先情報>
|
52
|
+
</管理情報>
|
53
|
+
<添付書類属性情報>
|
54
|
+
<添付種別>あ/x</添付種別>
|
55
|
+
<添付書類名称>あ/x</添付書類名称>
|
56
|
+
<添付書類ファイル名称>あ/x</添付書類ファイル名称>
|
57
|
+
<提出情報>1</提出情報></添付書類属性情報>
|
58
|
+
<手数料情報>
|
59
|
+
<手数料1>
|
60
|
+
<手数料識別子>aaa</手数料識別子>
|
61
|
+
<略科目コード>1</略科目コード>
|
62
|
+
<略科目名>あ</略科目名>
|
63
|
+
<振込金額>1</振込金額>
|
64
|
+
</手数料1>
|
65
|
+
<手数料2>
|
66
|
+
<手数料識別子>aaa</手数料識別子>
|
67
|
+
<略科目コード>1</略科目コード>
|
68
|
+
<略科目名>あ</略科目名>
|
69
|
+
<振込金額>1</振込金額>
|
70
|
+
</手数料2>
|
71
|
+
<手数料3>
|
72
|
+
<手数料識別子>aaa</手数料識別子>
|
73
|
+
<略科目コード>1</略科目コード>
|
74
|
+
<略科目名>あ</略科目名>
|
75
|
+
<振込金額>1</振込金額>
|
76
|
+
</手数料3>
|
77
|
+
<手数料4>
|
78
|
+
<手数料識別子>aaa</手数料識別子>
|
79
|
+
<略科目コード>1</略科目コード>
|
80
|
+
<略科目名>あ</略科目名>
|
81
|
+
<振込金額>1</振込金額>
|
82
|
+
</手数料4>
|
83
|
+
<手数料5>
|
84
|
+
<手数料識別子>aaa</手数料識別子>
|
85
|
+
<略科目コード>1</略科目コード>
|
86
|
+
<略科目名>あ</略科目名>
|
87
|
+
<振込金額>1</振込金額>
|
88
|
+
</手数料5>
|
89
|
+
<手数料6>
|
90
|
+
<手数料識別子>aaa</手数料識別子>
|
91
|
+
<略科目コード>1</略科目コード>
|
92
|
+
<略科目名>あ</略科目名>
|
93
|
+
<振込金額>1</振込金額>
|
94
|
+
</手数料6>
|
95
|
+
</手数料情報>
|
96
|
+
<通信欄></通信欄>
|
97
|
+
<府省照会情報>
|
98
|
+
<府省照会1>
|
99
|
+
<府省照会情報ラベル></府省照会情報ラベル>
|
100
|
+
<府省照会情報></府省照会情報>
|
101
|
+
</府省照会1>
|
102
|
+
<府省照会2>
|
103
|
+
<府省照会情報ラベル></府省照会情報ラベル>
|
104
|
+
<府省照会情報></府省照会情報>
|
105
|
+
</府省照会2>
|
106
|
+
<府省照会3>
|
107
|
+
<府省照会情報ラベル></府省照会情報ラベル>
|
108
|
+
<府省照会情報></府省照会情報>
|
109
|
+
</府省照会3>
|
110
|
+
<府省照会4>
|
111
|
+
<府省照会情報ラベル></府省照会情報ラベル>
|
112
|
+
<府省照会情報></府省照会情報>
|
113
|
+
</府省照会4>
|
114
|
+
<府省照会5>
|
115
|
+
<府省照会情報ラベル></府省照会情報ラベル>
|
116
|
+
<府省照会情報></府省照会情報>
|
117
|
+
</府省照会5>
|
118
|
+
<府省照会6>
|
119
|
+
<府省照会情報ラベル></府省照会情報ラベル>
|
120
|
+
<府省照会情報></府省照会情報>
|
121
|
+
</府省照会6>
|
122
|
+
<府省照会7>
|
123
|
+
<府省照会情報ラベル></府省照会情報ラベル>
|
124
|
+
<府省照会情報></府省照会情報>
|
125
|
+
</府省照会7>
|
126
|
+
<府省照会8>
|
127
|
+
<府省照会情報ラベル></府省照会情報ラベル>
|
128
|
+
<府省照会情報></府省照会情報>
|
129
|
+
</府省照会8>
|
130
|
+
<府省照会9>
|
131
|
+
<府省照会情報ラベル></府省照会情報ラベル>
|
132
|
+
<府省照会情報></府省照会情報>
|
133
|
+
</府省照会9>
|
134
|
+
<府省照会10>
|
135
|
+
<府省照会情報ラベル></府省照会情報ラベル>
|
136
|
+
<府省照会情報></府省照会情報>
|
137
|
+
</府省照会10>
|
138
|
+
<提出先情報>
|
139
|
+
<提出先識別子></提出先識別子>
|
140
|
+
<提出先名称></提出先名称>
|
141
|
+
</提出先情報>
|
142
|
+
<申請書属性情報>
|
143
|
+
<申請書様式ID>aaa</申請書様式ID>
|
144
|
+
<申請書様式バージョン>1</申請書様式バージョン>
|
145
|
+
<申請書様式名称>あ</申請書様式名称>
|
146
|
+
<申請書ファイル名称>x</申請書ファイル名称>
|
147
|
+
</申請書属性情報>
|
148
|
+
</構成情報>
|
149
|
+
<署名情報>
|
150
|
+
<Signature>
|
151
|
+
<SignedInfo>
|
152
|
+
<CanonicalizationMethod></CanonicalizationMethod>
|
153
|
+
<SignatureMethod></SignatureMethod>
|
154
|
+
<Reference>
|
155
|
+
<Transforms></Transforms>
|
156
|
+
<DigestMethod></DigestMethod>
|
157
|
+
<DigestValue></DigestValue>
|
158
|
+
</Reference>
|
159
|
+
</SignedInfo>
|
160
|
+
<SignatureValue></SignatureValue>
|
161
|
+
<KeyInfo>
|
162
|
+
<X509Data>
|
163
|
+
<X509Certificate></X509Certificate>
|
164
|
+
</X509Data>
|
165
|
+
</KeyInfo>
|
166
|
+
</Signature>
|
167
|
+
</署名情報>
|
168
|
+
<その他>
|
169
|
+
<納付関連情報>
|
170
|
+
<納付方法>1</納付方法>
|
171
|
+
<振込者氏名カナ>あ</振込者氏名カナ>
|
172
|
+
</納付関連情報>
|
173
|
+
</その他>
|
174
|
+
</DataRoot>
|
data/lib/kiji/signer.rb
ADDED
@@ -0,0 +1,341 @@
|
|
1
|
+
# Copyright (c) 2012 Edgars Beigarts
|
2
|
+
# Released under the MIT license
|
3
|
+
# http://opensource.org/licenses/mit-license.php
|
4
|
+
require 'nokogiri'
|
5
|
+
require 'base64'
|
6
|
+
require 'digest/sha1'
|
7
|
+
require 'openssl'
|
8
|
+
require 'kiji/digester'
|
9
|
+
require 'uri'
|
10
|
+
|
11
|
+
module Kiji
|
12
|
+
class Signer
|
13
|
+
attr_accessor :document, :private_key, :signature_algorithm_id
|
14
|
+
attr_reader :cert
|
15
|
+
attr_writer :security_node, :signature_node, :security_token_id
|
16
|
+
|
17
|
+
WSU_NAMESPACE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
|
18
|
+
WSSE_NAMESPACE = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
|
19
|
+
|
20
|
+
def initialize(document)
|
21
|
+
# self.document = Nokogiri::XML(document.to_s, &:noblanks)
|
22
|
+
self.document = Nokogiri::XML(document.to_s)
|
23
|
+
self.digest_algorithm = :sha1
|
24
|
+
self.set_default_signature_method!
|
25
|
+
|
26
|
+
yield(self) if block_given?
|
27
|
+
end
|
28
|
+
|
29
|
+
def to_xml
|
30
|
+
document.to_xml(save_with: 0, encoding: 'UTF-8')
|
31
|
+
end
|
32
|
+
|
33
|
+
# Return symbol name for supported digest algorithms and string name for custom ones.
|
34
|
+
def digest_algorithm
|
35
|
+
@digester.symbol || @digester.digest_name
|
36
|
+
end
|
37
|
+
|
38
|
+
# Allows to change algorithm for node digesting (default is SHA1).
|
39
|
+
#
|
40
|
+
# You may pass either a one of +:sha1+, +:sha256+ or +:gostr3411+ symbols
|
41
|
+
# or +Hash+ with keys +:id+ with a string, which will denote algorithm in XML Reference tag
|
42
|
+
# and +:digester+ with instance of class with interface compatible with +OpenSSL::Digest+ class.
|
43
|
+
def digest_algorithm=(algorithm)
|
44
|
+
@digester = Kiji::Digester.new(algorithm)
|
45
|
+
end
|
46
|
+
|
47
|
+
# Return symbol name for supported digest algorithms and string name for custom ones.
|
48
|
+
def signature_digest_algorithm
|
49
|
+
@sign_digester.symbol || @sign_digester.digest_name
|
50
|
+
end
|
51
|
+
|
52
|
+
# Allows to change digesting algorithm for signature creation. Same as +digest_algorithm=+
|
53
|
+
def signature_digest_algorithm=(algorithm)
|
54
|
+
@sign_digester = Kiji::Digester.new(algorithm)
|
55
|
+
end
|
56
|
+
|
57
|
+
# Receives certificate for signing and tries to guess a digest algorithm for signature creation.
|
58
|
+
#
|
59
|
+
# Will change +signature_digest_algorithm+ and +signature_algorithm_id+ for known certificate types and reset to defaults for others.
|
60
|
+
def cert=(certificate)
|
61
|
+
@cert = certificate
|
62
|
+
# Try to guess a digest algorithm for signature creation
|
63
|
+
case @cert.signature_algorithm
|
64
|
+
when 'GOST R 34.11-94 with GOST R 34.10-2001'
|
65
|
+
self.signature_digest_algorithm = :gostr3411
|
66
|
+
self.signature_algorithm_id = 'http://www.w3.org/2001/04/xmldsig-more#gostr34102001-gostr3411'
|
67
|
+
# Add clauses for other types of keys that require other digest algorithms and identifiers
|
68
|
+
else # most common 'sha1WithRSAEncryption' type included here
|
69
|
+
self.set_default_signature_method! # Reset any changes as they can become malformed
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def security_token_id
|
74
|
+
@security_token_id ||= 'uuid-639b8970-7644-4f9e-9bc4-9c2e367808fc-1'
|
75
|
+
end
|
76
|
+
|
77
|
+
def security_node
|
78
|
+
@security_node ||= document.xpath('//wsse:Security', wsse: WSSE_NAMESPACE).first
|
79
|
+
end
|
80
|
+
|
81
|
+
def canonicalize(node = document, inclusive_namespaces = nil)
|
82
|
+
# node.canonicalize(Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0, inclusive_namespaces, nil) # The last argument should be exactly +nil+ to remove comments from result
|
83
|
+
node.canonicalize(Nokogiri::XML::XML_C14N_1_1, inclusive_namespaces, nil) # The last argument should be exactly +nil+ to remove comments from result
|
84
|
+
end
|
85
|
+
|
86
|
+
# <Signature xmlns="http://www.w3.org/2000/09/xmldsig#">
|
87
|
+
def signature_node
|
88
|
+
@signature_node ||= begin
|
89
|
+
@signature_node = security_node.at_xpath('ds:Signature', ds: 'http://www.w3.org/2000/09/xmldsig#')
|
90
|
+
unless @signature_node
|
91
|
+
@signature_node = Nokogiri::XML::Node.new('Signature', document)
|
92
|
+
@signature_node['Id'] = DateTime.now.strftime('%Y%m%d%H%M%S')
|
93
|
+
@signature_node.default_namespace = 'http://www.w3.org/2000/09/xmldsig#'
|
94
|
+
security_node.add_child(@signature_node)
|
95
|
+
end
|
96
|
+
@signature_node
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# <SignedInfo>
|
101
|
+
# <CanonicalizationMethod Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
|
102
|
+
# <SignatureMethod Algorithm="http://www.w3.org/2000/09/xmldsig#rsa-sha1"/>
|
103
|
+
# ...
|
104
|
+
# </SignedInfo>
|
105
|
+
def signed_info_node
|
106
|
+
node = signature_node.at_xpath('ds:SignedInfo', ds: 'http://www.w3.org/2000/09/xmldsig#')
|
107
|
+
unless node
|
108
|
+
node = Nokogiri::XML::Node.new('SignedInfo', document)
|
109
|
+
signature_node.add_child(node)
|
110
|
+
canonicalization_method_node = Nokogiri::XML::Node.new('CanonicalizationMethod', document)
|
111
|
+
canonicalization_method_node['Algorithm'] = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
|
112
|
+
node.add_child(canonicalization_method_node)
|
113
|
+
signature_method_node = Nokogiri::XML::Node.new('SignatureMethod', document)
|
114
|
+
signature_method_node['Algorithm'] = signature_algorithm_id
|
115
|
+
node.add_child(signature_method_node)
|
116
|
+
end
|
117
|
+
node
|
118
|
+
end
|
119
|
+
|
120
|
+
# <o:BinarySecurityToken u:Id="" 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">
|
121
|
+
# ...
|
122
|
+
# </o:BinarySecurityToken>
|
123
|
+
# <SignedInfo>
|
124
|
+
# ...
|
125
|
+
# </SignedInfo>
|
126
|
+
# <KeyInfo>
|
127
|
+
# <o:SecurityTokenReference>
|
128
|
+
# <o: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"/>
|
129
|
+
# </o:SecurityTokenReference>
|
130
|
+
# </KeyInfo>
|
131
|
+
def binary_security_token_node
|
132
|
+
node = document.at_xpath('wsse:BinarySecurityToken', wsse: WSSE_NAMESPACE)
|
133
|
+
unless node
|
134
|
+
node = Nokogiri::XML::Node.new('BinarySecurityToken', document)
|
135
|
+
node['ValueType'] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3'
|
136
|
+
node['EncodingType'] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary'
|
137
|
+
node.content = Base64.encode64(cert.to_der).gsub("\n", '')
|
138
|
+
signature_node.add_previous_sibling(node)
|
139
|
+
wsse_ns = namespace_prefix(node, WSSE_NAMESPACE, 'wsse')
|
140
|
+
wsu_ns = namespace_prefix(node, WSU_NAMESPACE, 'wsu')
|
141
|
+
node["#{wsu_ns}:Id"] = security_token_id
|
142
|
+
key_info_node = Nokogiri::XML::Node.new('KeyInfo', document)
|
143
|
+
security_token_reference_node = Nokogiri::XML::Node.new("#{wsse_ns}:SecurityTokenReference", document)
|
144
|
+
key_info_node.add_child(security_token_reference_node)
|
145
|
+
reference_node = Nokogiri::XML::Node.new("#{wsse_ns}:Reference", document)
|
146
|
+
reference_node['ValueType'] = 'http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3'
|
147
|
+
reference_node['URI'] = "##{security_token_id}"
|
148
|
+
security_token_reference_node.add_child(reference_node)
|
149
|
+
signed_info_node.add_next_sibling(key_info_node)
|
150
|
+
end
|
151
|
+
node
|
152
|
+
end
|
153
|
+
|
154
|
+
# <KeyInfo>
|
155
|
+
# <X509Data>
|
156
|
+
# <X509Certificate>MIID+jCCAuKgAwIBA...</X509Certificate>
|
157
|
+
# </X509Data>
|
158
|
+
# </KeyInfo>
|
159
|
+
def x509_data_node
|
160
|
+
# issuer_name_node = Nokogiri::XML::Node.new('X509IssuerName', document)
|
161
|
+
# issuer_name_node.content = "System.Security.Cryptography.X509Certificates.X500DistinguishedName"
|
162
|
+
#
|
163
|
+
# issuer_number_node = Nokogiri::XML::Node.new('X509SerialNumber', document)
|
164
|
+
# issuer_number_node.content = cert.serial
|
165
|
+
#
|
166
|
+
# issuer_serial_node = Nokogiri::XML::Node.new('X509IssuerSerial', document)
|
167
|
+
# issuer_serial_node.add_child(issuer_name_node)
|
168
|
+
# issuer_serial_node.add_child(issuer_number_node)
|
169
|
+
|
170
|
+
cetificate_node = Nokogiri::XML::Node.new('X509Certificate', document)
|
171
|
+
cetificate_node.content = Base64.encode64(cert.to_der).gsub("\n", '')
|
172
|
+
|
173
|
+
data_node = Nokogiri::XML::Node.new('X509Data', document)
|
174
|
+
# data_node.add_child(issuer_serial_node)
|
175
|
+
data_node.add_child(cetificate_node)
|
176
|
+
|
177
|
+
key_info_node = Nokogiri::XML::Node.new('KeyInfo', document)
|
178
|
+
key_info_node.add_child(data_node)
|
179
|
+
|
180
|
+
signed_info_node.add_next_sibling(key_info_node)
|
181
|
+
|
182
|
+
data_node
|
183
|
+
end
|
184
|
+
|
185
|
+
##
|
186
|
+
# Digests some +target_node+, which integrity you wish to track. Any changes in digested node will invalidate signed message.
|
187
|
+
# All digest should be calculated **before** signing.
|
188
|
+
#
|
189
|
+
# Available options:
|
190
|
+
# * [+:id+] Id for the node, if you don't want to use automatically calculated one
|
191
|
+
# * [+:inclusive_namespaces+] Array of namespace prefixes which definitions should be added to node during canonicalization
|
192
|
+
# * [+:enveloped+]
|
193
|
+
#
|
194
|
+
# Example of XML that will be inserted in message for call like <tt>digest!(node, inclusive_namespaces: ['soap'])</tt>:
|
195
|
+
#
|
196
|
+
# <Reference URI="#_0">
|
197
|
+
# <Transforms>
|
198
|
+
# <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315">
|
199
|
+
# <ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="soap" />
|
200
|
+
# </Transform>
|
201
|
+
# </Transforms>
|
202
|
+
# <DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1"/>
|
203
|
+
# <DigestValue>aeqXriJuUCk4tPNPAGDXGqHj6ao=</DigestValue>
|
204
|
+
# </Reference>
|
205
|
+
|
206
|
+
def digest!(target_node, options = {})
|
207
|
+
wsu_ns = namespace_prefix(target_node, WSU_NAMESPACE)
|
208
|
+
current_id = target_node["#{wsu_ns}:Id"] if wsu_ns
|
209
|
+
id = options[:id] || current_id || "_#{Digest::SHA1.hexdigest(target_node.to_s)}"
|
210
|
+
# if id.to_s.size > 0
|
211
|
+
# wsu_ns ||= namespace_prefix(target_node, WSU_NAMESPACE, 'wsu')
|
212
|
+
# target_node["#{wsu_ns}:Id"] = id.to_s
|
213
|
+
# end
|
214
|
+
target_canon = canonicalize(target_node, options[:inclusive_namespaces])
|
215
|
+
# target_digest = Base64.encode64(@digester.digest(target_canon)).strip
|
216
|
+
target_digest = @digester.base64(target_canon)
|
217
|
+
|
218
|
+
reference_node = Nokogiri::XML::Node.new('Reference', document)
|
219
|
+
reference_node['URI'] = id.to_s.size > 0 ? encode_ja(id) : ''
|
220
|
+
signed_info_node.add_child(reference_node)
|
221
|
+
|
222
|
+
transforms_node = Nokogiri::XML::Node.new('Transforms', document)
|
223
|
+
reference_node.add_child(transforms_node)
|
224
|
+
|
225
|
+
transform_node = Nokogiri::XML::Node.new('Transform', document)
|
226
|
+
if options[:enveloped]
|
227
|
+
transform_node['Algorithm'] = 'http://www.w3.org/2000/09/xmldsig#enveloped-signature'
|
228
|
+
else
|
229
|
+
# transform_node['Algorithm'] = 'http://www.w3.org/2001/10/xml-exc-c14n#'
|
230
|
+
transform_node['Algorithm'] = 'http://www.w3.org/TR/2001/REC-xml-c14n-20010315'
|
231
|
+
end
|
232
|
+
if options[:inclusive_namespaces]
|
233
|
+
inclusive_namespaces_node = Nokogiri::XML::Node.new('ec:InclusiveNamespaces', document)
|
234
|
+
inclusive_namespaces_node.add_namespace_definition('ec', transform_node['Algorithm'])
|
235
|
+
inclusive_namespaces_node['PrefixList'] = options[:inclusive_namespaces].join(' ')
|
236
|
+
transform_node.add_child(inclusive_namespaces_node)
|
237
|
+
end
|
238
|
+
transforms_node.add_child(transform_node)
|
239
|
+
|
240
|
+
digest_method_node = Nokogiri::XML::Node.new('DigestMethod', document)
|
241
|
+
digest_method_node['Algorithm'] = @digester.digest_id
|
242
|
+
reference_node.add_child(digest_method_node)
|
243
|
+
|
244
|
+
digest_value_node = Nokogiri::XML::Node.new('DigestValue', document)
|
245
|
+
digest_value_node.content = target_digest
|
246
|
+
reference_node.add_child(digest_value_node)
|
247
|
+
self
|
248
|
+
end
|
249
|
+
|
250
|
+
def digest_file!(file_content, options = {})
|
251
|
+
# target_digest = Base64.encode64(@digester.digest(file_content)).strip
|
252
|
+
target_digest = @digester.base64(file_content)
|
253
|
+
|
254
|
+
reference_node = Nokogiri::XML::Node.new('Reference', document)
|
255
|
+
id = options[:id]
|
256
|
+
reference_node['URI'] = id.to_s.size > 0 ? encode_ja(id) : ''
|
257
|
+
signed_info_node.add_child(reference_node)
|
258
|
+
|
259
|
+
digest_method_node = Nokogiri::XML::Node.new('DigestMethod', document)
|
260
|
+
digest_method_node['Algorithm'] = @digester.digest_id
|
261
|
+
reference_node.add_child(digest_method_node)
|
262
|
+
|
263
|
+
digest_value_node = Nokogiri::XML::Node.new('DigestValue', document)
|
264
|
+
digest_value_node.content = target_digest
|
265
|
+
reference_node.add_child(digest_value_node)
|
266
|
+
self
|
267
|
+
end
|
268
|
+
|
269
|
+
##
|
270
|
+
# Sign document with provided certificate, private key and other options
|
271
|
+
#
|
272
|
+
# This should be very last action before calling +to_xml+, all the required nodes should be digested with +digest!+ **before** signing.
|
273
|
+
#
|
274
|
+
# Available options:
|
275
|
+
# * [+:security_token+] Serializes certificate in DER format, encodes it with Base64 and inserts it within +<BinarySecurityToken>+ tag
|
276
|
+
# * [+:issuer_serial+]
|
277
|
+
# * [+:inclusive_namespaces+] Array of namespace prefixes which definitions should be added to signed info node during canonicalization
|
278
|
+
|
279
|
+
def sign!(options = {})
|
280
|
+
binary_security_token_node if options[:security_token]
|
281
|
+
x509_data_node if options[:issuer_serial]
|
282
|
+
|
283
|
+
if options[:inclusive_namespaces]
|
284
|
+
c14n_method_node = signed_info_node.at_xpath('ds:CanonicalizationMethod', ds: 'http://www.w3.org/2000/09/xmldsig#')
|
285
|
+
inclusive_namespaces_node = Nokogiri::XML::Node.new('ec:InclusiveNamespaces', document)
|
286
|
+
inclusive_namespaces_node.add_namespace_definition('ec', c14n_method_node['Algorithm'])
|
287
|
+
inclusive_namespaces_node['PrefixList'] = options[:inclusive_namespaces].join(' ')
|
288
|
+
c14n_method_node.add_child(inclusive_namespaces_node)
|
289
|
+
end
|
290
|
+
|
291
|
+
signed_info_canon = canonicalize(signed_info_node, options[:inclusive_namespaces])
|
292
|
+
|
293
|
+
signature = private_key.sign(@sign_digester.digester, signed_info_canon)
|
294
|
+
signature_value_digest = Base64.encode64(signature).gsub("\n", '')
|
295
|
+
|
296
|
+
signature_value_node = Nokogiri::XML::Node.new('SignatureValue', document)
|
297
|
+
signature_value_node.content = signature_value_digest
|
298
|
+
signed_info_node.add_next_sibling(signature_value_node)
|
299
|
+
self
|
300
|
+
end
|
301
|
+
|
302
|
+
protected
|
303
|
+
|
304
|
+
def encode_ja(str)
|
305
|
+
ret = ''
|
306
|
+
str.split(//).each do |c|
|
307
|
+
if /[!-~]/ =~ c
|
308
|
+
ret.concat(c)
|
309
|
+
else
|
310
|
+
ret.concat(CGI.escape(c))
|
311
|
+
end
|
312
|
+
end
|
313
|
+
ret
|
314
|
+
end
|
315
|
+
|
316
|
+
# Reset digest algorithm for signature creation and signature algorithm identifier
|
317
|
+
def set_default_signature_method!
|
318
|
+
# self.signature_digest_algorithm = :sha1
|
319
|
+
# self.signature_algorithm_id = 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
|
320
|
+
self.signature_digest_algorithm = :sha256
|
321
|
+
self.signature_algorithm_id = 'http://www.w3.org/2001/04/xmldsig-more#rsa-sha256'
|
322
|
+
end
|
323
|
+
|
324
|
+
##
|
325
|
+
# Searches in namespaces, defined on +target_node+ or its ancestors,
|
326
|
+
# for the +namespace+ with given URI and returns its prefix.
|
327
|
+
#
|
328
|
+
# If there is no such namespace and +desired_prefix+ is specified,
|
329
|
+
# adds such a namespace to +target_node+ with +desired_prefix+
|
330
|
+
|
331
|
+
def namespace_prefix(target_node, namespace, desired_prefix = nil)
|
332
|
+
ns = target_node.namespaces.key(namespace)
|
333
|
+
if ns
|
334
|
+
ns.match(/(?:xmlns:)?(.*)/) && Regexp.last_match(1)
|
335
|
+
elsif desired_prefix
|
336
|
+
target_node.add_namespace_definition(desired_prefix, namespace)
|
337
|
+
desired_prefix
|
338
|
+
end
|
339
|
+
end
|
340
|
+
end
|
341
|
+
end
|