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