win32-certstore 0.3.0 → 0.6.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7498d33d838e240261d6629228c9e5f4135cbc8cfef53dd6eb2c25fd15cfa04f
4
- data.tar.gz: 7ebbfe860ed3109d18bf6cedb18040fec935a82985348317a9513e6803b80f1e
3
+ metadata.gz: e832ae077e8be7cd039393f84b74062e58dd331b1317cdcc2a1bb1f13109f176
4
+ data.tar.gz: 453bd4ad7e2d6a92d3935b0a4df4f241636b657256a39f1ac35bc81d2d34030b
5
5
  SHA512:
6
- metadata.gz: 6bcf63bbce574b4c92224c1228b7abd68a9e15bd527ffaafd3750f14bb106a499d03eabef6fd134ee603fa790230c12161f0a64ed7e6a072a3f4135da1cfe8db
7
- data.tar.gz: e58963b69cc9e20d7b31316e2a1cc2b00484489ea85a8796115555bc2dd40875f55a2327bcddd067c8c8e985096228b2835f3709233aa04a23174027dc8015e7
6
+ metadata.gz: a3254affc58f8eb862a585b78cc5c5451c61db3398ef1de59ffcb6580755f5e24338c2a1caf16e89e46db4e8ee7c9f431a1c4372768cb7ff08bd76265d1b53da
7
+ data.tar.gz: bab7b27e4c0c6d780556a6410836283f6de31c64d559fb1b331b679c3d671b68673b6313f53560916e0a5c89f83fff658fd3335f965cfa3024b5066860393b3b
@@ -31,18 +31,21 @@ module Win32
31
31
 
32
32
  attr_accessor :store_name
33
33
 
34
- def initialize(store_name)
34
+ # Initializes a new instance of a certificate store.
35
+ # takes 2 parameters - the store name (My, Root, etc) and the location (CurrentUser or LocalMachine), it defaults to LocalMachine for backwards compatibility
36
+ def initialize(store_name, store_location: CERT_SYSTEM_STORE_LOCAL_MACHINE)
35
37
  @store_name = store_name
36
- @certstore_handler = open(store_name)
38
+ @store_location = store_location
39
+ @certstore_handler = open(store_name, store_location: store_location)
37
40
  end
38
41
 
39
42
  # To open given certificate store
40
- def self.open(store_name)
43
+ def self.open(store_name, store_location: CERT_SYSTEM_STORE_LOCAL_MACHINE)
41
44
  validate_store(store_name)
42
45
  if block_given?
43
- yield new(store_name)
46
+ yield new(store_name, store_location: store_location)
44
47
  else
45
- new(store_name)
48
+ new(store_name, store_location: store_location)
46
49
  end
47
50
  end
48
51
 
@@ -60,18 +63,19 @@ module Win32
60
63
  #
61
64
  # @param path [String] Path of the certificate that should be imported
62
65
  # @param password [String] Password of the certificate if it is protected
66
+ # @param key_properties [Integer] dwFlags used to specify properties of the pfx key, see certstore/store_base.rb cert_add_pfx function
63
67
  #
64
68
  # @return [Boolean]
65
69
  #
66
- def add_pfx(path, password)
67
- cert_add_pfx(certstore_handler, path, password)
70
+ def add_pfx(path, password, key_properties = 0)
71
+ cert_add_pfx(certstore_handler, path, password, key_properties)
68
72
  end
69
73
 
70
74
  # Return `OpenSSL::X509` certificate object
71
75
  # @param request [thumbprint<string>] of certificate
72
76
  # @return [Object] of certificates in OpenSSL::X509 format
73
- def get(certificate_thumbprint)
74
- cert_get(certificate_thumbprint)
77
+ def get(certificate_thumbprint, store_name: @store_name, store_location: @store_location)
78
+ cert_get(certificate_thumbprint, store_name: store_name, store_location: store_location)
75
79
  end
76
80
 
77
81
  # Returns all the certificates in a store
@@ -98,8 +102,8 @@ module Win32
98
102
  # Validates a certificate in a certificate store on the basis of time validity
99
103
  # @param request[thumbprint<string>] of certificate
100
104
  # @return [true, false] only true or false
