net-ssh 2.4.0 → 2.5.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 (37) hide show
  1. data/CHANGELOG.rdoc +21 -0
  2. data/Manifest +11 -0
  3. data/lib/net/ssh/authentication/key_manager.rb +1 -1
  4. data/lib/net/ssh/authentication/session.rb +12 -4
  5. data/lib/net/ssh/buffer.rb +12 -2
  6. data/lib/net/ssh/key_factory.rb +7 -2
  7. data/lib/net/ssh/known_hosts.rb +12 -2
  8. data/lib/net/ssh/ruby_compat.rb +8 -0
  9. data/lib/net/ssh/transport/algorithms.rb +22 -1
  10. data/lib/net/ssh/transport/cipher_factory.rb +32 -5
  11. data/lib/net/ssh/transport/constants.rb +3 -1
  12. data/lib/net/ssh/transport/ctr.rb +95 -0
  13. data/lib/net/ssh/transport/hmac.rb +8 -5
  14. data/lib/net/ssh/transport/hmac/ripemd160.rb +13 -0
  15. data/lib/net/ssh/transport/kex.rb +11 -0
  16. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +44 -0
  17. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +11 -3
  18. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +93 -0
  19. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +13 -0
  20. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +13 -0
  21. data/lib/net/ssh/transport/openssl.rb +111 -1
  22. data/lib/net/ssh/version.rb +1 -1
  23. data/net-ssh.gemspec +12 -4
  24. data/test/authentication/test_key_manager.rb +48 -1
  25. data/test/test_buffer.rb +92 -2
  26. data/test/test_key_factory.rb +42 -0
  27. data/test/transport/hmac/test_ripemd160.rb +34 -0
  28. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +13 -0
  29. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +161 -0
  30. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +37 -0
  31. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +37 -0
  32. data/test/transport/test_algorithms.rb +41 -19
  33. data/test/transport/test_cipher_factory.rb +255 -27
  34. data/test/transport/test_packet_stream.rb +1009 -0
  35. metadata +13 -4
  36. data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
  37. data/lib/net/ssh/authentication/agent/socket.rb +0 -170
@@ -0,0 +1,13 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+
5
+ # The RIPEMD-160 HMAC algorithm. This has a mac and key length of 20, and
6
+ # uses the RIPEMD-160 digest algorithm.
7
+ class RIPEMD160 < Abstract
8
+ mac_length 20
9
+ key_length 20
10
+ digest_class OpenSSL::Digest::RIPEMD160
11
+ end
12
+
13
+ end
@@ -1,4 +1,5 @@
1
1
  require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
+ require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
2
3
  require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
3
4
  require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha256'
4
5
 
@@ -9,9 +10,19 @@ module Net::SSH::Transport
9
10
  MAP = {
10
11
  'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
11
12
  'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
13
+ 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
12
14
  }
13
15
  if defined?(DiffieHellmanGroupExchangeSHA256)
14
16
  MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256
15
17
  end
18
+ if defined?(OpenSSL::PKey::EC)
19
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
20
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
21
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp521'
22
+
23
+ MAP['ecdh-sha2-nistp256'] = EcdhSHA2NistP256
24
+ MAP['ecdh-sha2-nistp384'] = EcdhSHA2NistP384
25
+ MAP['ecdh-sha2-nistp521'] = EcdhSHA2NistP521
26
+ end
16
27
  end
17
28
  end
@@ -0,0 +1,44 @@
1
+ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
+
3
+ module Net; module SSH; module Transport; module Kex
4
+
5
+ # A key-exchange service implementing the "diffie-hellman-group14-sha1"
6
+ # key-exchange algorithm. (defined in RFC 4253)
7
+ class DiffieHellmanGroup14SHA1 < DiffieHellmanGroup1SHA1
8
+ include Constants, Loggable
9
+
10
+ # The value of 'P', as a string, in hexadecimal
11
+ P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
12
+ "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
13
+ "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
14
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
15
+ "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
16
+ "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
17
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
18
+ "49286651" "ECE45B3D" "C2007CB8" "A163BF05" +
19
+ "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" +
20
+ "83655D23" "DCA3AD96" "1C62F356" "208552BB" +
21
+ "9ED52907" "7096966D" "670C354E" "4ABC9804" +
22
+ "F1746C08" "CA18217C" "32905E46" "2E36CE3B" +
23
+ "E39E772C" "180E8603" "9B2783A2" "EC07A28F" +
24
+ "B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" +
25
+ "3995497C" "EA956AE5" "15D22618" "98FA0510" +
26
+ "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"
27
+
28
+ # The radix in which P_s represents the value of P
29
+ P_r = 16
30
+
31
+ # The group constant
32
+ G = 2
33
+
34
+ private
35
+
36
+ def get_p
37
+ OpenSSL::BN.new(P_s, P_r)
38
+ end
39
+
40
+ def get_g
41
+ G
42
+ end
43
+ end
44
+ end; end; end; end
@@ -40,8 +40,8 @@ module Net; module SSH; module Transport; module Kex
40
40
  # required by this algorithm, which was acquired during earlier
