easy_code_sign 0.1.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 (63) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +95 -0
  3. data/LICENSE +21 -0
  4. data/README.md +331 -0
  5. data/Rakefile +16 -0
  6. data/exe/easysign +7 -0
  7. data/lib/easy_code_sign/cli.rb +428 -0
  8. data/lib/easy_code_sign/configuration.rb +102 -0
  9. data/lib/easy_code_sign/deferred_signing_request.rb +104 -0
  10. data/lib/easy_code_sign/errors.rb +113 -0
  11. data/lib/easy_code_sign/pdf/appearance_builder.rb +104 -0
  12. data/lib/easy_code_sign/pdf/timestamp_handler.rb +31 -0
  13. data/lib/easy_code_sign/providers/base.rb +126 -0
  14. data/lib/easy_code_sign/providers/pkcs11_base.rb +197 -0
  15. data/lib/easy_code_sign/providers/safenet.rb +109 -0
  16. data/lib/easy_code_sign/signable/base.rb +98 -0
  17. data/lib/easy_code_sign/signable/gem_file.rb +224 -0
  18. data/lib/easy_code_sign/signable/pdf_file.rb +486 -0
  19. data/lib/easy_code_sign/signable/zip_file.rb +226 -0
  20. data/lib/easy_code_sign/signer.rb +254 -0
  21. data/lib/easy_code_sign/timestamp/client.rb +184 -0
  22. data/lib/easy_code_sign/timestamp/request.rb +114 -0
  23. data/lib/easy_code_sign/timestamp/response.rb +246 -0
  24. data/lib/easy_code_sign/timestamp/verifier.rb +227 -0
  25. data/lib/easy_code_sign/verification/certificate_chain.rb +298 -0
  26. data/lib/easy_code_sign/verification/result.rb +222 -0
  27. data/lib/easy_code_sign/verification/signature_checker.rb +196 -0
  28. data/lib/easy_code_sign/verification/trust_store.rb +140 -0
  29. data/lib/easy_code_sign/verifier.rb +426 -0
  30. data/lib/easy_code_sign/version.rb +5 -0
  31. data/lib/easy_code_sign.rb +183 -0
  32. data/plugin/.gitignore +21 -0
  33. data/plugin/Gemfile +24 -0
  34. data/plugin/Gemfile.lock +134 -0
  35. data/plugin/README.md +248 -0
  36. data/plugin/Rakefile +121 -0
  37. data/plugin/docs/API_REFERENCE.md +366 -0
  38. data/plugin/docs/DEVELOPMENT.md +522 -0
  39. data/plugin/docs/INSTALLATION.md +204 -0
  40. data/plugin/native_host/build/Rakefile +90 -0
  41. data/plugin/native_host/install/com.easysign.host.json +9 -0
  42. data/plugin/native_host/install/install_chrome.sh +81 -0
  43. data/plugin/native_host/install/install_firefox.sh +81 -0
  44. data/plugin/native_host/src/easy_sign_host.rb +158 -0
  45. data/plugin/native_host/src/protocol.rb +101 -0
  46. data/plugin/native_host/src/signing_service.rb +167 -0
  47. data/plugin/native_host/test/native_host_test.rb +113 -0
  48. data/plugin/src/easy_sign/background.rb +323 -0
  49. data/plugin/src/easy_sign/content.rb +74 -0
  50. data/plugin/src/easy_sign/inject.rb +239 -0
  51. data/plugin/src/easy_sign/messaging.rb +109 -0
  52. data/plugin/src/easy_sign/popup.rb +200 -0
  53. data/plugin/templates/manifest.json +58 -0
  54. data/plugin/templates/popup.css +223 -0
  55. data/plugin/templates/popup.html +59 -0
  56. data/sig/easy_code_sign.rbs +4 -0
  57. data/test/easy_code_sign_test.rb +122 -0
  58. data/test/pdf_signable_test.rb +569 -0
  59. data/test/signable_test.rb +334 -0
  60. data/test/test_helper.rb +18 -0
  61. data/test/timestamp_test.rb +163 -0
  62. data/test/verification_test.rb +350 -0
  63. metadata +219 -0
