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.
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,9 @@
1
+ module PkiExpress
2
+ class PadesHorizontalAlign < Enum
3
+ LEFT = 'Left'
4
+ CENTER = 'Center'
5
+ RIGHT = 'Right'
6
+
7
+ VALUES = [ LEFT, CENTER, RIGHT ]
8
+ end
9
+ end
@@ -0,0 +1,8 @@
1
+ module PkiExpress
2
+ class PadesMeasurementUnits < Enum
3
+ CENTIMETERS = 'Centimeters'
4
+ PDF_POINTS = 'PdfPoints'
5
+
6
+ VALUES = [ CENTIMETERS, PDF_POINTS ]
7
+ end
8
+ end
@@ -0,0 +1,51 @@
1
+ module PkiExpress
2
+ class PadesPageOptimization
3
+ attr_reader :custom_paper_size, :paper_size, :page_orientation
4
+
5
+ def initialize(paper_size=nil, custom_paper_size=nil)
6
+ @page_orientation = PadesPageOrientation::AUTO
7
+ if custom_paper_size
8
+ @paper_size = PadesPaperSize::CUSTOM
9
+ @custom_paper_size = custom_paper_size
10
+ else
11
+ @paper_size = paper_size
12
+ end
13
+ end
14
+
15
+ def custom_paper_size=(value)
16
+ @custom_paper_size = value
17
+ @paper_size = PadesPaperSize::CUSTOM
18
+ end
19
+
20
+ def paper_size=(value)
21
+ unless PadesPaperSize.contains?(value)
22
+ raise 'The provided "paper_size" is not valid. Try using PadesPaperSize constants'
23
+ end
24
+ @paper_size = value
25
+ end
26
+
27
+ def page_orientation=(value)
28
+ unless PadesPageOrientation.contains?(value)
29
+ raise 'The provided "page_orientation" is not valid. Try using PadesPageOrientation constants'
30
+ end
31
+ @page_orientation = value
32
+ end
33
+
34
+ def to_model
35
+ custom_paper_size = nil
36
+ if @paper_size == PadesPaperSize::CUSTOM
37
+ if @custom_paper_size
38
+ custom_paper_size = @custom_paper_size&.to_model
39
+ else
40
+ raise 'paper_size is set to :custom but no custom_paper_size was set'
41
+ end
42
+ end
43
+
44
+ {
45
+ 'pageSize': @paper_size,
46
+ 'customPageSize': custom_paper_size,
47
+ 'pageOrientation': @page_orientation,
48
+ }
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,9 @@
1
+ module PkiExpress
2
+ class PadesPageOrientation < Enum
3
+ AUTO = 'Auto'
4
+ PORTRAIT = 'Portrait'
5
+ LANDSCAPE = 'Landscape'
6
+
7
+ VALUES = [ AUTO, PORTRAIT, LANDSCAPE ]
8
+ end
9
+ end
@@ -0,0 +1,21 @@
1
+ module PkiExpress
2
+ class PadesPaperSize < Enum
3
+ CUSTOM = 'Custom'
4
+ A0 = 'A0'
5
+ A1 = 'A1'
6
+ A2 = 'A2'
7
+ A3 = 'A3'
8
+ A4 = 'A4'
9
+ A5 = 'A5'
10
+ A6 = 'A6'
11
+ A7 = 'A7'
12
+ A8 = 'A8'
13
+ LETTER = 'Letter'
14
+ LEGAL = 'Legal'
15
+ LEDGER = 'Ledger'
16
+
17
+ VALUES = [
18
+ CUSTOM, A0, A1, A2, A3, A4, A5, A6, A7, A8, LETTER, LEGAL, LEDGER
19
+ ]
20
+ end
21
+ end
@@ -0,0 +1,232 @@
1
+ module PkiExpress
2
+ class PadesSignatureStarter < SignatureStarter
3
+ attr_accessor :suppress_default_visual_representation
4
+
5
+ def initialize(config=PkiExpressConfig.new)
6
+ super(config)
7
+ @pdf_to_sign_path = nil
8
+ @vr_json_path = nil
9
+ @suppress_default_visual_representation = false
10
+ end
11
+
12
+ # region The "pdf_to_sign" accessors
13
+
14
+ def pdf_to_sign
15
+ _get_pdf_to_sign
16
+ end
17
+
18
+ def _get_pdf_to_sign
19
+ unless @pdf_to_sign_path
20
+ return nil
21
+ end
22
+
23
+ File.read(@pdf_to_sign_path)
24
+ end
25
+ private :_get_pdf_to_sign
26
+
27
+ def pdf_to_sign=(content_raw)
28
+ _set_pdf_to_sign(content_raw)
29
+ end
30
+
31
+ def _set_pdf_to_sign(content_raw)
32
+ unless content_raw
33
+ raise 'The provided "pdf_to_sign" is not valid'
34
+ end
35
+
36
+ temp_file_path = self.create_temp_file
37
+ File.open(temp_file_path, 'wb') do |f|
38
+ f.write(content_raw)
39
+ end
40
+ @pdf_to_sign_path = temp_file_path
41
+ end
42
+ private :_set_pdf_to_sign
43
+
44
+ def pdf_to_sign_base64
45
+ _get_pdf_to_sign_base64
46
+ end
47
+
48
+ def _get_pdf_to_sign_base64
49
+ unless @pdf_to_sign_path
50
+ return nil
51
+ end
52
+
53
+ content = File.read(@pdf_to_sign_path)
54
+ Base64.encode64(content)
55
+ end
56
+ private :_get_pdf_to_sign_base64
57
+
58
+ def pdf_to_sign_base64=(content_base64)
59
+ _set_pdf_to_sign_base64(content_base64)
60
+ end
61
+
62
+ def _set_pdf_to_sign_base64(content_base64)
63
+ unless content_base64
64
+ raise 'The provided "pdf_to_sign_base64" is not valid'
65
+ end
66
+
67
+ begin
68
+ content_raw = Base64.decode64(content_base64)
69
+ rescue Error
70
+ raise 'The provided "pdf_to_sign_base64" is not Base64-encoded'
71
+ end
72
+
73
+ _set_pdf_to_sign(content_raw)
74
+ end
75
+ private :_set_pdf_to_sign_base64
76
+
77
+ def pdf_to_sign_path
78
+ _get_pdf_to_sign_path
79
+ end
80
+
81
+ def _get_pdf_to_sign_path
82
+ @pdf_to_sign_path
83
+ end
84
+ private :_get_pdf_to_sign_path
85
+
86
+ def pdf_to_sign_path=(path)
87
+ _set_pdf_to_sign_path(path)
88
+ end
89
+
90
+ def _set_pdf_to_sign_path(path)
91
+ unless path
92
+ raise 'The provided "pdf_to_sign_path" is not valid'
93
+ end
94
+ unless File.exists?(path)
95
+ raise 'The provided "pdf_to_sign_path" does not exist'
96
+ end
97
+ @pdf_to_sign_path = path
98
+ end
99
+ private :_set_pdf_to_sign_path
100
+
101
+ # endregion
102
+
103
+ # region set_visual_representation
104
+
105
+ def visual_representation_content_raw
106
+ _get_visual_representation_content_raw
107
+ end
108
+
109
+ def _get_visual_representation_content_raw
110
+ unless @vr_json_path
111
+ return nil
112
+ end
113
+
114
+ File.read(@vr_json_path)
115
+ end
116
+ private :_get_visual_representation_content_raw
117
+
118
+ def visual_representation_content_raw=(content_raw)
119
+ _set_visual_representation_content_raw(content_raw)
120
+ end
121
+
122
+ def _set_visual_representation_content_raw(content_raw)
123
+ unless content_raw
124
+ raise 'The provided "visual_representation" is not valid'
125
+ end
126
+
127
+ temp_file_path = self.create_temp_file
128
+ File.open(temp_file_path, 'wb') do |f|
129
+ f.write(content_raw)
130
+ end
131
+ @vr_json_path = temp_file_path
132
+ end
133
+ private :_set_visual_representation_content_raw
134
+
135
+ def visual_representation_path
136
+ _get_visual_representation_path
137
+ end
138
+
139
+ def _get_visual_representation_path
140
+ @vr_json_path
141
+ end
142
+ private :_get_visual_representation_path
143
+
144
+ def visual_representation_path=(path)
145
+ _set_visual_representation_path(path)
146
+ end
147
+
148
+ def _set_visual_representation_path(path)
149
+ unless path
150
+ raise 'The provided "visual_representation_path" is not valid'
151
+ end
152
+ unless File.exists?(path)
153
+ raise 'The provided "visual_representation_path" does not exist'
154
+ end
155
+ @vr_json_path = path
156
+ end
157
+ private :_set_visual_representation_path
158
+
159
+ def visual_representation
160
+ _get_visual_representation
161
+ end
162
+
163
+ def _get_visual_representation
164
+ unless @vr_json_path
165
+ return nil
166
+ end
167
+
168
+ content = File.read(@vr_json_path)
169
+ JSON.parse(content)
170
+ end
171
+ private :_get_visual_representation
172
+
173
+
174
+ def visual_representation=(vr)
175
+ _set_visual_representation(vr)
176
+ end
177
+
178
+ def _set_visual_representation(vr)
179
+ temp_file_path = self.create_temp_file
180
+ json = JSON.pretty_generate(vr.to_model)
181
+ File.open(temp_file_path, 'w') do |f|
182
+ f.write(json)
183
+ end
184
+ @vr_json_path = temp_file_path
185
+ end
186
+ private :_set_visual_representation
187
+
188
+ # endregion
189
+
190
+ def start
191
+ unless @pdf_to_sign_path
192
+ raise 'The PDF to be signed was not set'
193
+ end
194
+
195
+ unless @certificate_path
196
+ raise 'The certificate was not set'
197
+ end
198
+
199
+ # Generate transfer file.
200
+ transfer_file_id = get_transfer_filename
201
+
202
+ args = [
203
+ @pdf_to_sign_path,
204
+ @certificate_path,
205
+ File.expand_path(transfer_file_id, @config.transfer_data_folder),
206
+ ]
207
+
208
+ # Verify and add common options between signers.
209
+ verify_and_add_common_options(args)
210
+
211
+ if @vr_json_path
212
+ args.append('--visual-rep')
213
+ args.append(@vr_json_path)
214
+ end
215
+
216
+ if @suppress_default_visual_representation
217
+ args.append('--suppress-default-visual-rep')
218
+
219
+ # This option can only be used on versions greater than 1.13.1 of the
220
+ # PKI Express.
221
+ @version_manager.require_version('1.13.1')
222
+ end
223
+
224
+ # Invoke command.
225
+ result = invoke(Commands::START_PADES, args)
226
+
227
+ # Parse output and return model.
228
+ model = parse_output(result)
229
+ SignatureStartResult.new(model, transfer_file_id)
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,17 @@
1
+ module PkiExpress
2
+ class PadesSize
3
+ attr_accessor :width, :height
4
+
5
+ def initialize(width, height)
6
+ @width = width
7
+ @height = height
8
+ end
9
+
10
+ def to_model
11
+ {
12
+ width: @width,
13
+ height: @height,
14
+ }
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ module PkiExpress
2
+ class PadesTextHorizontalAlign < Enum
3
+ LEFT = 'Left'
4
+ RIGHT = 'Right'
5
+
6
+ VALUES = [ LEFT, RIGHT ]
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module PkiExpress
2
+ class PadesVerticalAlign < Enum
3
+ TOP = 'Top'
4
+ CENTER = 'Center'
5
+ BOTTOM = 'Bottom'
6
+
7
+ VALUES = [ TOP, CENTER, BOTTOM ]
8
+ end
9
+ end
@@ -0,0 +1,22 @@
1
+ module PkiExpress
2
+ class PadesVisualAutoPositioning < PadesVisualPositioning
3
+ attr_accessor :container, :signature_rectangle_size, :row_spacing
4
+
5
+ def initialize(page_number=nil, measurement_units=nil, container=nil, signature_rectangle_size=nil, row_spacing=nil)
6
+ super(page_number, measurement_units)
7
+ @container = container
8
+ @signature_rectangle_size = signature_rectangle_size
9
+ @row_spacing = row_spacing
10
+ end
11
+
12
+ def to_model
13
+ model = super
14
+ model['auto'] = {
15
+ 'container': @container&.to_model,
16
+ 'signatureRectangleSize': @signature_rectangle_size&.to_model,
17
+ 'rowSpacing': @row_spacing,
18
+ }
19
+ model
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,52 @@
1
+ module PkiExpress
2
+ class PadesVisualImage
3
+ attr_reader :horizontal_align, :vertical_align
4
+ attr_accessor :opacity, :content, :url,
5
+ :mime_type
6
+
7
+ def initialize(image_content=nil, image_url = nil, image_mime_type=nil)
8
+ @opacity = 100
9
+ @horizontal_align = PadesHorizontalAlign::CENTER
10
+ @vertical_align = PadesVerticalAlign::CENTER
11
+ @content = image_content
12
+ @url = image_url
13
+ @mime_type = image_mime_type
14
+ end
15
+
16
+ def horizontal_align=(value)
17
+ unless PadesHorizontalAlign.contains?(value)
18
+ raise 'The provided "horizontal_align" is not valid. Try using PadesHorizontalAlign constants'
19
+ end
20
+
21
+ @horizontal_align = value
22
+ end
23
+
24
+ def vertical_align=(value)
25
+ unless PadesVerticalAlign.contains?(value)
26
+ raise 'The provided "vertical_align" is not valid. Try using PadesVerticalAlign constants'
27
+ end
28
+
29
+ @vertical_align = value
30
+ end
31
+
32
+ def to_model
33
+ resource_model = {
34
+ 'mimeType': @mime_type,
35
+ }
36
+ if @content
37
+ resource_model['content'] = Base64.encode64(@content)
38
+ elsif @url
39
+ resource_model['url'] = @url
40
+ else
41
+ raise 'The image content was not set, neither its URL'
42
+ end
43
+
44
+ {
45
+ resource: resource_model,
46
+ opacity: @opacity,
47
+ horizontal_align: @horizontal_align,
48
+ vertical_align: @vertical_align,
49
+ }
50
+ end
51
+ end
52
+ end