41
41
  # processing.
42
42
  def initialize(algorithms, connection, data)
43
- @p = OpenSSL::BN.new(P_s, P_r)
44
- @g = G
43
+ @p = get_p
44
+ @g = get_g
45
45
 
46
46
  @digester = OpenSSL::Digest::SHA1
47
47
  @algorithms = algorithms
@@ -76,7 +76,15 @@ module Net; module SSH; module Transport; module Kex
76
76
  end
77
77
 
78
78
  private
79
-
79
+
80
+ def get_p
81
+ OpenSSL::BN.new(P_s, P_r)
82
+ end
83
+
84
+ def get_g
85
+ G
86
+ end
87
+
80
88
  # Returns the DH key parameters for the current connection.
81
89
  def get_parameters
82
90
  [p, g]
@@ -0,0 +1,93 @@
1
+ require 'net/ssh/transport/constants'
2
+ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
3
+
4
+ module Net; module SSH; module Transport; module Kex
5
+
6
+ # A key-exchange service implementing the "ecdh-sha2-nistp256"
7
+ # key-exchange algorithm. (defined in RFC 5656)
8
+ class EcdhSHA2NistP256 < DiffieHellmanGroup1SHA1
9
+ include Constants, Loggable
10
+
11
+ attr_reader :ecdh
12
+
13
+ def digester
14
+ OpenSSL::Digest::SHA256
15
+ end
16
+
17
+ def curve_name
18
+ OpenSSL::PKey::EC::CurveNameAlias['nistp256']
19
+ end
20
+
21
+ def initialize(algorithms, connection, data)
22
+ @algorithms = algorithms
23
+ @connection = connection
24
+
25
+ @digester = digester
26
+ @data = data.dup
27
+ @ecdh = generate_key
28
+ @logger = @data.delete(:logger)
29
+ end
30
+
31
+ private
32
+
33
+ def get_message_types
34
+ [KEXECDH_INIT, KEXECDH_REPLY]
35
+ end
36
+
37
+ def build_signature_buffer(result)
38
+ response = Net::SSH::Buffer.new
39
+ response.write_string data[:client_version_string],
40
+ data[:server_version_string],
41
+ data[:client_algorithm_packet],
42
+ data[:server_algorithm_packet],
43
+ result[:key_blob],
44
+ ecdh.public_key.to_bn.to_s(2),
45
+ result[:server_ecdh_pubkey]
46
+ response.write_bignum result[:shared_secret]
47
+ response
48
+ end
49
+
50
+ def generate_key #:nodoc:
51
+ OpenSSL::PKey::EC.new(curve_name).generate_key
52
+ end
53
+
54
+ def send_kexinit #:nodoc:
55
+ init, reply = get_message_types
56
+
57
+ # send the KEXECDH_INIT message
58
+ ## byte SSH_MSG_KEX_ECDH_INIT
59
+ ## string Q_C, client's ephemeral public key octet string
60
+ buffer = Net::SSH::Buffer.from(:byte, init, :string, ecdh.public_key.to_bn.to_s(2))
61
+ connection.send_message(buffer)
62
+
63
+ # expect the following KEXECDH_REPLY message
64
+ ## byte SSH_MSG_KEX_ECDH_REPLY
65
+ ## string K_S, server's public host key
66
+ ## string Q_S, server's ephemeral public key octet string
67
+ ## string the signature on the exchange hash
68
+ buffer = connection.next_message
69
+ raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
70
+
71
+ result = Hash.new
72
+ result[:key_blob] = buffer.read_string
73
+ result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
74
+ result[:server_ecdh_pubkey] = buffer.read_string
75
+
76
+ # compute shared secret from server's public key and client's private key
77
+ pk = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(curve_name).group,
78
+ OpenSSL::BN.new(result[:server_ecdh_pubkey], 2))
79
+ result[:shared_secret] = OpenSSL::BN.new(ecdh.dh_compute_key(pk), 2)
80
+
81
+ sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
82
+ sig_type = sig_buffer.read_string
83
+ if sig_type != algorithms.host_key
84
+ raise Net::SSH::Exception,
85
+ "host key algorithm mismatch for signature " +
86
+ "'#{sig_type}' != '#{algorithms.host_key}'"
87
+ end
88
+ result[:server_sig] = sig_buffer.read_string
89
+
90
+ return result
91
+ end
92
+ end
93
+ end; end; end; end
@@ -0,0 +1,13 @@
1
+ module Net; module SSH; module Transport; module Kex
2
+
3
+ # A key-exchange service implementing the "ecdh-sha2-nistp256"
4
+ # key-exchange algorithm. (defined in RFC 5656)
5
+ class EcdhSHA2NistP384 < EcdhSHA2NistP256
6
+ def digester
7
+ OpenSSL::Digest::SHA384
8
+ end
9
+ def curve_name
10
+ OpenSSL::PKey::EC::CurveNameAlias['nistp384']
11
+ end
12
+ end
13
+ end; end; end; end
@@ -0,0 +1,13 @@
1
+ module Net; module SSH; module Transport; module Kex
2
+
3
+ # A key-exchange service implementing the "ecdh-sha2-nistp521"
4
+ # key-exchange algorithm. (defined in RFC 5656)
5
+ class EcdhSHA2NistP521 < EcdhSHA2NistP256
6
+ def digester
7
+ OpenSSL::Digest::SHA512
8
+ end
9
+ def curve_name
10
+ OpenSSL::PKey::EC::CurveNameAlias['nistp521']
11
+ end
12
+ end
13
+ end; end; end; end
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  require 'openssl'
2
3
 