101
- def valid?(certificate_thumbprint)
102
- cert_validate(certificate_thumbprint)
105
+ def valid?(certificate_thumbprint, store_location: "", store_name: "")
106
+ cert_validate(certificate_thumbprint, store_location: store_location, store_name: store_name)
103
107
  end
104
108
 
105
109
  # To close and destroy pointer of open certificate store handler
@@ -117,8 +121,9 @@ module Win32
117
121
  attr_reader :certstore_handler
118
122
 
119
123
  # To open certstore and return open certificate store pointer
120
- def open(store_name)
121
- certstore_handler = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, nil, CERT_SYSTEM_STORE_LOCAL_MACHINE, wstring(store_name))
124
+
125
+ def open(store_name, store_location: CERT_SYSTEM_STORE_LOCAL_MACHINE)
126
+ certstore_handler = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, nil, store_location, wstring(store_name))
122
127
  unless certstore_handler
123
128
  last_error = FFI::LastError.error
124
129
  raise SystemCallError.new("Unable to open the Certificate Store `#{store_name}`.", last_error)
@@ -14,7 +14,7 @@
14
14
  # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
- require "openssl"
17
+ require "openssl" unless defined?(OpenSSL)
18
18
 
19
19
  module Win32
20
20
  class Certstore
@@ -16,7 +16,7 @@
16
16
  # limitations under the License.
17
17
  #
18
18
 
19
- require "ffi"
19
+ require "ffi" unless defined?(FFI)
20
20
 
21
21
  module Win32
22
22
  class Certstore
@@ -88,6 +88,9 @@ module Win32
88
88
 
89
89
  CERT_STORE_PROV_SYSTEM = 10
90
90
  CERT_SYSTEM_STORE_LOCAL_MACHINE = 0x00020000
91
+ CERT_SYSTEM_STORE_CURRENT_USER = 0x00010000
92
+ CERT_SYSTEM_STORE_SERVICES = 0x00050000
93
+ CERT_SYSTEM_STORE_USERS = 0x00060000
91
94
 
92
95
  # Define ffi pointer
93
96
  HCERTSTORE = FFI::TypeDefs[:pointer]
@@ -113,17 +116,17 @@ module Win32
113
116
 
114
117
  class FILETIME < FFI::Struct
115
118
  layout :dwLowDateTime, DWORD,
116
- :dwHighDateTime, DWORD
119
+ :dwHighDateTime, DWORD
117
120
  end
118
121
 
119
122
  class CRYPT_INTEGER_BLOB < FFI::Struct
120
123
  layout :cbData, DWORD, # Count, in bytes, of data
121
- :pbData, :pointer # Pointer to data buffer
124
+ :pbData, :pointer # Pointer to data buffer
122
125
  end
123
126
 
124
127
  class CRYPT_NAME_BLOB < FFI::Struct
125
128
  layout :cbData, DWORD, # Count, in bytes, of data
126
- :pbData, :pointer # Pointer to data buffer
129
+ :pbData, :pointer # Pointer to data buffer
127
130
  def initialize(str = nil)
128
131
  super(nil)
129
132
  if str
@@ -134,7 +137,7 @@ module Win32
134
137
 
135
138
  class CRYPT_HASH_BLOB < FFI::Struct
136
139
  layout :cbData, DWORD, # Count, in bytes, of data
137
- :pbData, :pointer # Pointer to data buffer
140
+ :pbData, :pointer # Pointer to data buffer
138
141
 
139
142
  def initialize(str = nil)
140
143
  super(nil)
@@ -151,7 +154,7 @@ module Win32
151
154
 
152
155
  class CRYPT_DATA_BLOB < FFI::Struct
153
156
  layout :cbData, DWORD, # Count, in bytes, of data
154
- :pbData, :pointer # Pointer to data buffer
157
+ :pbData, :pointer # Pointer to data buffer
155
158
 
156
159
  def initialize(str = nil)
157
160
  super(nil)
@@ -164,47 +167,47 @@ module Win32
164
167
 
165
168
  class CERT_EXTENSION < FFI::Struct
166
169
  layout :pszObjId, LPTSTR,
