pki_express 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +3 -0
  3. data/.gitignore +28 -0
  4. data/CHANGELOG.md +2 -0
  5. data/Gemfile +4 -0
  6. data/README.md +24 -0
  7. data/Rakefile +1 -0
  8. data/lib/pki_express.rb +48 -0
  9. data/lib/pki_express/auth_complete_result.rb +22 -0
  10. data/lib/pki_express/auth_start_result.rb +77 -0
  11. data/lib/pki_express/authentication.rb +285 -0
  12. data/lib/pki_express/base_signer.rb +55 -0
  13. data/lib/pki_express/cades_signature_starter.rb +242 -0
  14. data/lib/pki_express/command_error.rb +14 -0
  15. data/lib/pki_express/commands.rb +21 -0
  16. data/lib/pki_express/enum.rb +9 -0
  17. data/lib/pki_express/error_codes.rb +46 -0
  18. data/lib/pki_express/installation_not_found_error.rb +8 -0
  19. data/lib/pki_express/name.rb +48 -0
  20. data/lib/pki_express/pades_horizontal_align.rb +9 -0
  21. data/lib/pki_express/pades_measurement_units.rb +8 -0
  22. data/lib/pki_express/pades_page_optimization.rb +51 -0
  23. data/lib/pki_express/pades_page_orientation.rb +9 -0
  24. data/lib/pki_express/pades_paper_size.rb +21 -0
  25. data/lib/pki_express/pades_signature_starter.rb +232 -0
  26. data/lib/pki_express/pades_size.rb +17 -0
  27. data/lib/pki_express/pades_text_horizontal_align.rb +8 -0
  28. data/lib/pki_express/pades_vertical_align.rb +9 -0
  29. data/lib/pki_express/pades_visual_auto_positioning.rb +22 -0
  30. data/lib/pki_express/pades_visual_image.rb +52 -0
  31. data/lib/pki_express/pades_visual_manual_positioning.rb +17 -0
  32. data/lib/pki_express/pades_visual_positioning.rb +28 -0
  33. data/lib/pki_express/pades_visual_rectangle.rb +74 -0
  34. data/lib/pki_express/pades_visual_representation.rb +22 -0
  35. data/lib/pki_express/pades_visual_text.rb +35 -0
  36. data/lib/pki_express/pk_certificate.rb +62 -0
  37. data/lib/pki_express/pki_brazil_certificate_fields.rb +58 -0
  38. data/lib/pki_express/pki_brazil_certificate_types.rb +19 -0
  39. data/lib/pki_express/pki_express_config.rb +26 -0
  40. data/lib/pki_express/pki_express_operator.rb +216 -0
  41. data/lib/pki_express/pki_italy_certificate_fields.rb +16 -0
  42. data/lib/pki_express/pki_italy_certificate_types.rb +11 -0
  43. data/lib/pki_express/signature_finisher.rb +298 -0
  44. data/lib/pki_express/signature_start_result.rb +13 -0
  45. data/lib/pki_express/signature_starter.rb +115 -0
  46. data/lib/pki_express/signer.rb +106 -0
  47. data/lib/pki_express/standard_signature_policies.rb +36 -0
  48. data/lib/pki_express/timestamp_authority.rb +51 -0
  49. data/lib/pki_express/validation_error.rb +8 -0
  50. data/lib/pki_express/validation_item.rb +43 -0
  51. data/lib/pki_express/validation_results.rb +121 -0
  52. data/lib/pki_express/version.rb +3 -0
  53. data/lib/pki_express/version_manager.rb +21 -0
  54. data/pki_express.gemspec +27 -0
  55. 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,9 @@
1
+ module PkiExpress
2
+ class Enum
3
+ VALUES = []
4
+
5
+ def self.contains?(value)
6
+ VALUES.include? (value)
7
+ end
8
+ end
9
+ 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,8 @@
1
+ module PkiExpress
2
+ class InstallationNotFoundError < CommandError
3
+
4
+ def initialize(message, inner_error=nil)
5
+ super(ErrorCodes::COMMAND_NOT_FOUND, message, inner_error)
6
+ end
7
+ end
8
+ 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