3
4
  module OpenSSL
@@ -122,6 +123,115 @@ module OpenSSL
122
123
  end
123
124
  end
124
125
 
125
- end
126
+ if defined?(OpenSSL::PKey::EC)
127
+ # This class is originally defined in the OpenSSL module. As needed, methods
128
+ # have been added to it by the Net::SSH module for convenience in dealing
129
+ # with SSH functionality.
130
+ class EC
131
+ CurveNameAlias = {
132
+ "nistp256" => "prime256v1",
133
+ "nistp384" => "secp384r1",
134
+ "nistp521" => "secp521r1",
135
+ }
136
+
137
+ CurveNameAliasInv = {
138
+ "prime256v1" => "nistp256",
139
+ "secp384r1" => "nistp384",
140
+ "secp521r1" => "nistp521",
141
+ }
142
+
143
+ def self.read_keyblob(curve_name_in_type, buffer)
144
+ curve_name_in_key = buffer.read_string
145
+ unless curve_name_in_type == curve_name_in_key
146
+ raise Net::SSH::Exception, "curve name mismatched (`#{curve_name_in_key}' with `#{curve_name_in_type}')"
147
+ end
148
+ public_key_oct = buffer.read_string
149
+ begin
150
+ key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
151
+ group = key.group
152
+ point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
153
+ key.public_key = point
154
+
155
+ return key
156
+ rescue OpenSSL::PKey::ECError => e
157
+ raise NotImplementedError, "unsupported key type `#{type}'"
158
+ end
159
+
160
+ end
161
+
162
+ # Returns the description of this key type used by the
163
+ # SSH2 protocol, like "ecdsa-sha2-nistp256"
164
+ def ssh_type
165
+ "ecdsa-sha2-#{CurveNameAliasInv[self.group.curve_name]}"
166
+ end
126
167
 