@@ -0,0 +1,350 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "test_helper"
4
+ require "tempfile"
5
+
6
+ class VerificationResultTest < Minitest::Test
7
+ def test_initializes_with_default_values
8
+ result = EasyCodeSign::Verification::Result.new
9
+
10
+ refute result.valid?
11
+ refute result.signature_valid?
12
+ refute result.integrity_valid?
13
+ refute result.certificate_valid?
14
+ refute result.chain_valid?
15
+ refute result.trusted?
16
+ refute result.timestamped?
17
+ assert_empty result.errors
18
+ assert_empty result.warnings
19
+ end
20
+
21
+ def test_add_error
22
+ result = EasyCodeSign::Verification::Result.new
23
+ result.add_error("Test error")
24
+
25
+ assert_includes result.errors, "Test error"
26
+ end
27
+
28
+ def test_add_warning
29
+ result = EasyCodeSign::Verification::Result.new
30
+ result.add_warning("Test warning")
31
+
32
+ assert_includes result.warnings, "Test warning"
33
+ end
34
+
35
+ def test_certificate_expired_returns_true_for_expired_cert
36
+ result = EasyCodeSign::Verification::Result.new
37
+
38
+ cert = OpenSSL::X509::Certificate.new
39
+ cert.not_before = Time.now - 86_400 * 365
40
+ cert.not_after = Time.now - 86_400 # Expired yesterday
41
+
42
+ result.signer_certificate = cert
43
+
44
+ assert result.certificate_expired?
45
+ end
46
+
47
+ def test_certificate_expired_returns_false_for_valid_cert
48
+ result = EasyCodeSign::Verification::Result.new
49
+
50
+ cert = OpenSSL::X509::Certificate.new
51
+ cert.not_before = Time.now - 86_400
52
+ cert.not_after = Time.now + 86_400 * 365
53
+
54
+ result.signer_certificate = cert
55
+
56
+ refute result.certificate_expired?
57
+ end
58
+
59
+ def test_to_h_returns_hash
60
+ result = EasyCodeSign::Verification::Result.new
61
+ result.file_path = "/path/to/file.gem"
62
+ result.file_type = :gem
63
+ result.valid = true
64
+
65
+ hash = result.to_h
66
+
67
+ assert_equal "/path/to/file.gem", hash[:file_path]
68
+ assert_equal :gem, hash[:file_type]
69
+ assert hash[:valid]
70
+ assert_kind_of Hash, hash[:checks]
71
+ end
72
+
73
+ def test_summary_returns_string
74
+ result = EasyCodeSign::Verification::Result.new
75
+ result.valid = true
76
+
77
+ cert = OpenSSL::X509::Certificate.new
78
+ cert.subject = OpenSSL::X509::Name.parse("/CN=Test Signer")
79
+ result.signer_certificate = cert
80
+ result.signer_name = "Test Signer"
81
+
82
+ summary = result.summary
83
+
84
+ assert_includes summary, "VALID"
85
+ assert_includes summary, "Test Signer"
86
+ end
87
+ end
88
+
89
+ class TrustStoreTest < Minitest::Test
90
+ def test_initializes_with_system_certs_by_default
91
+ store = EasyCodeSign::Verification::TrustStore.new
92
+
93
+ assert_instance_of OpenSSL::X509::Store, store.store
94
+ end
95
+
96
+ def test_initializes_without_system_certs
97
+ store = EasyCodeSign::Verification::TrustStore.new(use_system_certs: false)
98
+
99
+ assert_instance_of OpenSSL::X509::Store, store.store
100
+ end
101
+
102
+ def test_add_certificate
103
+ store = EasyCodeSign::Verification::TrustStore.new(use_system_certs: false)
104
+
105
+ # Create a self-signed certificate
106
+ key = OpenSSL::PKey::RSA.new(2048)
107
+ cert = create_self_signed_cert(key)
108
+
109
+ result = store.add_certificate(cert)
110
+
111
+ assert_same store, result # Returns self for chaining
112
+ end
113
+
114
+ def test_add_file_from_pem
115
+ store = EasyCodeSign::Verification::TrustStore.new(use_system_certs: false)
116
+
117
+ key = OpenSSL::PKey::RSA.new(2048)
118
+ cert = create_self_signed_cert(key)
119
+
120
+ temp_file = Tempfile.new(["cert", ".pem"])
121
+ temp_file.write(cert.to_pem)
122
+ temp_file.close
123
+
124
+ result = store.add_file(temp_file.path)
125
+
126
+ assert_same store, result
127
+ ensure
128
+ temp_file&.unlink
129
+ end
130
+
131
+ def test_verify_returns_hash
132
+ store = EasyCodeSign::Verification::TrustStore.new(use_system_certs: false)
133
+
134
+ key = OpenSSL::PKey::RSA.new(2048)
135
+ cert = create_self_signed_cert(key)
136
+ store.add_certificate(cert)
137
+
138
+ result = store.verify(cert)
139
+
140
+ assert_kind_of Hash, result
141
+ assert_includes result.keys, :trusted
142
+ assert_includes result.keys, :error
143
+ end
144
+
145
+ private
146
+
147
+ def create_self_signed_cert(key)
148
+ cert = OpenSSL::X509::Certificate.new
149
+ cert.version = 2
150
+ cert.serial = 1
151
+ cert.subject = OpenSSL::X509::Name.parse("/CN=Test CA")
152
+ cert.issuer = cert.subject
153
+ cert.public_key = key.public_key
154
+ cert.not_before = Time.now
155
+ cert.not_after = Time.now + 86_400 * 365
156
+ cert.sign(key, OpenSSL::Digest.new("SHA256"))
157
+ cert
158
+ end
159
+ end
160
+
161
+ class CertificateChainTest < Minitest::Test
162
+ def setup
163
+ @trust_store = EasyCodeSign::Verification::TrustStore.new(use_system_certs: false)
164
+ @key = OpenSSL::PKey::RSA.new(2048)
165
+ @cert = create_valid_cert(@key)
166
+ @trust_store.add_certificate(@cert)
167
+ end
168
+
169
+ def test_validate_returns_result_object
170
+ validator = EasyCodeSign::Verification::CertificateChain.new(@trust_store)
171
+
172
+ result = validator.validate(@cert)
173
+
174
+ assert_instance_of EasyCodeSign::Verification::ChainValidationResult, result
175
+ end
176
+
177
+ def test_validates_self_signed_trusted_cert
178
+ validator = EasyCodeSign::Verification::CertificateChain.new(@trust_store)
179
+
180
+ result = validator.validate(@cert)
181
+
182
+ assert result.certificate_valid
183
+ end
184
+
185
+ def test_detects_expired_certificate
186
+ validator = EasyCodeSign::Verification::CertificateChain.new(@trust_store)
187
+
188
+ expired_key = OpenSSL::PKey::RSA.new(2048)
189
+ expired_cert = create_expired_cert(expired_key)
190
+
191
+ result = validator.validate(expired_cert)
192
+
193
+ refute result.certificate_valid
194
+ assert result.expired
195
+ assert_any_match(result.errors, /expired/i)
196
+ end
197
+
198
+ private
199
+
200
+ def create_valid_cert(key)
201
+ cert = OpenSSL::X509::Certificate.new
202
+ cert.version = 2
203
+ cert.serial = 1
204
+ cert.subject = OpenSSL::X509::Name.parse("/CN=Test Cert")
205
+ cert.issuer = cert.subject
206
+ cert.public_key = key.public_key
207
+ cert.not_before = Time.now - 86_400
208
+ cert.not_after = Time.now + 86_400 * 365
209
+ cert.sign(key, OpenSSL::Digest.new("SHA256"))
210
+ cert
211
+ end
212
+
213
+ def create_expired_cert(key)
214
+ cert = OpenSSL::X509::Certificate.new
215
+ cert.version = 2
216
+ cert.serial = 2
217
+ cert.subject = OpenSSL::X509::Name.parse("/CN=Expired Cert")
218
+ cert.issuer = cert.subject
219
+ cert.public_key = key.public_key
220
+ cert.not_before = Time.now - 86_400 * 365
221
+ cert.not_after = Time.now - 86_400 # Expired yesterday
222
+ cert.sign(key, OpenSSL::Digest.new("SHA256"))
223
+ cert
224
+ end
225
+
226
+ def assert_any_match(array, pattern)
227
+ assert array.any? { |item| item.match?(pattern) },
228
+ "Expected at least one item in #{array.inspect} to match #{pattern.inspect}"
229
+ end
230
+ end
231
+
232
+ class SignatureCheckerTest < Minitest::Test
233
+ def test_verify_raw_with_valid_signature
234
+ checker = EasyCodeSign::Verification::SignatureChecker.new
235
+
236
+ key = OpenSSL::PKey::RSA.new(2048)
237
+ cert = create_cert(key)
238
+ content = "test content to sign"
239
+ signature = key.sign(OpenSSL::Digest.new("SHA256"), content)
240
+
241
+ result = checker.verify_raw(signature, content, cert, algorithm: :sha256)
242
+
243
+ assert result.valid?
244
+ assert result.signature_valid
245
+ end
246
+
247
+ def test_verify_raw_with_invalid_signature
248
+ checker = EasyCodeSign::Verification::SignatureChecker.new
249
+
250
+ key = OpenSSL::PKey::RSA.new(2048)
251
+ cert = create_cert(key)
252
+ content = "test content to sign"
253
+ signature = "invalid signature data"
254
+
255
+ result = checker.verify_raw(signature, content, cert, algorithm: :sha256)
256
+
257
+ refute result.valid?
258
+ refute result.signature_valid
259
+ end
260
+
261
+ def test_verify_raw_with_tampered_content
262
+ checker = EasyCodeSign::Verification::SignatureChecker.new
263
+
264
+ key = OpenSSL::PKey::RSA.new(2048)
265
+ cert = create_cert(key)
266
+ content = "original content"
267
+ signature = key.sign(OpenSSL::Digest.new("SHA256"), content)
268
+
269
+ result = checker.verify_raw(signature, "tampered content", cert, algorithm: :sha256)
270
+
271
+ refute result.valid?
272
+ end
273
+
274
+ private
275
+
276
+ def create_cert(key)
277
+ cert = OpenSSL::X509::Certificate.new
278
+ cert.version = 2
279
+ cert.serial = 1
280
+ cert.subject = OpenSSL::X509::Name.parse("/CN=Test")
281
+ cert.issuer = cert.subject
282
+ cert.public_key = key.public_key
283
+ cert.not_before = Time.now
284
+ cert.not_after = Time.now + 86_400
285
+ cert.sign(key, OpenSSL::Digest.new("SHA256"))
286
+ cert
287
+ end
288
+ end
289
+
290
+ class VerifierTest < EasyCodeSignTest
291
+ def test_initializes_with_default_trust_store
292
+ verifier = EasyCodeSign::Verifier.new
293
+
294
+ assert_instance_of EasyCodeSign::Verification::TrustStore, verifier.trust_store
295
+ end
296
+
297
+ def test_initializes_with_custom_trust_store
298
+ custom_store = EasyCodeSign::Verification::TrustStore.new(use_system_certs: false)
299
+ verifier = EasyCodeSign::Verifier.new(trust_store: custom_store)
300
+
301
+ assert_same custom_store, verifier.trust_store
302
+ end
303
+
304
+ def test_verify_unsigned_zip_returns_error
305
+ temp_zip = Tempfile.new(["unsigned", ".zip"])
306
+ Zip::File.open(temp_zip.path, Zip::File::CREATE) do |zip|
307
+ zip.get_output_stream("test.txt") { |f| f.write("test") }
308
+ end
309
+
310
+ verifier = EasyCodeSign::Verifier.new
311
+ result = verifier.verify(temp_zip.path)
312
+
313
+ refute result.valid?
314
+ assert_any_match(result.errors, /not signed/i)
315
+ ensure
316
+ temp_zip&.close
317
+ temp_zip&.unlink
318
+ end
319
+
320
+ def test_verify_unsigned_gem_returns_error
321
+ temp_gem = Tempfile.new(["unsigned", ".gem"])
322
+ create_unsigned_gem(temp_gem.path)
323
+
324
+ verifier = EasyCodeSign::Verifier.new
325
+ result = verifier.verify(temp_gem.path)
326
+
327
+ refute result.valid?
328
+ assert_any_match(result.errors, /not signed/i)
329
+ ensure
330
+ temp_gem&.close
331
+ temp_gem&.unlink
332
+ end
333
+
334
+ private
335
+
336
+ def create_unsigned_gem(path)
337
+ File.open(path, "wb") do |io|
338
+ Gem::Package::TarWriter.new(io) do |tar|
339
+ tar.add_file_simple("data.tar.gz", 0o644, 4) { |f| f.write("data") }
340
+ tar.add_file_simple("metadata.gz", 0o644, 4) { |f| f.write("meta") }
341
+ tar.add_file_simple("checksums.yaml.gz", 0o644, 4) { |f| f.write("sums") }
342
+ end
343
+ end
344
+ end
345
+
346
+ def assert_any_match(array, pattern)
347
+ assert array.any? { |item| item.match?(pattern) },
348
+ "Expected at least one item in #{array.inspect} to match #{pattern.inspect}"
349
+ end
350
+ end
metadata ADDED
@@ -0,0 +1,219 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: easy_code_sign
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - michail
8
+ bindir: exe
9
+ cert_chain: []
10
+ date: 1980-01-02 00:00:00.000000000 Z
11
+ dependencies:
12
+ - !ruby/object:Gem::Dependency
13
+ name: base64
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '0.2'
19
+ type: :runtime
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '0.2'
26
+ - !ruby/object:Gem::Dependency
27
+ name: hexapdf
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '1.0'
33
+ type: :runtime
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1.0'
40
+ - !ruby/object:Gem::Dependency
41
+ name: pkcs11
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '0.3'
47
+ type: :runtime
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '0.3'
54
+ - !ruby/object:Gem::Dependency
55
+ name: rubyzip
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '2.3'
61
+ type: :runtime
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - "~>"
66
+ - !ruby/object:Gem::Version
67
+ version: '2.3'
68
+ - !ruby/object:Gem::Dependency
69
+ name: thor
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '1.3'
75
+ type: :runtime
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.3'
82
+ - !ruby/object:Gem::Dependency
83
+ name: minitest
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '5.0'
89
+ type: :development
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '5.0'
96
+ - !ruby/object:Gem::Dependency
97
+ name: rake
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '13.0'
103
+ type: :development
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '13.0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rubocop
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '1.21'
117
+ type: :development
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '1.21'
124
+ description: A Ruby gem for code signing operations using hardware tokens (HSM/smart
125
+ cards) via PKCS#11. Supports SafeNet eToken, RFC 3161 timestamping, PDF visible
126
+ signatures, and signature verification.
127
+ email:
128
+ - mpantel@aegean.gr
129
+ executables:
130
+ - easysign
131
+ extensions: []
132
+ extra_rdoc_files: []
133
+ files:
134
+ - CHANGELOG.md
135
+ - LICENSE
136
+ - README.md
137
+ - Rakefile
138
+ - exe/easysign
139
+ - lib/easy_code_sign.rb
140
+ - lib/easy_code_sign/cli.rb
141
+ - lib/easy_code_sign/configuration.rb
142
+ - lib/easy_code_sign/deferred_signing_request.rb
143
+ - lib/easy_code_sign/errors.rb
144
+ - lib/easy_code_sign/pdf/appearance_builder.rb
145
+ - lib/easy_code_sign/pdf/timestamp_handler.rb
146
+ - lib/easy_code_sign/providers/base.rb
147
+ - lib/easy_code_sign/providers/pkcs11_base.rb
148
+ - lib/easy_code_sign/providers/safenet.rb
149
+ - lib/easy_code_sign/signable/base.rb
150
+ - lib/easy_code_sign/signable/gem_file.rb
151
+ - lib/easy_code_sign/signable/pdf_file.rb
152
+ - lib/easy_code_sign/signable/zip_file.rb
153
+ - lib/easy_code_sign/signer.rb
154
+ - lib/easy_code_sign/timestamp/client.rb
155
+ - lib/easy_code_sign/timestamp/request.rb
156
+ - lib/easy_code_sign/timestamp/response.rb
157
+ - lib/easy_code_sign/timestamp/verifier.rb
158
+ - lib/easy_code_sign/verification/certificate_chain.rb
159
+ - lib/easy_code_sign/verification/result.rb
160
+ - lib/easy_code_sign/verification/signature_checker.rb
161
+ - lib/easy_code_sign/verification/trust_store.rb
162
+ - lib/easy_code_sign/verifier.rb
163
+ - lib/easy_code_sign/version.rb
164
+ - plugin/.gitignore
165
+ - plugin/Gemfile
166
+ - plugin/Gemfile.lock
167
+ - plugin/README.md
168
+ - plugin/Rakefile
169
+ - plugin/docs/API_REFERENCE.md
170
+ - plugin/docs/DEVELOPMENT.md
171
+ - plugin/docs/INSTALLATION.md
172
+ - plugin/native_host/build/Rakefile
173
+ - plugin/native_host/install/com.easysign.host.json
174
+ - plugin/native_host/install/install_chrome.sh
175
+ - plugin/native_host/install/install_firefox.sh
176
+ - plugin/native_host/src/easy_sign_host.rb
177
+ - plugin/native_host/src/protocol.rb
178
+ - plugin/native_host/src/signing_service.rb
179
+ - plugin/native_host/test/native_host_test.rb
180
+ - plugin/src/easy_sign/background.rb
181
+ - plugin/src/easy_sign/content.rb
182
+ - plugin/src/easy_sign/inject.rb
183
+ - plugin/src/easy_sign/messaging.rb
184
+ - plugin/src/easy_sign/popup.rb
185
+ - plugin/templates/manifest.json
186
+ - plugin/templates/popup.css
187
+ - plugin/templates/popup.html
188
+ - sig/easy_code_sign.rbs
189
+ - test/easy_code_sign_test.rb
190
+ - test/pdf_signable_test.rb
191
+ - test/signable_test.rb
192
+ - test/test_helper.rb
193
+ - test/timestamp_test.rb
194
+ - test/verification_test.rb
195
+ homepage: https://github.com/mpantel/easy_code_sign
196
+ licenses:
197
+ - MIT
198
+ metadata:
199
+ homepage_uri: https://github.com/mpantel/easy_code_sign
200
+ source_code_uri: https://github.com/mpantel/easy_code_sign
201
+ changelog_uri: https://github.com/mpantel/easy_code_sign/blob/main/CHANGELOG.md
202
+ rdoc_options: []
203
+ require_paths:
204
+ - lib
205
+ required_ruby_version: !ruby/object:Gem::Requirement
206
+ requirements:
207
+ - - ">="
208
+ - !ruby/object:Gem::Version
209
+ version: 3.2.0
210
+ required_rubygems_version: !ruby/object:Gem::Requirement
211
+ requirements:
212
+ - - ">="
213
+ - !ruby/object:Gem::Version
214
+ version: '0'
215
+ requirements: []
216
+ rubygems_version: 4.0.3
217
+ specification_version: 4
218
+ summary: Sign and verify Ruby gems, ZIP files, and PDFs using hardware security tokens
219
+ test_files: []