167
- :fCritical, BOOL,
168
- :Value, CRYPT_INTEGER_BLOB
170
+ :fCritical, BOOL,
171
+ :Value, CRYPT_INTEGER_BLOB
169
172
  end
170
173
 
171
174
  class CRYPT_BIT_BLOB < FFI::Struct
172
175
  layout :cbData, DWORD,
173
- :pbData, BYTE,
174
- :cUnusedBits, DWORD
176
+ :pbData, BYTE,
177
+ :cUnusedBits, DWORD
175
178
  end
176
179
 
177
180
  class CRYPT_ALGORITHM_IDENTIFIER < FFI::Struct
178
181
  layout :pszObjId, LPSTR,
179
- :Parameters, CRYPT_INTEGER_BLOB
182
+ :Parameters, CRYPT_INTEGER_BLOB
180
183
  end
181
184
 
182
185
  class CERT_PUBLIC_KEY_INFO < FFI::Struct
183
186
  layout :Algorithm, CRYPT_ALGORITHM_IDENTIFIER,
184
- :PublicKey, CRYPT_BIT_BLOB
187
+ :PublicKey, CRYPT_BIT_BLOB
185
188
  end
186
189
 
187
190
  class CERT_INFO < FFI::Struct
188
191
  layout :dwVersion, DWORD,
189
- :SerialNumber, CRYPT_INTEGER_BLOB,
190
- :SignatureAlgorithm, CRYPT_ALGORITHM_IDENTIFIER,
191
- :Issuer, CRYPT_NAME_BLOB,
192
- :NotBefore, FILETIME,
193
- :NotAfter, FILETIME,
194
- :Subject, CRYPT_NAME_BLOB,
195
- :SubjectPublicKeyInfo, CERT_PUBLIC_KEY_INFO,
196
- :IssuerUniqueId, CRYPT_BIT_BLOB,
197
- :SubjectUniqueId, CRYPT_BIT_BLOB,
198
- :cExtension, DWORD,
199
- :rgExtension, CERT_EXTENSION
192
+ :SerialNumber, CRYPT_INTEGER_BLOB,
193
+ :SignatureAlgorithm, CRYPT_ALGORITHM_IDENTIFIER,
194
+ :Issuer, CRYPT_NAME_BLOB,
195
+ :NotBefore, FILETIME,
196
+ :NotAfter, FILETIME,
197
+ :Subject, CRYPT_NAME_BLOB,
198
+ :SubjectPublicKeyInfo, CERT_PUBLIC_KEY_INFO,
199
+ :IssuerUniqueId, CRYPT_BIT_BLOB,
200
+ :SubjectUniqueId, CRYPT_BIT_BLOB,
201
+ :cExtension, DWORD,
202
+ :rgExtension, CERT_EXTENSION
200
203
  end
201
204
 
202
205
  class CERT_CONTEXT < FFI::Struct
203
206
  layout :dwCertEncodingType, DWORD,
204
- :pbCertEncoded, BYTE,
205
- :cbCertEncoded, DWORD,
206
- :pCertInfo, CERT_INFO,
207
- :hCertStore, HCERTSTORE
207
+ :pbCertEncoded, BYTE,
208
+ :cbCertEncoded, DWORD,
209
+ :pCertInfo, CERT_INFO,
210
+ :hCertStore, HCERTSTORE
208
211
  end
209
212
 
210
213
  ###############################################################################
@@ -21,19 +21,18 @@ module Win32
21
21
  class Certstore
22
22
  module Mixin
23
23
  module Helper
24
-
25
- # PSCommand to search certificate from thumbprint and convert in pem
26
- def cert_ps_cmd(thumbprint, store_name)
24
+ def cert_ps_cmd(thumbprint, store_location: "LocalMachine", store_name: "My")
27
25
  <<-EOH
26
+ $cert = Get-ChildItem Cert:\\#{store_location}\\#{store_name} -Recurse | Where { $_.Thumbprint -eq "#{thumbprint}" }
27
+
28
28
  $content = $null