168
+ def digester
169
+ if self.group.curve_name =~ /^[a-z]+(\d+)\w*\z/
170
+ curve_size = $1.to_i
171
+ if curve_size <= 256
172
+ OpenSSL::Digest::SHA256.new
173
+ elsif curve_size <= 384
174
+ OpenSSL::Digest::SHA384.new
175
+ else
176
+ OpenSSL::Digest::SHA512.new
177
+ end
178
+ else
179
+ OpenSSL::Digest::SHA256.new
180
+ end
181
+ end
182
+ private :digester
183
+
184
+ # Converts the key to a blob, according to the SSH2 protocol.
185
+ def to_blob
186
+ @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
187
+ :string, CurveNameAliasInv[self.group.curve_name],
188
+ :string, self.public_key.to_bn.to_s(2)).to_s
189
+ @blob
190
+ end
191
+
192
+ # Verifies the given signature matches the given data.
193
+ def ssh_do_verify(sig, data)
194
+ digest = digester.digest(data)
195
+ a1sig = nil
196
+
197
+ begin
198
+ sig_r_len = sig[0,4].unpack("H*")[0].to_i(16)
199
+ sig_l_len = sig[4+sig_r_len,4].unpack("H*")[0].to_i(16)
200
+
201
+ sig_r = sig[4,sig_r_len].unpack("H*")[0]
202
+ sig_s = sig[4+sig_r_len+4,sig_l_len].unpack("H*")[0]
203
+
204
+ a1sig = OpenSSL::ASN1::Sequence([
205
+ OpenSSL::ASN1::Integer(sig_r.to_i(16)),
206
+ OpenSSL::ASN1::Integer(sig_s.to_i(16)),
207
+ ])
208
+ rescue
209
+ end
210
+
211
+ if a1sig == nil
212
+ return false
213
+ else
214
+ dsa_verify_asn1(digest, a1sig.to_der)
215
+ end
216
+ end
217
+
218
+ # Returns the signature for the given data.
219
+ def ssh_do_sign(data)
220
+ digest = digester.digest(data)
221
+ sig = dsa_sign_asn1(digest)
222
+ a1sig = OpenSSL::ASN1.decode( sig )
223
+
224
+ sig_r = a1sig.value[0].value
225
+ sig_s = a1sig.value[1].value
226
+
227
+ return Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
228
+ end
229
+ end
230
+ else
231
+ class OpenSSL::PKey::ECError < RuntimeError
232
+ # for compatibility with interpreters
233
+ # without EC support (i.e. JRuby)
234
+ end
235
+ end
236
+ end
127
237
  end
@@ -48,7 +48,7 @@ module Net; module SSH
48
48
  MAJOR = 2
49
49
 
50
50
  # The minor component of this version of the Net::SSH library
51
- MINOR = 4
51
+ MINOR = 5
52
52
 
53
53
  # The tiny component of this version of the Net::SSH library
54
54
  TINY = 0
@@ -1,7 +1,7 @@
1
1
  @spec = Gem::Specification.new do |s|
2
2
  s.name = "net-ssh"
3
3
  s.rubyforge_project = 'net-ssh'
4
- s.version = "2.4.0"
4
+ s.version = "2.5.0"
5
5
  s.summary = "Net::SSH: a pure-Ruby implementation of the SSH2 client protocol."
6
6
  s.description = s.summary + " It allows you to write programs that invoke and interact with processes on remote servers, via SSH2."
7
7
  s.authors = ["Jamis Buck", "Delano Mandelbaum"]
@@ -31,8 +31,6 @@
31
31
  THANKS.rdoc
32
32
  lib/net/ssh.rb
33
33
  lib/net/ssh/authentication/agent.rb
34
- lib/net/ssh/authentication/agent/java_pageant.rb
35
- lib/net/ssh/authentication/agent/socket.rb
36
34
  lib/net/ssh/authentication/constants.rb
37
35
  lib/net/ssh/authentication/key_manager.rb
38
36
  lib/net/ssh/authentication/methods/abstract.rb
@@ -74,11 +72,13 @@
74
72
  lib/net/ssh/transport/algorithms.rb
75
73
  lib/net/ssh/transport/cipher_factory.rb
76
74
  lib/net/ssh/transport/constants.rb
75
+ lib/net/ssh/transport/ctr.rb
77
76
  lib/net/ssh/transport/hmac.rb
78
77
  lib/net/ssh/transport/hmac/abstract.rb
79
78
  lib/net/ssh/transport/hmac/md5.rb
80
79
  lib/net/ssh/transport/hmac/md5_96.rb
81
80
  lib/net/ssh/transport/hmac/none.rb
81
+ lib/net/ssh/transport/hmac/ripemd160.rb
82
82
  lib/net/ssh/transport/hmac/sha1.rb
83
83
  lib/net/ssh/transport/hmac/sha1_96.rb
84
84
  lib/net/ssh/transport/hmac/sha2_256.rb
@@ -89,8 +89,12 @@
89
89
  lib/net/ssh/transport/key_expander.rb
90
90
  lib/net/ssh/transport/kex.rb
91
91
  lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb
92
+ lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb
92
93
  lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb
93
94
  lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb
95
+ lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb
96
+ lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb
97
+ lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb
94
98
  lib/net/ssh/transport/openssl.rb
95
99
  lib/net/ssh/transport/packet_stream.rb
96
100
  lib/net/ssh/transport/server_version.rb
@@ -129,6 +133,7 @@
129
133
  test/transport/hmac/test_md5.rb
130
134
  test/transport/hmac/test_md5_96.rb
131
135
  test/transport/hmac/test_none.rb
136
+ test/transport/hmac/test_ripemd160.rb
132
137
  test/transport/hmac/test_sha1.rb
