net-ssh 4.0.1 → 4.1.0.beta1

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
  SHA1:
3
- metadata.gz: 1b8b826d8c871af72b032997bce4a0c712535416
4
- data.tar.gz: 9f595442bcd2630e658d90e03806c431e74b290d
3
+ metadata.gz: 3ddb17acb82519ed776b8253f91d7ce18fefdf51
4
+ data.tar.gz: 15b3ed1a09ac2284404592c7aa75258960acd0db
5
5
  SHA512:
6
- metadata.gz: 6e580fe96e26173fed37ddf9b7900ef93d3865a8331c42c5f5cd195cb2fc81302a6552caa5fd11fccdd5e6d2941f3ba711b26061e51b25b2ddf298cf2e23079b
7
- data.tar.gz: cc669fc72133df8552cdb6820ed0eebe5fc9d59c1c8874c2fb9bc3604e64760cc1734c6e6076e8232de66c74ce54d63a3f1e421ab6bef754fc47a457a4cb3521
6
+ metadata.gz: 929f76416e948641680d7355c1e86d8614799b6ed874de172111a1d66d0dcfe2b5ef715e4d4bf10c2bc3d8268e5ffcbd9b487544e00c802d3c5069549789cb48
7
+ data.tar.gz: 8fefcbc82dc35a448abe499a5656245c1d7c3959abea95e1629bbbe390bb7f73cd53bd3b0c96cc18e6d03f831c370ad0d4a1af9cc699e48f564621e5e52b3d07
Binary file
data.tar.gz.sig CHANGED
Binary file
@@ -1,3 +1,8 @@
1
+ === 4.1.0.beta1
2
+
3
+ * Fix nil error when libsodium is not there [chapmajs ,#488]
4
+ * SSH certificate support for client auth [David Bartley, #485]
5
+
1
6
  === 4.0.1
2
7
  === 4.0.1.rc2
3
8
 
@@ -29,20 +29,28 @@ module Net; module SSH; module Authentication
29
29
  attr_accessor :comment
30
30
  end
31
31
 
32
- SSH2_AGENT_REQUEST_VERSION = 1
33
- SSH2_AGENT_REQUEST_IDENTITIES = 11
34
- SSH2_AGENT_IDENTITIES_ANSWER = 12
35
- SSH2_AGENT_SIGN_REQUEST = 13
36
- SSH2_AGENT_SIGN_RESPONSE = 14
37
- SSH2_AGENT_FAILURE = 30
38
- SSH2_AGENT_VERSION_RESPONSE = 103
32
+ SSH2_AGENT_REQUEST_VERSION = 1
33
+ SSH2_AGENT_REQUEST_IDENTITIES = 11
34
+ SSH2_AGENT_IDENTITIES_ANSWER = 12
35
+ SSH2_AGENT_SIGN_REQUEST = 13
36
+ SSH2_AGENT_SIGN_RESPONSE = 14
37
+ SSH2_AGENT_ADD_IDENTITY = 17
38
+ SSH2_AGENT_REMOVE_IDENTITY = 18
39
+ SSH2_AGENT_REMOVE_ALL_IDENTITIES = 19
40
+ SSH2_AGENT_ADD_ID_CONSTRAINED = 25
41
+ SSH2_AGENT_FAILURE = 30
42
+ SSH2_AGENT_VERSION_RESPONSE = 103
39
43
 
40
- SSH_COM_AGENT2_FAILURE = 102
44
+ SSH_COM_AGENT2_FAILURE = 102
41
45
 
42
46
  SSH_AGENT_REQUEST_RSA_IDENTITIES = 1
43
47
  SSH_AGENT_RSA_IDENTITIES_ANSWER1 = 2
44
48
  SSH_AGENT_RSA_IDENTITIES_ANSWER2 = 5
45
49
  SSH_AGENT_FAILURE = 5
50
+ SSH_AGENT_SUCCESS = 6
51
+
52
+ SSH_AGENT_CONSTRAIN_LIFETIME = 1
53
+ SSH_AGENT_CONSTRAIN_CONFIRM = 2
46
54
 
47
55
  # The underlying socket being used to communicate with the SSH agent.
48
56
  attr_reader :socket
@@ -139,6 +147,37 @@ module Net; module SSH; module Authentication
139
147
  return reply.read_string
140
148
  end
141
149
 
150
+ # Adds the private key with comment to the agent.
151
+ # If lifetime is given, the key will automatically be removed after lifetime
152
+ # seconds.
153
+ # If confirm is true, confirmation will be required for each agent signing
154
+ # operation.
155
+ def add_identity(priv_key, comment, lifetime: nil, confirm: false)
156
+ constraints = Buffer.new
157
+ if lifetime
158
+ constraints.write_byte(SSH_AGENT_CONSTRAIN_LIFETIME)
159
+ constraints.write_long(lifetime)
160
+ end
161
+ constraints.write_byte(SSH_AGENT_CONSTRAIN_CONFIRM) if confirm
162
+
163
+ req_type = constraints.empty? ? SSH2_AGENT_ADD_IDENTITY : SSH2_AGENT_ADD_ID_CONSTRAINED
164
+ type, = send_and_wait(req_type, :string, priv_key.ssh_type, :raw, blob_for_add(priv_key),
165
+ :string, comment, :raw, constraints)
166
+ raise AgentError, "could not add identity to agent" if type != SSH_AGENT_SUCCESS
167
+ end
168
+
169
+ # Removes key from the agent.
170
+ def remove_identity(key)
171
+ type, = send_and_wait(SSH2_AGENT_REMOVE_IDENTITY, :string, key.to_blob)
172
+ raise AgentError, "could not remove identity from agent" if type != SSH_AGENT_SUCCESS
173
+ end
174
+
175
+ # Removes all identities from the agent.
176
+ def remove_all_identities
177
+ type, = send_and_wait(SSH2_AGENT_REMOVE_ALL_IDENTITIES)
178
+ raise AgentError, "could not remove all identity from agent" if type != SSH_AGENT_SUCCESS
179
+ end
180
+
142
181
  private
143
182
 
144
183
  def unix_socket_class
@@ -178,6 +217,40 @@ module Net; module SSH; module Authentication
178
217
  type == SSH2_AGENT_FAILURE ||
179
218
  type == SSH_COM_AGENT2_FAILURE
180
219
  end
220
+
221
+ def blob_for_add(priv_key)
222
+ # Ideally we'd have something like `to_private_blob` on the various key types, but the
223
+ # nuances with encoding (e.g. `n` and `e` are reversed for RSA keys) make this impractical.
224
+ case priv_key.ssh_type
225
+ when /^ssh-dss$/
226
+ Net::SSH::Buffer.from(:bignum, priv_key.p, :bignum, priv_key.q, :bignum, priv_key.g,
227
+ :bignum, priv_key.pub_key, :bignum, priv_key.priv_key).to_s
228
+ when /^ssh-dss-cert-v01@openssh\.com$/
229
+ Net::SSH::Buffer.from(:string, priv_key.to_blob, :bignum, priv_key.key.priv_key).to_s
230
+ when /^ecdsa\-sha2\-(\w*)$/
231
+ curve_name = OpenSSL::PKey::EC::CurveNameAliasInv[priv_key.group.curve_name]
232
+ Net::SSH::Buffer.from(:string, curve_name, :mstring, priv_key.public_key.to_bn.to_s(2),
233
+ :bignum, priv_key.private_key).to_s
234
+ when /^ecdsa\-sha2\-(\w*)-cert-v01@openssh\.com$/
235
+ Net::SSH::Buffer.from(:string, priv_key.to_blob, :bignum, priv_key.key.private_key).to_s
236
+ when /^ssh-ed25519$/
237
+ Net::SSH::Buffer.from(:string, priv_key.public_key.verify_key.to_bytes,
238
+ :string, priv_key.sign_key.keypair_bytes).to_s
239
+ when /^ssh-ed25519-cert-v01@openssh\.com$/
240
+ # Unlike the other certificate types, the public key is included after the certifiate.
241
+ Net::SSH::Buffer.from(:string, priv_key.to_blob,
242
+ :string, priv_key.key.public_key.verify_key.to_bytes,
243
+ :string, priv_key.key.sign_key.keypair_bytes).to_s
244
+ when /^ssh-rsa$/
245
+ # `n` and `e` are reversed compared to the ordering in `OpenSSL::PKey::RSA#to_blob`.
246
+ Net::SSH::Buffer.from(:bignum, priv_key.n, :bignum, priv_key.e, :bignum, priv_key.d,
247
+ :bignum, priv_key.iqmp, :bignum, priv_key.p, :bignum, priv_key.q).to_s
248
+ when /^ssh-rsa-cert-v01@openssh\.com$/
249
+ Net::SSH::Buffer.from(:string, priv_key.to_blob, :bignum, priv_key.key.d,
250
+ :bignum, priv_key.key.iqmp, :bignum, priv_key.key.p,
251
+ :bignum, priv_key.key.q).to_s
252
+ end
253
+ end
181
254
  end
182
255
 
183
256
  end; end; end
@@ -0,0 +1,169 @@
1
+ require 'securerandom'
2
+
3
+ module Net; module SSH; module Authentication
4
+ # Class for representing an SSH certificate.
5
+ #
6
+ # http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/ssh/PROTOCOL.certkeys?rev=1.10&content-type=text/plain
7
+ class Certificate
8
+ attr_accessor :nonce
9
+ attr_accessor :key
10
+ attr_accessor :serial
11
+ attr_accessor :type
12
+ attr_accessor :key_id
13
+ attr_accessor :valid_principals
14
+ attr_accessor :valid_after
15
+ attr_accessor :valid_before
16
+ attr_accessor :critical_options
17
+ attr_accessor :extensions
18
+ attr_accessor :reserved
19
+ attr_accessor :signature_key
20
+ attr_accessor :signature
21
+
22
+ # Read a certificate blob associated with a key of the given type.
23
+ def self.read_certblob(buffer, type)
24
+ cert = Certificate.new
25
+ cert.nonce = buffer.read_string
26
+ cert.key = buffer.read_keyblob(type)
27
+ cert.serial = buffer.read_int64
28
+ cert.type = type_symbol(buffer.read_long)
29
+ cert.key_id = buffer.read_string
30
+ cert.valid_principals = buffer.read_buffer.read_all(&:read_string)
31
+ cert.valid_after = Time.at(buffer.read_int64)
32
+ cert.valid_before = Time.at(buffer.read_int64)
33
+ cert.critical_options = read_options(buffer)
34
+ cert.extensions = read_options(buffer)
35
+ cert.reserved = buffer.read_string
36
+ cert.signature_key = buffer.read_buffer.read_key
37
+ cert.signature = buffer.read_string
38
+ cert
39
+ end
40
+
41
+ def ssh_type
42
+ key.ssh_type + "-cert-v01@openssh.com"
43
+ end
44
+
45
+ def ssh_signature_type
46
+ key.ssh_type
47
+ end
48
+
49
+ # Serializes the certificate (and key).
50
+ def to_blob
51
+ Buffer.from(
52
+ :raw, to_blob_without_signature,
53
+ :string, signature
54
+ ).to_s
55
+ end
56
+
57
+ def ssh_do_sign(data)
58
+ key.ssh_do_sign(data)
59
+ end
60
+
61
+ def ssh_do_verify(sig, data)
62
+ key.ssh_do_verify(sig, data)
63
+ end
64
+
65
+ def to_pem
66
+ key.to_pem
67
+ end
68
+
69
+ def fingerprint
70
+ key.fingerprint
71
+ end
72
+
73
+ # Signs the certificate with key.
74
+ def sign!(key, sign_nonce=nil)
75
+ # ssh-keygen uses 32 bytes of nonce.
76
+ self.nonce = sign_nonce || SecureRandom.random_bytes(32)
77
+ self.signature_key = key
78
+ self.signature = Net::SSH::Buffer.from(
79
+ :string, key.ssh_signature_type,
80
+ :mstring, key.ssh_do_sign(to_blob_without_signature)
81
+ ).to_s
82
+ self
83
+ end
84
+
85
+ def sign(key, sign_nonce=nil)
86
+ cert = clone
87
+ cert.sign!(key, sign_nonce)
88
+ end
89
+
90
+ # Checks whether the certificate's signature was signed by signature key.
91
+ def signature_valid?
92
+ buffer = Buffer.new(signature)
93
+ buffer.read_string # skip signature format
94
+ signature_key.ssh_do_verify(buffer.read_string, to_blob_without_signature)
95
+ end
96
+
97
+ def self.read_options(buffer)
98
+ names = []
99
+ options = buffer.read_buffer.read_all do |b|
100
+ name = b.read_string
101
+ names << name
102
+ data = b.read_string
103
+ data = Buffer.new(data).read_string unless data.empty?
104
+ [name, data]
105
+ end
106
+
107
+ if names.sort != names
108
+ raise ArgumentError, "option/extension names must be in sorted order"
109
+ end
110
+
111
+ Hash[options]
112
+ end
113
+ private_class_method :read_options
114
+
115
+ def self.type_symbol(type)
116
+ types = {1 => :user, 2 => :host}
117
+ raise ArgumentError("unsupported type: #{type}") unless types.include?(type)
118
+ types.fetch(type)
119
+ end
120
+ private_class_method :type_symbol
121
+
122
+ private
123
+
124
+ def type_value(type)
125
+ types = {user: 1, host: 2}
126
+ raise ArgumentError("unsupported type: #{type}") unless types.include?(type)
127
+ types.fetch(type)
128
+ end
129
+
130
+ def ssh_time(t)
131
+ # Times in certificates are represented as a uint64.
132
+ [[t.to_i, 0].max, 2<<64 - 1].min
133
+ end
134
+
135
+ def to_blob_without_signature
136
+ Buffer.from(
137
+ :string, ssh_type,
138
+ :string, nonce,
139
+ :raw, key_without_type,
140
+ :int64, serial,
141
+ :long, type_value(type),
142
+ :string, key_id,
143
+ :string, valid_principals.inject(Buffer.new) { |acc, elem| acc.write_string(elem) }.to_s,
144
+ :int64, ssh_time(valid_after),
145
+ :int64, ssh_time(valid_before),
146
+ :string, options_to_blob(critical_options),
147
+ :string, options_to_blob(extensions),
148
+ :string, reserved,
149
+ :string, signature_key.to_blob
150
+ ).to_s
151
+ end
152
+
153
+ def key_without_type
154
+ # key.to_blob gives us e.g. "ssh-rsa,<key>" but we just want "<key>".
155
+ tmp = Buffer.new(key.to_blob)
156
+ tmp.read_string # skip the underlying key type
157
+ tmp.read
158
+ end
159
+
160
+ def options_to_blob(options)
161
+ options.keys.sort.inject(Buffer.new) do |b, name|
162
+ b.write_string(name)
163
+ data = options.fetch(name)
164
+ data = Buffer.from(:string, data).to_s unless data.empty?
165
+ b.write_string(data)
166
+ end.to_s
167
+ end
168
+ end
169
+ end; end; end
@@ -1,7 +1,11 @@
1
1
  gem 'rbnacl', '>= 3.2.0', '< 5.0'
2
2
  gem 'bcrypt_pbkdf', '~> 1.0' unless RUBY_PLATFORM == "java"
3
3
 
4
- require 'rbnacl/libsodium'
4
+ begin
5
+ require 'rbnacl/libsodium'
6
+ rescue LoadError # rubocop:disable Lint/HandleExceptions
7
+ end
8
+
5
9
  require 'rbnacl'
6
10
  require 'rbnacl/signatures/ed25519/verify_key'
7
11
  require 'rbnacl/signatures/ed25519/signing_key'
@@ -23,6 +27,8 @@ module ED25519
23
27
  end
24
28
 
25
29
  class PubKey
30
+ attr_reader :verify_key
31
+
26
32
  def initialize(data)
27
33
  @verify_key = RbNaCl::Signatures::Ed25519::VerifyKey.new(data)
28
34
  end
@@ -39,6 +45,10 @@ module ED25519
39
45
  "ssh-ed25519"
40
46
  end
41
47
 
48
+ def ssh_signature_type
49
+ ssh_type
50
+ end
51
+
42
52
  def ssh_do_verify(sig,data)
43
53
  @verify_key.verify(sig,data)
44
54
  end
@@ -60,6 +70,8 @@ module ED25519
60
70
  MEND = "-----END OPENSSH PRIVATE KEY-----\n"
61
71
  MAGIC = "openssh-key-v1"
62
72
 
73
+ attr_reader :sign_key
74
+
63
75
  def initialize(datafull,password)
64
76
  raise ArgumentError.new("Expected #{MBEGIN} at start of private key") unless datafull.start_with?(MBEGIN)
65
77
  raise ArgumentError.new("Expected #{MEND} at end of private key") unless datafull.end_with?(MEND)
@@ -116,6 +128,18 @@ module ED25519
116
128
  @sign_key = SigningKeyFromFile.new(pk,sk)
117
129
  end
118
130
 
131
+ def to_blob
132
+ public_key.to_blob
133
+ end
134
+
135
+ def ssh_type
136
+ "ssh-ed25519"
137
+ end
138
+
139
+ def ssh_signature_type
140
+ ssh_type
141
+ end
142
+
119
143
  def public_key
120
144
  PubKey.new(@pk)
121
145
  end
@@ -14,7 +14,7 @@ rescue LoadError => e
14
14
  end
15
15
 
16
16
  def self.raiseUnlessLoaded(message)
17
- description = dependenciesRequiredForED25519 if ERROR.is_a?(Gem::LoadError)
17
+ description = ERROR.is_a?(LoadError) ? dependenciesRequiredForED25519 : ''
18
18
  description << "#{ERROR.class} : \"#{ERROR.message}\"\n" if ERROR
19
19
  raise NotImplementedError, "#{message}\n#{description}" unless LOADED
20
20
  end
@@ -146,7 +146,7 @@ module Net
146
146
  end
147
147
 
148
148
  if info[:key]
149
- return Net::SSH::Buffer.from(:string, identity.ssh_type,
149
+ return Net::SSH::Buffer.from(:string, identity.ssh_signature_type,
150
150
  :mstring, info[:key].ssh_do_sign(data.to_s)).to_s
151
151
  end
152
152
 
@@ -189,8 +189,12 @@ module Net
189
189
  key_files.map do |file|
190
190
  if readable_file?(file)
191
191
  identity = {}
192
+ cert_file = file + "-cert.pub"
192
193
  public_key_file = file + ".pub"
193
- if readable_file?(public_key_file)
194
+ if readable_file?(cert_file)
195
+ identity[:load_from] = :pubkey_file
196
+ identity[:pubkey_file] = cert_file
197
+ elsif readable_file?(public_key_file)
194
198
  identity[:load_from] = :pubkey_file
195
199
  identity[:pubkey_file] = public_key_file
196
200
  else
@@ -1,6 +1,7 @@
1
1
  require 'net/ssh/ruby_compat'
2
2
  require 'net/ssh/transport/openssl'
3
3
 
4
+ require 'net/ssh/authentication/certificate'
4
5
  require 'net/ssh/authentication/ed25519_loader'
5
6
 
6
7
  module Net; module SSH
@@ -186,6 +187,11 @@ module Net; module SSH
186
187
  data
187
188
  end
188
189
 
190
+ # Calls block(self) until the buffer is empty, and returns all results.
191
+ def read_all(&block)
192
+ Enumerator.new { |e| e << yield(self) until eof? }.to_a
193
+ end
194
+
189
195
  # Return the next 8 bytes as a 64-bit integer (in network byte order).
190
196
  # Returns nil if there are less than 8 bytes remaining to be read in the
191
197
  # buffer.
@@ -246,7 +252,9 @@ module Net; module SSH
246
252
  # a key. Only RSA, DSA, and ECDSA keys are supported.
247
253
  def read_keyblob(type)
248
254
  case type
249
- when /^ssh-dss(-cert-v01@openssh\.com)?$/
255
+ when /^(.*)-cert-v01@openssh\.com$/
256
+ key = Net::SSH::Authentication::Certificate.read_certblob(self, $1)
257
+ when /^ssh-dss$/
250
258
  key = OpenSSL::PKey::DSA.new
251
259
  if key.respond_to?(:set_pqg)
252
260
  key.set_pqg(read_bignum, read_bignum, read_bignum)
@@ -260,8 +268,7 @@ module Net; module SSH
260
268
  else
261
269
  key.pub_key = read_bignum
262
270
  end
263
-
264
- when /^ssh-rsa(-cert-v01@openssh\.com)?$/
271
+ when /^ssh-rsa$/
265
272
  key = OpenSSL::PKey::RSA.new
266
273
  if key.respond_to?(:set_key)
267
274
  e = read_bignum
@@ -93,7 +93,7 @@ module Net; module SSH
93
93
  blob = nil
94
94
  begin
95
95
  blob = fields.shift
96
- end while !blob.nil? && !/^(ssh-(rsa|dss|ed25519)|ecdsa-sha2-nistp\d+)$/.match(blob)
96
+ end while !blob.nil? && !/^(ssh-(rsa|dss|ed25519)|ecdsa-sha2-nistp\d+)(-cert-v01@openssh\.com)?$/.match(blob)
97
97
  blob = fields.shift
98
98
 
99
99
  raise Net::SSH::Exception, "public key at #{filename} is not valid" if blob.nil?
@@ -263,7 +263,7 @@ module Net; module SSH; module Transport
263
263
  is_supported
264
264
  end
265
265
 
266
- lwarn { "unsupported #{algorithm} algorithm: `#{unsupported}'" } unless unsupported.empty?
266
+ lwarn { %(unsupported algorithm: `#{unsupported}') } unless unsupported.empty?
267
267
 
268
268
  list
269
269
  end
@@ -60,6 +60,10 @@ module OpenSSL
60
60
  "ssh-rsa"
61
61
  end
62
62
 
63
+ def ssh_signature_type
64
+ ssh_type
65
+ end
66
+
63
67
  # Converts the key to a blob, according to the SSH2 protocol.
64
68
  def to_blob
65
69
  @blob ||= Net::SSH::Buffer.from(:string, ssh_type, :bignum, e, :bignum, n).to_s
@@ -87,6 +91,10 @@ module OpenSSL
87
91
  "ssh-dss"
88
92
  end
89
93
 
94
+ def ssh_signature_type
95
+ ssh_type
96
+ end
97
+
90
98
  # Converts the key to a blob, according to the SSH2 protocol.
91
99
  def to_blob
92
100
  @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
@@ -165,6 +173,10 @@ module OpenSSL
165
173
  "ecdsa-sha2-#{CurveNameAliasInv[self.group.curve_name]}"
166
174
  end
167
175
 
176
+ def ssh_signature_type
177
+ ssh_type
178
+ end
179
+
168
180
  def digester
169
181
  if self.group.curve_name =~ /^[a-z]+(\d+)\w*\z/
170
182
  curve_size = $1.to_i
@@ -48,14 +48,14 @@ module Net; module SSH
48
48
  MAJOR = 4
49
49
 
50
50
  # The minor component of this version of the Net::SSH library
51
- MINOR = 0
51
+ MINOR = 1
52
52
 
53
53
  # The tiny component of this version of the Net::SSH library
54
- TINY = 1
54
+ TINY = 0
55
55
 
56
56
  # The prerelease component of this version of the Net::SSH library
57
57
  # nil allowed
58
- PRE = nil
58
+ PRE = "beta1"
59
59
 
60
60
  # The current version of the Net::SSH library as a Version instance
61
61
  CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: net-ssh
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.1
4
+ version: 4.1.0.beta1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jamis Buck
@@ -32,7 +32,7 @@ cert_chain:
32
32
  L4d54WIy4HkZCqQXoTSiK5HZMIdXkPk3F1bZdJ8Dy1sMRru0rUkkM5mW7TQ75mfW
33
33
  Zp0QrZyNZhtitrXFbZneGRrIA/8G2Krft5Ly/A==
34
34
  -----END CERTIFICATE-----
35
- date: 2017-01-07 00:00:00.000000000 Z
35
+ date: 2017-01-20 00:00:00.000000000 Z
36
36
  dependencies:
37
37
  - !ruby/object:Gem::Dependency
38
38
  requirement: !ruby/object:Gem::Requirement
@@ -166,6 +166,7 @@ files:
166
166
  - appveyor.yml
167
167
  - lib/net/ssh.rb
168
168
  - lib/net/ssh/authentication/agent.rb
169
+ - lib/net/ssh/authentication/certificate.rb
169
170
  - lib/net/ssh/authentication/constants.rb
170
171
  - lib/net/ssh/authentication/ed25519.rb
171
172
  - lib/net/ssh/authentication/ed25519_loader.rb
@@ -265,9 +266,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
265
266
  version: '2.0'
266
267
  required_rubygems_version: !ruby/object:Gem::Requirement
267
268
  requirements:
268
- - - ">="
269
+ - - ">"
269
270
  - !ruby/object:Gem::Version
270
- version: '0'
271
+ version: 1.3.1
271
272
  requirements: []
272
273
  rubyforge_project:
273
274
  rubygems_version: 2.6.8
metadata.gz.sig CHANGED
Binary file