29
- $cert = Get-ChildItem Cert:\\LocalMachine\\'#{store_name}' -Recurse | Where { $_.Thumbprint -eq '#{thumbprint}' }
30
- if($cert -ne $null)
29
+ if($null -ne $cert)
31
30
  {
32
- $content = @(
33
- '-----BEGIN CERTIFICATE-----'
34
- [System.Convert]::ToBase64String($cert.RawData, 'InsertLineBreaks')
35
- '-----END CERTIFICATE-----'
36
- )
31
+ $content = @(
32
+ '-----BEGIN CERTIFICATE-----'
33
+ [System.Convert]::ToBase64String($cert.RawData, 'InsertLineBreaks')
34
+ '-----END CERTIFICATE-----'
35
+ )
37
36
  }
38
37
  $content
39
38
  EOH
@@ -43,7 +42,6 @@ module Win32
43
42
  def valid_duration?(cert_obj)
44
43
  cert_obj.not_before < Time.now.utc && cert_obj.not_after > Time.now.utc
45
44
  end
46
-
47
45
  end
48
46
  end
49
47
  end
@@ -15,12 +15,12 @@
15
15
  # See the License for the specific language governing permissions and
16
16
  # limitations under the License.
17
17
 
18
- require "mixlib/shellout"
18
+ require "mixlib/shellout" unless defined?(Mixlib::ShellOut)
19
19
 
20
20
  module Win32
21
21
  class Certstore
22
22
  module Mixin
23
- module ShellOut
23
+ module ShellExec
24
24
  def shell_out_command(*command_args)
25
25
  cmd = Mixlib::ShellOut.new(*command_args)
26
26
  cmd.live_stream
@@ -28,6 +28,7 @@ module Win32
28
28
  if cmd.error!
29
29
  raise Mixlib::ShellOut::ShellCommandFailed, cmd.error!
30
30
  end
31
+
31
32
  cmd
32
33
  end
33
34
 
@@ -38,7 +39,7 @@ module Win32
38
39
  # @param script [String] script to run
39
40
  # @param options [Hash] options hash
40
41
  # @return [Mixlib::Shellout] mixlib-shellout object
41
- def powershell_out(*command_args)
42
+ def powershell_exec(*command_args)
42
43
  script = command_args.first
43
44
  options = command_args.last.is_a?(Hash) ? command_args.last : nil
44
45
 
@@ -51,8 +52,8 @@ module Win32
51
52
  # @param script [String] script to run
52
53
  # @param options [Hash] options hash
53
54
  # @return [Mixlib::Shellout] mixlib-shellout object
54
- def powershell_out!(*command_args)
55
- cmd = powershell_out(*command_args)
55
+ def powershell_exec!(*command_args)
56
+ cmd = powershell_exec(*command_args)
56
57
  cmd.error!
57
58
  cmd
58
59
  end
@@ -96,7 +97,7 @@ module Win32
96
97
  "-InputFormat None",
97
98
  ]
98
99
 
99
- "powershell.exe #{flags.join(' ')} -Command \"#{script.gsub('"', '\"')}\""
100
+ "powershell.exe #{flags.join(" ")} -Command \"#{script.gsub('"', '\"')}\""
100
101
  end
101
102
  end
102
103
  end
@@ -36,14 +36,12 @@ module Win32
36
36
  ustring += "\000\000" if ustring.length == 0 || ustring[-1].chr != "\000"
37
37
 
38
38
  # encode it all as UTF-16LE AKA Windows Wide Character AKA Windows Unicode
39
- ustring = begin
40
- if ustring.respond_to?(:encode)
41
- ustring.encode("UTF-16LE")
42
- else
43
- require "iconv"
44
- Iconv.conv("UTF-16LE", "UTF-8", ustring)
45
- end
46
- end
39
+ ustring = if ustring.respond_to?(:encode)
40
+ ustring.encode("UTF-16LE")
41
+ else
42
+ require "iconv"
43
+ Iconv.conv("UTF-16LE", "UTF-8", ustring)
44
+ end
47
45
  ustring
48
46
  end
49
47
 
@@ -53,14 +51,12 @@ module Win32
53
51
  wstring = wstring.force_encoding("UTF-16LE") if wstring.respond_to?(:force_encoding)
54
52
 
55
53
  # encode it all as UTF-8