133
138
  test/transport/hmac/test_sha1_96.rb
134
139
  test/transport/hmac/test_sha2_256.rb
@@ -136,8 +141,12 @@
136
141
  test/transport/hmac/test_sha2_512.rb
137
142
  test/transport/hmac/test_sha2_512_96.rb
138
143
  test/transport/kex/test_diffie_hellman_group1_sha1.rb
144
+ test/transport/kex/test_diffie_hellman_group14_sha1.rb
139
145
  test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb
140
146
  test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb
147
+ test/transport/kex/test_ecdh_sha2_nistp256.rb
148
+ test/transport/kex/test_ecdh_sha2_nistp384.rb
149
+ test/transport/kex/test_ecdh_sha2_nistp521.rb
141
150
  test/transport/test_algorithms.rb
142
151
  test/transport/test_cipher_factory.rb
143
152
  test/transport/test_hmac.rb
@@ -148,5 +157,4 @@
148
157
  test/transport/test_state.rb
149
158
  )
150
159
 
151
-
152
160
  end
@@ -62,6 +62,28 @@ module Authentication
62
62
  assert_equal({:from => :agent}, manager.known_identities[dsa])
63
63
  end
64
64
 
65
+ if defined?(OpenSSL::PKey::EC)
66
+ def test_identities_with_ecdsa_should_load_from_agent
67
+ manager.stubs(:agent).returns(agent_with_ecdsa_keys)
68
+
69
+ identities = []
70
+ manager.each_identity { |identity| identities << identity }
71
+ assert_equal 5, identities.length
72
+
73
+ assert_equal rsa.to_blob, identities[0].to_blob
74
+ assert_equal dsa.to_blob, identities[1].to_blob
75
+ assert_equal ecdsa_sha2_nistp256.to_blob, identities[2].to_blob
76
+ assert_equal ecdsa_sha2_nistp384.to_blob, identities[3].to_blob
77
+ assert_equal ecdsa_sha2_nistp521.to_blob, identities[4].to_blob
78
+
79
+ assert_equal({:from => :agent}, manager.known_identities[rsa])
80
+ assert_equal({:from => :agent}, manager.known_identities[dsa])
81
+ assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp256])
82
+ assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp384])
83
+ assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp521])
84
+ end
85
+ end
86
+
65
87
  def test_only_identities_with_key_files_should_load_from_agent_of_keys_only_set
66
88
  manager(:keys_only => true).stubs(:agent).returns(agent)
67
89
 
@@ -139,7 +161,11 @@ module Authentication
139
161
  Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, any_of(true, false)).returns(key).at_least_once
140
162
  end
141
163
 
142
- key.stubs(:public_key).returns(key)
164
+ # do not override OpenSSL::PKey::EC#public_key
165
+ # (it will be called in transport/openssl.rb.)
166
+ unless defined?(OpenSSL::PKey::EC) && key.public_key.kind_of?(OpenSSL::PKey::EC::Point)
167
+ key.stubs(:public_key).returns(key)
168
+ end
143
169
  end
144
170
 
145
171
  def stub_file_public_key(name, key)
@@ -158,10 +184,31 @@ module Authentication
158
184
  @dsa ||= OpenSSL::PKey::DSA.new(512)
159
185
  end
160
186
 
187
+ if defined?(OpenSSL::PKey::EC)
188
+ def ecdsa_sha2_nistp256
189
+ @ecdsa_sha2_nistp256 ||= OpenSSL::PKey::EC.new("prime256v1").generate_key
190
+ end
191
+
192
+ def ecdsa_sha2_nistp384
193
+ @ecdsa_sha2_nistp384 ||= OpenSSL::PKey::EC.new("secp384r1").generate_key
194
+ end
195
+
196
+ def ecdsa_sha2_nistp521
197
+ @ecdsa_sha2_nistp521 ||= OpenSSL::PKey::EC.new("secp521r1").generate_key
198
+ end
199
+ end
200
+
161
201
  def agent
162
202
  @agent ||= stub("agent", :identities => [rsa, dsa])
163
203
  end
164
204
 
205
+ def agent_with_ecdsa_keys
206
+ @agent ||= stub("agent", :identities => [rsa, dsa,
207
+ ecdsa_sha2_nistp256,
208
+ ecdsa_sha2_nistp384,
209
+ ecdsa_sha2_nistp521])
210
+ end
211
+
165
212
  def manager(options = {})
166
213
  @manager ||= Net::SSH::Authentication::KeyManager.new(nil, options)
167
214
  end