pki_express 1.0.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.
- checksums.yaml +7 -0
- data/.gitattributes +3 -0
- data/.gitignore +28 -0
- data/CHANGELOG.md +2 -0
- data/Gemfile +4 -0
- data/README.md +24 -0
- data/Rakefile +1 -0
- data/lib/pki_express.rb +48 -0
- data/lib/pki_express/auth_complete_result.rb +22 -0
- data/lib/pki_express/auth_start_result.rb +77 -0
- data/lib/pki_express/authentication.rb +285 -0
- data/lib/pki_express/base_signer.rb +55 -0
- data/lib/pki_express/cades_signature_starter.rb +242 -0
- data/lib/pki_express/command_error.rb +14 -0
- data/lib/pki_express/commands.rb +21 -0
- data/lib/pki_express/enum.rb +9 -0
- data/lib/pki_express/error_codes.rb +46 -0
- data/lib/pki_express/installation_not_found_error.rb +8 -0
- data/lib/pki_express/name.rb +48 -0
- data/lib/pki_express/pades_horizontal_align.rb +9 -0
- data/lib/pki_express/pades_measurement_units.rb +8 -0
- data/lib/pki_express/pades_page_optimization.rb +51 -0
- data/lib/pki_express/pades_page_orientation.rb +9 -0
- data/lib/pki_express/pades_paper_size.rb +21 -0
- data/lib/pki_express/pades_signature_starter.rb +232 -0
- data/lib/pki_express/pades_size.rb +17 -0
- data/lib/pki_express/pades_text_horizontal_align.rb +8 -0
- data/lib/pki_express/pades_vertical_align.rb +9 -0
- data/lib/pki_express/pades_visual_auto_positioning.rb +22 -0
- data/lib/pki_express/pades_visual_image.rb +52 -0
- data/lib/pki_express/pades_visual_manual_positioning.rb +17 -0
- data/lib/pki_express/pades_visual_positioning.rb +28 -0
- data/lib/pki_express/pades_visual_rectangle.rb +74 -0
- data/lib/pki_express/pades_visual_representation.rb +22 -0
- data/lib/pki_express/pades_visual_text.rb +35 -0
- data/lib/pki_express/pk_certificate.rb +62 -0
- data/lib/pki_express/pki_brazil_certificate_fields.rb +58 -0
- data/lib/pki_express/pki_brazil_certificate_types.rb +19 -0
- data/lib/pki_express/pki_express_config.rb +26 -0
- data/lib/pki_express/pki_express_operator.rb +216 -0
- data/lib/pki_express/pki_italy_certificate_fields.rb +16 -0
- data/lib/pki_express/pki_italy_certificate_types.rb +11 -0
- data/lib/pki_express/signature_finisher.rb +298 -0
- data/lib/pki_express/signature_start_result.rb +13 -0
- data/lib/pki_express/signature_starter.rb +115 -0
- data/lib/pki_express/signer.rb +106 -0
- data/lib/pki_express/standard_signature_policies.rb +36 -0
- data/lib/pki_express/timestamp_authority.rb +51 -0
- data/lib/pki_express/validation_error.rb +8 -0
- data/lib/pki_express/validation_item.rb +43 -0
- data/lib/pki_express/validation_results.rb +121 -0
- data/lib/pki_express/version.rb +3 -0
- data/lib/pki_express/version_manager.rb +21 -0
- data/pki_express.gemspec +27 -0
- metadata +129 -0
@@ -0,0 +1,55 @@
|
|
1
|
+
module PkiExpress
|
2
|
+
|
3
|
+
class BaseSigner < PkiExpressOperator
|
4
|
+
|
5
|
+
def initialize(config=PkiExpressConfig.new)
|
6
|
+
super(config)
|
7
|
+
end
|
8
|
+
|
9
|
+
def verify_and_add_common_options(args)
|
10
|
+
|
11
|
+
if StandardSignaturePolicies::require_timestamp(@signature_policy) and
|
12
|
+
@timestamp_authority.nil?
|
13
|
+
raise 'The provided policy requires a timestamp authority and none was provided.'
|
14
|
+
end
|
15
|
+
|
16
|
+
# Set the signature policy.
|
17
|
+
unless @signature_policy.nil?
|
18
|
+
args << '--policy'
|
19
|
+
args << @signature_policy
|
20
|
+
|
21
|
+
# This operation evolved after version 1.5 to other signature policies.
|
22
|
+
if @signature_policy != StandardSignaturePolicies::XML_DSIG_BASIC and @signature_policy != StandardSignaturePolicies::NFE_PADRAO_NACIONAL
|
23
|
+
# This operation evolved after version 1.5 to other signature
|
24
|
+
# policies.
|
25
|
+
@version_manager.require_version('1.5')
|
26
|
+
end
|
27
|
+
|
28
|
+
if @signature_policy == StandardSignaturePolicies::COD_WITH_SHA1 or @signature_policy == StandardSignaturePolicies::COD_WITH_SHA256
|
29
|
+
# These policies can only be used on version greater than 1.6 of
|
30
|
+
# PKI Express.
|
31
|
+
@version_manager.require_version('1.6')
|
32
|
+
end
|
33
|
+
|
34
|
+
if @signature_policy == StandardSignaturePolicies::PKI_BRAZIL_PADES_ADR_BASICA or @signature_policy == StandardSignaturePolicies::PKI_BRAZIL_PADES_ADR_BASICA_WITH_LTV or @signature_policy == StandardSignaturePolicies::PKI_BRAZIL_PADES_ADR_TEMPO
|
35
|
+
# These policies can only be used on version greater than 1.12 of
|
36
|
+
# PKI Express.
|
37
|
+
@version_manager.require_version('1.12')
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# Add timestamp authority.
|
42
|
+
if @timestamp_authority
|
43
|
+
tsp_args = @timestamp_authority.get_cmd_arguments
|
44
|
+
args.append(*tsp_args)
|
45
|
+
|
46
|
+
|
47
|
+
# This option can only be used on version greater than 1.5 of the
|
48
|
+
# PKI Express.
|
49
|
+
@version_manager.require_version('1.5')
|
50
|
+
end
|
51
|
+
end
|
52
|
+
protected :verify_and_add_common_options
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,242 @@
|
|
1
|
+
module PkiExpress
|
2
|
+
|
3
|
+
class CadesSignatureStarter < SignatureStarter
|
4
|
+
|
5
|
+
attr_accessor :encapsulated_content
|
6
|
+
|
7
|
+
def initialize(config=PkiExpressConfig.new)
|
8
|
+
super(config)
|
9
|
+
@file_to_sign_path = nil
|
10
|
+
@data_file_path = nil
|
11
|
+
@encapsulated_content = true
|
12
|
+
end
|
13
|
+
|
14
|
+
# region The "file_to_sign" accessors
|
15
|
+
|
16
|
+
def file_to_sign
|
17
|
+
_get_file_to_sign
|
18
|
+
end
|
19
|
+
|
20
|
+
def _get_file_to_sign
|
21
|
+
unless @file_to_sign_path
|
22
|
+
return nil
|
23
|
+
end
|
24
|
+
|
25
|
+
File.read(@file_to_sign_path)
|
26
|
+
end
|
27
|
+
private :_get_file_to_sign
|
28
|
+
|
29
|
+
def file_to_sign=(content_raw)
|
30
|
+
_set_file_to_sign(content_raw)
|
31
|
+
end
|
32
|
+
|
33
|
+
def _set_file_to_sign(content_raw)
|
34
|
+
unless content_raw
|
35
|
+
raise 'The provided "file_to_sign" is not valid'
|
36
|
+
end
|
37
|
+
|
38
|
+
temp_file_path = self.create_temp_file
|
39
|
+
File.open(temp_file_path, 'wb') do |f|
|
40
|
+
f.write(content_raw)
|
41
|
+
end
|
42
|
+
@file_to_sign_path = temp_file_path
|
43
|
+
end
|
44
|
+
private :_set_file_to_sign
|
45
|
+
|
46
|
+
def file_to_sign_base64
|
47
|
+
_get_file_to_sign_base64
|
48
|
+
end
|
49
|
+
|
50
|
+
def _get_file_to_sign_base64
|
51
|
+
unless @file_to_sign_path
|
52
|
+
return nil
|
53
|
+
end
|
54
|
+
|
55
|
+
content = File.read(@file_to_sign_path)
|
56
|
+
Base64.encode64(content)
|
57
|
+
end
|
58
|
+
private :_get_file_to_sign_base64
|
59
|
+
|
60
|
+
def file_to_sign_base64=(content_base64)
|
61
|
+
_set_file_to_sign_base64(content_base64)
|
62
|
+
end
|
63
|
+
|
64
|
+
def _set_file_to_sign_base64(content_base64)
|
65
|
+
unless content_base64
|
66
|
+
raise 'The provided "file_to_sign_base64" is not valid'
|
67
|
+
end
|
68
|
+
|
69
|
+
begin
|
70
|
+
content_raw = Base64.decode64(content_base64)
|
71
|
+
rescue Error
|
72
|
+
raise 'The provided "file_to_sign_base64" is not Base64-encoded'
|
73
|
+
end
|
74
|
+
|
75
|
+
_set_file_to_sign(content_raw)
|
76
|
+
end
|
77
|
+
private :_set_file_to_sign_base64
|
78
|
+
|
79
|
+
def file_to_sign_path
|
80
|
+
_get_file_to_sign_path
|
81
|
+
end
|
82
|
+
|
83
|
+
def _get_file_to_sign_path
|
84
|
+
@file_to_sign_path
|
85
|
+
end
|
86
|
+
private :_get_file_to_sign_path
|
87
|
+
|
88
|
+
def file_to_sign_path=(path)
|
89
|
+
_set_file_to_sign_path(path)
|
90
|
+
end
|
91
|
+
|
92
|
+
def _set_file_to_sign_path(path)
|
93
|
+
unless path
|
94
|
+
raise 'The provided "file_to_sign_path" is not valid'
|
95
|
+
end
|
96
|
+
unless File.exists?(path)
|
97
|
+
raise 'The provided "file_to_sign_path" does not exist'
|
98
|
+
end
|
99
|
+
|
100
|
+
@file_to_sign_path = path
|
101
|
+
end
|
102
|
+
private :_set_file_to_sign_path
|
103
|
+
|
104
|
+
# endregion
|
105
|
+
|
106
|
+
# region The "data_file" accessors
|
107
|
+
|
108
|
+
def data_file
|
109
|
+
_get_data_file
|
110
|
+
end
|
111
|
+
|
112
|
+
def _get_data_file
|
113
|
+
unless @data_file_path
|
114
|
+
return nil
|
115
|
+
end
|
116
|
+
|
117
|
+
File.read(@data_file_path)
|
118
|
+
end
|
119
|
+
private :_get_data_file
|
120
|
+
|
121
|
+
def data_file=(content_raw)
|
122
|
+
_set_data_file(content_raw)
|
123
|
+
end
|
124
|
+
|
125
|
+
def _set_data_file(content_raw)
|
126
|
+
unless content_raw
|
127
|
+
raise 'The provided "data_file" is not valid'
|
128
|
+
end
|
129
|
+
|
130
|
+
temp_file_path = self.create_temp_file
|
131
|
+
File.open(temp_file_path, 'wb') do |f|
|
132
|
+
f.write(content_raw)
|
133
|
+
end
|
134
|
+
@data_file_path = temp_file_path
|
135
|
+
end
|
136
|
+
private :_set_data_file
|
137
|
+
|
138
|
+
def data_file_base64
|
139
|
+
_get_data_file_base64
|
140
|
+
end
|
141
|
+
|
142
|
+
def _get_data_file_base64
|
143
|
+
unless @data_file_path
|
144
|
+
return nil
|
145
|
+
end
|
146
|
+
|
147
|
+
content = File.read(@data_file_path)
|
148
|
+
Base64.encode64(content)
|
149
|
+
end
|
150
|
+
private :_get_data_file_base64
|
151
|
+
|
152
|
+
def data_file_base64=(content_base64)
|
153
|
+
_set_data_file_base64(content_base64)
|
154
|
+
end
|
155
|
+
|
156
|
+
def _set_data_file_base64(content_base64)
|
157
|
+
unless content_base64
|
158
|
+
raise 'The provided "data_file_base64" is not valid'
|
159
|
+
end
|
160
|
+
|
161
|
+
begin
|
162
|
+
content_raw = Base64.decode64(content_base64)
|
163
|
+
rescue Error
|
164
|
+
raise 'The provided "data_file_base64" is not Base64-encoded'
|
165
|
+
end
|
166
|
+
|
167
|
+
_set_data_file(content_raw)
|
168
|
+
end
|
169
|
+
private :_set_data_file_base64
|
170
|
+
|
171
|
+
def data_file_path
|
172
|
+
_get_data_file_path
|
173
|
+
end
|
174
|
+
|
175
|
+
def _get_data_file_path
|
176
|
+
@data_file_path
|
177
|
+
end
|
178
|
+
private :_get_data_file_path
|
179
|
+
|
180
|
+
def data_file_path=(path)
|
181
|
+
_set_data_file_path(path)
|
182
|
+
end
|
183
|
+
|
184
|
+
def _set_data_file_path(path)
|
185
|
+
unless path
|
186
|
+
raise 'The provided "data_file_path" is not valid'
|
187
|
+
end
|
188
|
+
unless File.exists?(path)
|
189
|
+
raise 'The provided "data_file_path" does not exist'
|
190
|
+
end
|
191
|
+
|
192
|
+
@data_file_path = path
|
193
|
+
end
|
194
|
+
private :_set_data_file_path
|
195
|
+
|
196
|
+
# endregion
|
197
|
+
|
198
|
+
def start
|
199
|
+
|
200
|
+
unless @file_to_sign_path
|
201
|
+
raise 'The file to be signed was not set'
|
202
|
+
end
|
203
|
+
|
204
|
+
unless @certificate_path
|
205
|
+
raise 'The certificate was not set'
|
206
|
+
end
|
207
|
+
|
208
|
+
# Generate transfer file.
|
209
|
+
transfer_file_id = get_transfer_filename
|
210
|
+
|
211
|
+
args = [
|
212
|
+
@file_to_sign_path,
|
213
|
+
@certificate_path,
|
214
|
+
File.expand_path(transfer_file_id, @config.transfer_data_folder),
|
215
|
+
]
|
216
|
+
|
217
|
+
# Verify and add common options between signers.
|
218
|
+
verify_and_add_common_options(args)
|
219
|
+
|
220
|
+
if @data_file_path
|
221
|
+
args.append('--data-file')
|
222
|
+
args.append(@data_file_path)
|
223
|
+
end
|
224
|
+
|
225
|
+
unless @encapsulated_content
|
226
|
+
args.append('--detached')
|
227
|
+
end
|
228
|
+
|
229
|
+
# This operation can only be used on version greater than 1.3 of the
|
230
|
+
# PKI Express.
|
231
|
+
@version_manager.require_version('1.3')
|
232
|
+
|
233
|
+
# Invoke command.
|
234
|
+
result = invoke(Commands::START_CADES, args)
|
235
|
+
|
236
|
+
# Parse output and return model.
|
237
|
+
model = parse_output(result)
|
238
|
+
SignatureStartResult.new(model, transfer_file_id)
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module PkiExpress
|
2
|
+
class CommandError < StandardError
|
3
|
+
attr_accessor :name, :code, :inner_error
|
4
|
+
|
5
|
+
def initialize(code, msg, inner_error=nil)
|
6
|
+
super(msg)
|
7
|
+
|
8
|
+
@name = self.class.name
|
9
|
+
@code = code
|
10
|
+
@inner_error = inner_error
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module PkiExpress
|
2
|
+
class Commands
|
3
|
+
SIGN_CADES = 'sign-cades',
|
4
|
+
SIGN_PADES = 'sign-pades',
|
5
|
+
SIGN_XML = 'sign-xml',
|
6
|
+
START_CADES = 'start-cades',
|
7
|
+
START_PADES = 'start-pades',
|
8
|
+
START_XML = 'start-xml',
|
9
|
+
COMPLETE_SIG = 'complete-sig',
|
10
|
+
OPEN_PADES = 'open-pades',
|
11
|
+
OPEN_CADES = 'open-cades',
|
12
|
+
EDIT_PDF = 'edit-pdf',
|
13
|
+
MERGE_CMS = 'merge-cms',
|
14
|
+
START_AUTH = 'start-auth',
|
15
|
+
COMPLETE_AUTH = 'complete-auth',
|
16
|
+
STAMP_PDF = 'stamp-pdf',
|
17
|
+
READ_CERT = 'read-cert',
|
18
|
+
GEN_KEY = 'gen-key',
|
19
|
+
CREATE_PFX = 'create-pfx'
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module PkiExpress
|
2
|
+
class ErrorCodes
|
3
|
+
OK = 0,
|
4
|
+
BAD_SYNTAX = 1,
|
5
|
+
UNKNOWN_ERROR = 2,
|
6
|
+
FILE_NOT_FOUND = 3,
|
7
|
+
BAD_CERTIFICATE = 4,
|
8
|
+
BAD_THUMBPRINT = 5,
|
9
|
+
BAD_HASH = 6,
|
10
|
+
BAD_DATA = 7,
|
11
|
+
BAD_SIGNATURE = 8,
|
12
|
+
BAD_ALGORITHM = 9,
|
13
|
+
BAD_POLICY = 10,
|
14
|
+
BAD_VISUAL_REP = 11,
|
15
|
+
UNDEFINED_FILE_REFERENCE = 12,
|
16
|
+
CERT_NOT_FOUND = 13,
|
17
|
+
VALIDATION_FAILED = 14,
|
18
|
+
IO_ERROR = 15,
|
19
|
+
NO_CERTS_WITH_KEY = 16,
|
20
|
+
NOT_ACTIVATED = 17,
|
21
|
+
ACTIVATION_ERROR = 18,
|
22
|
+
BAD_LICENSE = 19,
|
23
|
+
LICENSE_NEEDED = 20,
|
24
|
+
INVALID_LICENSE = 21,
|
25
|
+
ACCESS_DENIED = 22,
|
26
|
+
CERT_THUMB_NEEDED = 23,
|
27
|
+
BAD_PDF_CHANGES = 24,
|
28
|
+
UPDATE_NEEDED = 25,
|
29
|
+
DATA_FILE_NEEDED = 26,
|
30
|
+
NO_ENCAPSULATED_CONTENT = 27,
|
31
|
+
NONCE_NOT_FOUND = 28,
|
32
|
+
DIRECTORY_NOT_FOUND = 29,
|
33
|
+
TIMESTAMP_AUTHORITY_NOT_AVAILABLE = 30,
|
34
|
+
POLICY_REQUIRES_NETWORK = 31,
|
35
|
+
TIMESTAMP_OPTIONS_REQUIRED = 32,
|
36
|
+
CULTURE_NOT_FOUND = 33,
|
37
|
+
TIME_ZONE_NOT_FOUND = 34,
|
38
|
+
INVALID_UTC_OFFSET = 35,
|
39
|
+
KEY_SIZE_NOT_SUPPORTED = 36,
|
40
|
+
BAD_KEY_FORMAT = 37,
|
41
|
+
BAD_KEY = 38,
|
42
|
+
INVALID_TIMEOUT_VALUE = 39,
|
43
|
+
|
44
|
+
COMMAND_NOT_FOUND = 127
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module PkiExpress
|
2
|
+
|
3
|
+
class Name
|
4
|
+
|
5
|
+
attr_accessor :country, :organization, :organization_unit, :dn_qualifier,
|
6
|
+
:state_name, :common_name, :serial_number, :locality, :title,
|
7
|
+
:surname, :given_name, :initials, :pseudonym,
|
8
|
+
:generation_qualifier, :email_address
|
9
|
+
|
10
|
+
def initialize(model)
|
11
|
+
@country = nil
|
12
|
+
@organization = nil
|
13
|
+
@organization_unit = nil
|
14
|
+
@dn_qualifier = nil
|
15
|
+
@state_name = nil
|
16
|
+
@common_name = nil
|
17
|
+
@serial_number = nil
|
18
|
+
@locality = nil
|
19
|
+
@title = nil
|
20
|
+
@surname = nil
|
21
|
+
@given_name = nil
|
22
|
+
@initials = nil
|
23
|
+
@pseudonym = nil
|
24
|
+
@generation_qualifier = nil
|
25
|
+
@email_address = nil
|
26
|
+
|
27
|
+
|
28
|
+
if model
|
29
|
+
@country = model.fetch(:country)
|
30
|
+
@organization = model.fetch(:organization)
|
31
|
+
@organization_unit = model.fetch(:organizationUnit)
|
32
|
+
@dn_qualifier = model.fetch(:dnQualifier)
|
33
|
+
@state_name = model.fetch(:stateName)
|
34
|
+
@common_name = model.fetch(:commonName)
|
35
|
+
@serial_number = model.fetch(:serialNumber)
|
36
|
+
@locality = model.fetch(:locality)
|
37
|
+
@title = model.fetch(:title)
|
38
|
+
@surname = model.fetch(:surname)
|
39
|
+
@given_name = model.fetch(:givenName)
|
40
|
+
@initials = model.fetch(:initials)
|
41
|
+
@pseudonym = model.fetch(:pseudonym)
|
42
|
+
@generation_qualifier = model.fetch(:generationQualifier)
|
43
|
+
@email_address = model.fetch(:emailAddress)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|