56
- wstring = begin
57
- if wstring.respond_to?(:encode)
58
- wstring.encode("UTF-8")
59
- else
60
- require "iconv"
61
- Iconv.conv("UTF-8", "UTF-16LE", wstring)
62
- end
63
- end
54
+ wstring = if wstring.respond_to?(:encode)
55
+ wstring.encode("UTF-8")
56
+ else
57
+ require "iconv"
58
+ Iconv.conv("UTF-8", "UTF-16LE", wstring)
59
+ end
64
60
  # remove trailing CRLF and NULL characters
65
61
  wstring.strip!
66
62
  wstring
@@ -17,10 +17,10 @@
17
17
 
18
18
  require_relative "mixin/crypto"
19
19
  require_relative "mixin/string"
20
- require_relative "mixin/shell_out"
20
+ require_relative "mixin/shell_exec"
21
21
  require_relative "mixin/unicode"
22
- require "openssl"
23
- require "json"
22
+ require "openssl" unless defined?(OpenSSL)
23
+ require "json" unless defined?(JSON)
24
24
 
25
25
  module Win32
26
26
  class Certstore
@@ -28,7 +28,7 @@ module Win32
28
28
  include Win32::Certstore::Mixin::Crypto
29
29
  include Win32::Certstore::Mixin::Assertions
30
30
  include Win32::Certstore::Mixin::String
31
- include Win32::Certstore::Mixin::ShellOut
31
+ include Win32::Certstore::Mixin::ShellExec
32
32
  include Win32::Certstore::Mixin::Unicode
33
33
  include Win32::Certstore::Mixin::Helper
34
34
 
@@ -57,16 +57,18 @@ module Win32
57
57
  # @param certstore_handler [FFI::Pointer] Handle of the store where certificate should be imported
58
58
  # @param path [String] Path of the certificate that should be imported
59
59
  # @param password [String] Password of the certificate
60
+ # @param key_properties [Integer] dwFlags used to specify properties of the pfx key, see link above
60
61
  #
61
62
  # @return [Boolean]
62
63
  #
63
64
  # @raise [SystemCallError] when Crypt API would not be able to perform some action
64
65
  #
65
- def cert_add_pfx(certstore_handler, path, password = "")
66
+ def cert_add_pfx(certstore_handler, path, password = "", key_properties = 0)
66
67
  cert_added = false
67
68
  # Imports a PFX BLOB and returns the handle of a store
68
- pfx_cert_store = PFXImportCertStore(CRYPT_DATA_BLOB.new(File.binread(path)), wstring(password), 0)
69
+ pfx_cert_store = PFXImportCertStore(CRYPT_DATA_BLOB.new(File.binread(path)), wstring(password), key_properties)
69
70
  raise if pfx_cert_store.null?
71
+
70
72
  # Find all the certificate contexts in certificate store and add them ino the store
71
73
  while (cert_context = CertEnumCertificatesInStore(pfx_cert_store, cert_context)) && (not cert_context.null?)
72
74
  # Add certificate context to the certificate store
@@ -85,11 +87,15 @@ module Win32
85
87
 
86
88
  # Get certificate from open certificate store and return certificate object
87
89
  # certificate_thumbprint => thumbprint is a hash. which could be sha1 or md5.
88
- def cert_get(certificate_thumbprint)
90
+ def cert_get(certificate_thumbprint, store_name:, store_location:)
89
91
  validate_thumbprint(certificate_thumbprint)
90
92
  thumbprint = update_thumbprint(certificate_thumbprint)
91
- cert_pem = get_cert_pem(thumbprint)
93
+ cert_pem = get_cert_pem(thumbprint, store_name: store_name, store_location: store_location)
92
94
  cert_pem = format_pem(cert_pem)
95
+ if cert_pem.empty?
96
+ raise ArgumentError, "Unable to retrieve the certificate"
97
+ end
98
+
93
99
  unless cert_pem.empty?
94
100
  build_openssl_obj(cert_pem)
95
101
  end
@@ -123,7 +129,7 @@ module Win32
123
129
  begin
124
130
  cert_args = cert_find_args(store_handler, thumbprint)
125
131
  pcert_context = CertFindCertificateInStore(*cert_args)
126
- if !pcert_context.null?
132
+ unless pcert_context.null?
127
133
  cert_delete_flag = CertDeleteCertificateFromStore(CertDuplicateCertificateContext(pcert_context)) || lookup_error
128
134
  end
129
135
  CertFreeCertificateContext(pcert_context)
@@ -136,10 +142,10 @@ module Win32
136
142
  # Verify certificate from open certificate store and return boolean or exceptions
137
143
  # store_handler => Open certificate store handler
138
144
  # certificate_thumbprint => thumbprint is a hash. which could be sha1 or md5.
139
- def cert_validate(certificate_thumbprint)
145
+ def cert_validate(certificate_thumbprint, store_location:, store_name:)
140
146
  validate_thumbprint(certificate_thumbprint)
141
147
  thumbprint = update_thumbprint(certificate_thumbprint)
142
- cert_pem = get_cert_pem(thumbprint)
148
+ cert_pem = get_cert_pem(thumbprint, store_name: store_name, store_location: store_location)
143
149
  cert_pem = format_pem(cert_pem)
144
150
  verify_certificate(cert_pem)
145
151
  end
@@ -149,6 +155,7 @@ module Win32
149
155
  # search_token => CN, RDN or any certificate attribute
150
156
  def cert_search(store_handler, search_token)
151
157
  raise ArgumentError, "Invalid search token" if !search_token || search_token.strip.empty?
158
+
152
159
  certificate_list = []
153
160
  begin
154
161
  while (pcert_context = CertEnumCertificatesInStore(store_handler, pcert_context)) && !pcert_context.null?
@@ -217,6 +224,7 @@ module Win32
217
224
  # Verify OpenSSL::X509::Certificate object
218
225
  def verify_certificate(cert_pem)
219
226
  return "Certificate not found" if cert_pem.empty?
227
+
220
228
  valid_duration?(build_openssl_obj(cert_pem))
221
229
  end
222
230
 
@@ -226,8 +234,13 @@ module Win32
226
234
  end
227
235
 
228
236
  # Get certificate pem
229
- def get_cert_pem(thumbprint)
230
- get_data = powershell_out!(cert_ps_cmd(thumbprint, store_name))
237
+ def get_cert_pem(thumbprint, store_name:, store_location:)
238
+ converted_store = if store_location == CERT_SYSTEM_STORE_LOCAL_MACHINE
239
+ "LocalMachine"
240
+ else
241
+ "CurrentUser"
242
+ end
243
+ get_data = powershell_exec!(cert_ps_cmd(thumbprint, store_location: converted_store, store_name: store_name))
231
244
  get_data.stdout
232
245
  end
233
246
 
@@ -1,6 +1,6 @@
1
1
  module Win32
2
2
  class Certstore
3
- VERSION = "0.3.0".freeze
3
+ VERSION = "0.6.2".freeze
4
4
  MAJOR, MINOR, TINY = VERSION.split(".")
5
5
  end
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: win32-certstore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.6.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chef Software
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-11 00:00:00.000000000 Z
11
+ date: 2021-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -79,7 +79,7 @@ files:
79
79
  - lib/win32/certstore/mixin/assertions.rb
80
80
  - lib/win32/certstore/mixin/crypto.rb
81
81
  - lib/win32/certstore/mixin/helper.rb
82
- - lib/win32/certstore/mixin/shell_out.rb
82
+ - lib/win32/certstore/mixin/shell_exec.rb
83
83
  - lib/win32/certstore/mixin/string.rb
84
84
  - lib/win32/certstore/mixin/unicode.rb
85
85
  - lib/win32/certstore/store_base.rb
@@ -97,16 +97,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
97
97
  requirements:
98
98
  - - ">="
99
99
  - !ruby/object:Gem::Version
100
- version: '2.3'
100
+ version: '2.5'
101
101
  required_rubygems_version: !ruby/object:Gem::Requirement
102
102
  requirements:
103
103
  - - ">="
104
104
  - !ruby/object:Gem::Version
105
105
  version: '0'
106
106
  requirements: []
107
- rubyforge_project:
108
- rubygems_version: 2.7.6
107
+ rubygems_version: 3.1.4
109
108
  signing_key:
110
109
  specification_version: 4
111
- summary: Ruby library for accessing the certificate store on Windows.
110
+ summary: Ruby library for accessing the certificate stores on Windows.
112
111
  test_files: []