summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklós Fazekas <mfazekas@szemafor.com>2019-09-11 15:29:18 +0200
committerGitHub <noreply@github.com>2019-09-11 15:29:18 +0200
commit1dd787785fe84e08326c0796685466491c66911f (patch)
tree5e2f9d78f00f3f94aaf968beb7e2700c26ade7ac
parent9525835a83b93e652822882f3b606494e9f11639 (diff)
parent4cca9f48399774c9c0bc3a38939001a158e5f0bb (diff)
downloadnet-ssh-1dd787785fe84e08326c0796685466491c66911f.tar.gz
Merge pull request #690 from fwininger/support_curve25519
Add Curve25519Sha256
-rw-r--r--.rubocop_todo.yml34
-rw-r--r--README.md3
-rw-r--r--lib/net/ssh/transport/algorithms.rb42
-rw-r--r--lib/net/ssh/transport/kex.rb7
-rw-r--r--lib/net/ssh/transport/kex/curve25519_sha256.rb38
-rw-r--r--lib/net/ssh/transport/kex/curve25519_sha256_loader.rb30
-rw-r--r--net-ssh.gemspec3
-rw-r--r--test/transport/kex/test_curve25519_sha256.rb156
-rw-r--r--test/transport/test_algorithms.rb18
9 files changed, 290 insertions, 41 deletions
diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml
index 56bd097..8ca8930 100644
--- a/.rubocop_todo.yml
+++ b/.rubocop_todo.yml
@@ -1,6 +1,6 @@
# This configuration was generated by
# `rubocop --auto-gen-config`
-# on 2019-08-28 11:52:48 +0200 using RuboCop version 0.74.0.
+# on 2019-09-10 17:13:26 +0200 using RuboCop version 0.74.0.
# The point is for the user to remove these configuration records
# one by one as the offenses are removed from the code base.
# Note that changes in the inspected code, or installation of new
@@ -27,12 +27,12 @@ Layout/AlignHash:
- 'lib/net/ssh/transport/kex.rb'
- 'test/test_config.rb'
-# Offense count: 71
+# Offense count: 70
# Cop supports --auto-correct.
Layout/EmptyLineAfterGuardClause:
Enabled: false
-# Offense count: 171
+# Offense count: 170
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: empty_lines, empty_lines_except_namespace, empty_lines_special, no_empty_lines
@@ -47,13 +47,12 @@ Layout/IndentFirstArrayElement:
Exclude:
- 'lib/net/ssh/transport/openssl.rb'
-# Offense count: 4
+# Offense count: 3
# Cop supports --auto-correct.
Layout/LeadingBlankLines:
Exclude:
- 'Rakefile'
- 'lib/net/ssh/authentication/pub_key_fingerprint.rb'
- - 'net-ssh.gemspec'
- 'support/arcfour_check.rb'
# Offense count: 14
@@ -88,7 +87,7 @@ Layout/SpaceAfterColon:
- 'test/integration/test_ed25519_pkeys.rb'
- 'test/verifiers/test_always.rb'
-# Offense count: 283
+# Offense count: 281
# Cop supports --auto-correct.
Layout/SpaceAfterComma:
Enabled: false
@@ -252,7 +251,7 @@ Lint/UselessAssignment:
- 'test/integration/common.rb'
- 'test/integration/test_forward.rb'
-# Offense count: 224
+# Offense count: 229
Metrics/AbcSize:
Max: 69
@@ -267,7 +266,7 @@ Metrics/BlockLength:
Metrics/BlockNesting:
Max: 4
-# Offense count: 30
+# Offense count: 31
# Configuration parameters: CountComments.
Metrics/ClassLength:
Max: 488
@@ -276,7 +275,7 @@ Metrics/ClassLength:
Metrics/CyclomaticComplexity:
Max: 27
-# Offense count: 208
+# Offense count: 211
# Configuration parameters: CountComments, ExcludedMethods.
Metrics/MethodLength:
Max: 82
@@ -354,12 +353,13 @@ Naming/MemoizedInstanceVariableName:
- 'lib/net/ssh/transport/openssl.rb'
- 'test/authentication/test_key_manager.rb'
-# Offense count: 30
+# Offense count: 32
# Configuration parameters: EnforcedStyle.
# SupportedStyles: snake_case, camelCase
Naming/MethodName:
Exclude:
- 'lib/net/ssh/authentication/ed25519_loader.rb'
+ - 'lib/net/ssh/transport/kex/curve25519_sha256_loader.rb'
- 'test/authentication/test_agent.rb'
- 'test/authentication/test_session.rb'
- 'test/common.rb'
@@ -551,7 +551,7 @@ Style/DefWithParentheses:
Exclude:
- 'test/integration/test_forward.rb'
-# Offense count: 13
+# Offense count: 14
Style/Documentation:
Exclude:
- 'spec/**/*'
@@ -561,6 +561,7 @@ Style/Documentation:
- 'lib/net/ssh/connection/session.rb'
- 'lib/net/ssh/ruby_compat.rb'
- 'lib/net/ssh/test/extensions.rb'
+ - 'lib/net/ssh/transport/kex.rb'
- 'lib/net/ssh/transport/key_expander.rb'
- 'lib/net/ssh/transport/openssl.rb'
@@ -592,7 +593,7 @@ Style/FormatStringToken:
Exclude:
- 'lib/net/ssh/loggable.rb'
-# Offense count: 163
+# Offense count: 166
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: always, never
@@ -610,7 +611,7 @@ Style/IfInsideElse:
Exclude:
- 'lib/net/ssh/connection/session.rb'
-# Offense count: 15
+# Offense count: 16
# Cop supports --auto-correct.
Style/IfUnlessModifier:
Exclude:
@@ -619,6 +620,7 @@ Style/IfUnlessModifier:
- 'lib/net/ssh/proxy/command.rb'
- 'lib/net/ssh/service/forward.rb'
- 'lib/net/ssh/transport/ctr.rb'
+ - 'lib/net/ssh/transport/kex.rb'
- 'lib/net/ssh/transport/kex/abstract5656.rb'
- 'lib/net/ssh/transport/key_expander.rb'
- 'test/integration/test_proxy.rb'
@@ -672,7 +674,7 @@ Style/MultipleComparison:
- 'lib/net/ssh/known_hosts.rb'
- 'lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb'
-# Offense count: 42
+# Offense count: 41
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle.
# SupportedStyles: literals, strict
@@ -899,7 +901,7 @@ Style/SpecialGlobalVars:
- 'test/manual/test_pageant.rb'
- 'test/test_all.rb'
-# Offense count: 1766
+# Offense count: 1754
# Cop supports --auto-correct.
# Configuration parameters: EnforcedStyle, ConsistentQuotesInMultiline.
# SupportedStyles: single_quotes, double_quotes
@@ -963,7 +965,7 @@ Style/ZeroLengthPredicate:
- 'lib/net/ssh/buffered_io.rb'
- 'lib/net/ssh/connection/channel.rb'
-# Offense count: 1615
+# Offense count: 1636
# Cop supports --auto-correct.
# Configuration parameters: AutoCorrect, AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
# URISchemes: http, https
diff --git a/README.md b/README.md
index 1f546ed..e00321c 100644
--- a/README.md
+++ b/README.md
@@ -50,6 +50,7 @@ Unsecure algoritms will be definively remove in Net::SSH 7.*.
| Name | Support | Details |
|--------------------------------------|-----------------------|----------|
+| curve25519-sha256 | OK | Require the gem `x25519` |
| ecdh-sha2-nistp521 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
| ecdh-sha2-nistp384 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
| ecdh-sha2-nistp256 | OK | [using weak elliptic curves](https://safecurves.cr.yp.to/) |
@@ -190,6 +191,8 @@ gem install ed25519
gem install bcrypt_pbkdf
```
+For curve25519-sha256 kex exchange support your bundle file should contain `x25519` dependency.
+
## RUBY SUPPORT
* See [net-ssh.gemspec](https://github.com/net-ssh/net-ssh/blob/master/net-ssh.gemspec) for current versions ruby requirements
diff --git a/lib/net/ssh/transport/algorithms.rb b/lib/net/ssh/transport/algorithms.rb
index 8fca624..830fa71 100644
--- a/lib/net/ssh/transport/algorithms.rb
+++ b/lib/net/ssh/transport/algorithms.rb
@@ -5,13 +5,13 @@ require 'net/ssh/transport/cipher_factory'
require 'net/ssh/transport/constants'
require 'net/ssh/transport/hmac'
require 'net/ssh/transport/kex'
+require 'net/ssh/transport/kex/curve25519_sha256_loader'
require 'net/ssh/transport/server_version'
require 'net/ssh/authentication/ed25519_loader'
module Net
module SSH
module Transport
-
# Implements the higher-level logic behind an SSH key-exchange. It handles
# both the initial exchange, as well as subsequent re-exchanges (as needed).
# It also encapsulates the negotiation of the algorithms, and provides a
@@ -45,7 +45,7 @@ module Net
hmac: %w[hmac-sha2-512 hmac-sha2-256
hmac-sha1]
- }
+ }.freeze
if Net::SSH::Authentication::ED25519Loader::LOADED
DEFAULT_ALGORITHMS[:host_key].unshift(
@@ -54,33 +54,40 @@ module Net
)
end
+ if Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
+ DEFAULT_ALGORITHMS[:kex].unshift(
+ 'curve25519-sha256',
+ 'curve22519-sha256@libssh.org'
+ )
+ end
+
# Define all algorithms, with the deprecated, supported by Net::SSH.
ALGORITHMS = {
host_key: DEFAULT_ALGORITHMS[:host_key] + %w[ssh-dss],
kex: DEFAULT_ALGORITHMS[:kex] +
- %w[diffie-hellman-group-exchange-sha1
- diffie-hellman-group1-sha1],
+ %w[diffie-hellman-group-exchange-sha1
+ diffie-hellman-group1-sha1],
encryption: DEFAULT_ALGORITHMS[:encryption] +
- %w[aes256-cbc aes192-cbc aes128-cbc
- rijndael-cbc@lysator.liu.se
- blowfish-ctr blowfish-cbc
- cast128-ctr cast128-cbc
- 3des-ctr 3des-cbc
- idea-cbc
- none],
+ %w[aes256-cbc aes192-cbc aes128-cbc
+ rijndael-cbc@lysator.liu.se
+ blowfish-ctr blowfish-cbc
+ cast128-ctr cast128-cbc
+ 3des-ctr 3des-cbc
+ idea-cbc
+ none],
hmac: DEFAULT_ALGORITHMS[:hmac] +
- %w[hmac-sha2-512-96 hmac-sha2-256-96
- hmac-sha1-96
- hmac-ripemd160 hmac-ripemd160@openssh.com
- hmac-md5 hmac-md5-96
- none],
+ %w[hmac-sha2-512-96 hmac-sha2-256-96
+ hmac-sha1-96
+ hmac-ripemd160 hmac-ripemd160@openssh.com
+ hmac-md5 hmac-md5-96
+ none],
compression: %w[none zlib@openssh.com zlib],
language: %w[]
- }
+ }.freeze
# The underlying transport layer session that supports this object
attr_reader :session
@@ -148,6 +155,7 @@ module Net
# Start the algorithm negotation
def start
raise ArgumentError, "Cannot call start if it's negotiation started or done" if @pending || @initialized
+
send_kexinit
end
diff --git a/lib/net/ssh/transport/kex.rb b/lib/net/ssh/transport/kex.rb
index 695bb5e..bec7f9f 100644
--- a/lib/net/ssh/transport/kex.rb
+++ b/lib/net/ssh/transport/kex.rb
@@ -5,19 +5,24 @@ require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha256'
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
require 'net/ssh/transport/kex/ecdh_sha2_nistp521'
+require 'net/ssh/transport/kex/curve25519_sha256_loader'
module Net::SSH::Transport
module Kex
# Maps the supported key-exchange algorithms as named by the SSH protocol
# to their corresponding implementors.
MAP = {
- 'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
+ 'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
'diffie-hellman-group-exchange-sha256' => DiffieHellmanGroupExchangeSHA256,
'ecdh-sha2-nistp256' => EcdhSHA2NistP256,
'ecdh-sha2-nistp384' => EcdhSHA2NistP384,
'ecdh-sha2-nistp521' => EcdhSHA2NistP521
}
+
+ if Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
+ MAP['curve25519-sha256'] = Curve25519Sha256
+ end
end
end
diff --git a/lib/net/ssh/transport/kex/curve25519_sha256.rb b/lib/net/ssh/transport/kex/curve25519_sha256.rb
new file mode 100644
index 0000000..9aeba85
--- /dev/null
+++ b/lib/net/ssh/transport/kex/curve25519_sha256.rb
@@ -0,0 +1,38 @@
+gem 'x25519' # raise if the gem x25519 is not installed
+
+require 'x25519'
+require 'net/ssh/transport/constants'
+require 'net/ssh/transport/kex/abstract5656'
+
+module Net
+ module SSH
+ module Transport
+ module Kex
+ # A key-exchange service implementing the "curve25519-sha256@libssh.org"
+ # key-exchange algorithm. (defined in https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves-06)
+ class Curve25519Sha256 < Abstract5656
+ def digester
+ OpenSSL::Digest::SHA256
+ end
+
+ private
+
+ def generate_key #:nodoc:
+ ::X25519::Scalar.generate
+ end
+
+ ## string Q_C, client's ephemeral public key octet string
+ def ecdh_public_key_bytes
+ ecdh.public_key.to_bytes
+ end
+
+ # compute shared secret from server's public key and client's private key
+ def compute_shared_secret(server_ecdh_pubkey)
+ pk = ::X25519::MontgomeryU.new(server_ecdh_pubkey)
+ OpenSSL::BN.new(ecdh.diffie_hellman(pk).to_bytes, 2)
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb b/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb
new file mode 100644
index 0000000..45ce19a
--- /dev/null
+++ b/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb
@@ -0,0 +1,30 @@
+module Net
+ module SSH
+ module Transport
+ module Kex
+ # Loads Curve25519Sha256 support which requires optinal dependencies
+ module Curve25519Sha256Loader
+ begin
+ require 'net/ssh/transport/kex/curve25519_sha256'
+ LOADED = true
+ ERROR = nil
+ rescue LoadError => e
+ ERROR = e
+ LOADED = false
+ end
+
+ def self.raiseUnlessLoaded(message)
+ description = ERROR.is_a?(LoadError) ? dependenciesRequiredForX25519 : ''
+ description << "#{ERROR.class} : \"#{ERROR.message}\"\n" if ERROR
+ raise NotImplementedError, "#{message}\n#{description}" unless LOADED
+ end
+
+ def self.dependenciesRequiredForX25519
+ result = "net-ssh requires the following gems for x25519 support:\n"
+ result << " * x25519\n"
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/net-ssh.gemspec b/net-ssh.gemspec
index 8cdc4ef..36fa542 100644
--- a/net-ssh.gemspec
+++ b/net-ssh.gemspec
@@ -1,4 +1,3 @@
-
require_relative 'lib/net/ssh/version'
Gem::Specification.new do |spec|
@@ -34,10 +33,10 @@ Gem::Specification.new do |spec|
unless ENV['NET_SSH_NO_ED25519']
spec.add_development_dependency("bcrypt_pbkdf", "~> 1.0") unless RUBY_PLATFORM == "java"
spec.add_development_dependency("ed25519", "~> 1.2")
+ spec.add_development_dependency('x25519') unless RUBY_PLATFORM == 'java'
end
spec.add_development_dependency "bundler", ">= 1.17"
-
spec.add_development_dependency "minitest", "~> 5.10"
spec.add_development_dependency "mocha", ">= 1.2.1"
spec.add_development_dependency "rake", "~> 12.0"
diff --git a/test/transport/kex/test_curve25519_sha256.rb b/test/transport/kex/test_curve25519_sha256.rb
new file mode 100644
index 0000000..8177a38
--- /dev/null
+++ b/test/transport/kex/test_curve25519_sha256.rb
@@ -0,0 +1,156 @@
+unless ENV['NET_SSH_NO_ED25519']
+ require_relative '../../common'
+ require 'transport/kex/test_diffie_hellman_group1_sha1'
+ require 'net/ssh/transport/kex/curve25519_sha256_loader'
+ require 'ostruct'
+
+ module Transport
+ module Kex
+ class TestCurve25519Sha256 < NetSSHTest
+ include Net::SSH::Transport::Constants
+
+ def setup
+ raise 'No X25519 set NET_SSH_NO_ED25519 to ignore this test' unless Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
+
+ @ecdh = @algorithms = @connection = @server_key =
+ @packet_data = @shared_secret = nil
+ end
+
+ def test_exchange_keys_should_return_expected_results_when_successful
+ result = exchange!
+ assert_equal session_id, result[:session_id]
+ assert_equal server_host_key.to_blob, result[:server_key].to_blob
+ assert_equal shared_secret, result[:shared_secret]
+ assert_equal digester, result[:hashing_algorithm]
+ end
+
+ def test_exchange_keys_with_unverifiable_host_should_raise_exception
+ connection.verifier { false }
+ assert_raises(Net::SSH::Exception) { exchange! }
+ end
+
+ def test_exchange_keys_with_signature_key_type_mismatch_should_raise_exception
+ assert_raises(Net::SSH::Exception) { exchange! key_type: 'ssh-dss' }
+ end
+
+ def test_exchange_keys_with_host_key_type_mismatch_should_raise_exception
+ algorithms host_key: 'ssh-dss'
+ assert_raises(Net::SSH::Exception) { exchange! key_type: 'ssh-dss' }
+ end
+
+ def test_exchange_keys_when_server_signature_could_not_be_verified_should_raise_exception
+ @signature = '1234567890'
+ assert_raises(Net::SSH::Exception) { exchange! }
+ end
+
+ def test_exchange_keys_should_pass_expected_parameters_to_host_key_verifier
+ verified = false
+ connection.verifier do |data|
+ verified = true
+ assert_equal server_host_key.to_blob, data[:key].to_blob
+
+ blob = b(:key, data[:key]).to_s
+ fingerprint = "SHA256:#{Base64.encode64(OpenSSL::Digest.digest('SHA256', blob)).chomp.gsub(/=+\z/, '')}"
+
+ assert_equal blob, data[:key_blob]
+ assert_equal fingerprint, data[:fingerprint]
+ assert_equal connection, data[:session]
+
+ true
+ end
+
+ assert_nothing_raised { exchange! }
+ assert verified
+ end
+
+ private
+
+ def digester
+ OpenSSL::Digest::SHA256
+ end
+
+ def subject
+ Net::SSH::Transport::Kex::Curve25519Sha256
+ end
+
+ def key_type
+ 'ecdsa-sha2-nistp256'
+ end
+
+ def exchange!(options = {})
+ connection.expect do |t, buffer|
+ assert_equal KEXECDH_INIT, buffer.type
+ assert_equal ecdh.ecdh.public_key.to_bytes, buffer.read_string
+ t.return(KEXECDH_REPLY,
+ :string, b(:key, server_host_key),
+ :string, server_ecdh_pubkey.to_bytes,
+ :string, b(:string, options[:key_type] || key_type,
+ :string, signature))
+ connection.expect do |t2, buffer2|
+ assert_equal NEWKEYS, buffer2.type
+ t2.return(NEWKEYS)
+ end
+ end
+ ecdh.exchange_keys
+ end
+
+ def ecdh
+ @ecdh ||= subject.new(algorithms, connection, packet_data)
+ end
+
+ def algorithms(options = {})
+ @algorithms ||= OpenStruct.new(host_key: options[:server_host_key] || 'ecdsa-sha2-nistp256', host_key_format: options[:server_host_key] || 'ecdsa-sha2-nistp256')
+ end
+
+ def connection
+ @connection ||= MockTransport.new
+ end
+
+ def server_key
+ @server_key ||= ::X25519::Scalar.generate
+ end
+
+ def server_host_key
+ @server_host_key ||= OpenSSL::PKey::EC.new('prime256v1').generate_key
+ end
+
+ def packet_data
+ @packet_data ||= { client_version_string: 'client version string',
+ server_version_string: 'server version string',
+ server_algorithm_packet: 'server algorithm packet',
+ client_algorithm_packet: 'client algorithm packet' }
+ end
+
+ def server_ecdh_pubkey
+ @server_ecdh_pubkey ||= server_key.public_key
+ end
+
+ def shared_secret
+ @shared_secret ||= OpenSSL::BN.new(ecdh.ecdh.diffie_hellman(server_ecdh_pubkey).to_bytes, 2)
+ end
+
+ def session_id
+ @session_id ||= begin
+ buffer = Net::SSH::Buffer.from(:string, packet_data[:client_version_string],
+ :string, packet_data[:server_version_string],
+ :string, packet_data[:client_algorithm_packet],
+ :string, packet_data[:server_algorithm_packet],
+ :string, Net::SSH::Buffer.from(:key, server_host_key),
+ :string, ecdh.ecdh.public_key.to_bytes,
+ :string, server_ecdh_pubkey.to_bytes,
+ :bignum, shared_secret)
+ digester.digest(buffer.to_s)
+ end
+ end
+
+ def signature
+ @signature ||= server_host_key.ssh_do_sign(session_id)
+ end
+
+ def b(*args)
+ Net::SSH::Buffer.from(*args)
+ end
+ end
+ end
+ end
+end \ No newline at end of file
diff --git a/test/transport/test_algorithms.rb b/test/transport/test_algorithms.rb
index 8ba6a68..eb91887 100644
--- a/test/transport/test_algorithms.rb
+++ b/test/transport/test_algorithms.rb
@@ -19,7 +19,7 @@ module Transport
def test_constructor_should_build_default_list_of_preferred_algorithms
assert_equal ed_ec_host_keys + %w[ssh-rsa-cert-v01@openssh.com ssh-rsa-cert-v00@openssh.com ssh-rsa], algorithms[:host_key]
- assert_equal ec_kex + %w[diffie-hellman-group-exchange-sha256 diffie-hellman-group14-sha1], algorithms[:kex]
+ assert_equal x25519_kex + ec_kex + %w[diffie-hellman-group-exchange-sha256 diffie-hellman-group14-sha1], algorithms[:kex]
assert_equal %w[aes256-ctr aes192-ctr aes128-ctr], algorithms[:encryption]
assert_equal %w[hmac-sha2-512 hmac-sha2-256 hmac-sha1], algorithms[:hmac]
assert_equal %w[none zlib@openssh.com zlib], algorithms[:compression]
@@ -28,7 +28,7 @@ module Transport
def test_constructor_should_build_complete_list_of_algorithms_with_append_all_supported_algorithms
assert_equal ed_ec_host_keys + %w[ssh-rsa-cert-v01@openssh.com ssh-rsa-cert-v00@openssh.com ssh-rsa ssh-dss], algorithms(append_all_supported_algorithms: true)[:host_key]
- assert_equal ec_kex + %w[diffie-hellman-group-exchange-sha256 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha1 diffie-hellman-group1-sha1], algorithms(append_all_supported_algorithms: true)[:kex]
+ assert_equal x25519_kex + ec_kex + %w[diffie-hellman-group-exchange-sha256 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha1 diffie-hellman-group1-sha1], algorithms(append_all_supported_algorithms: true)[:kex]
assert_equal %w[aes256-ctr aes192-ctr aes128-ctr aes256-cbc aes192-cbc aes128-cbc rijndael-cbc@lysator.liu.se blowfish-ctr blowfish-cbc cast128-ctr cast128-cbc 3des-ctr 3des-cbc idea-cbc none], algorithms(append_all_supported_algorithms: true)[:encryption]
assert_equal %w[hmac-sha2-512 hmac-sha2-256 hmac-sha1 hmac-sha2-512-96 hmac-sha2-256-96 hmac-sha1-96 hmac-ripemd160 hmac-ripemd160@openssh.com hmac-md5 hmac-md5-96 none], algorithms(append_all_supported_algorithms: true)[:hmac]
assert_equal %w[none zlib@openssh.com zlib], algorithms(append_all_supported_algorithms: true)[:compression]
@@ -81,13 +81,21 @@ module Transport
%w[ecdh-sha2-nistp521 ecdh-sha2-nistp384 ecdh-sha2-nistp256]
end
+ def x25519_kex
+ if Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
+ %w[curve25519-sha256 curve22519-sha256@libssh.org]
+ else
+ []
+ end
+ end
+
def test_constructor_with_preferred_kex_should_put_preferred_kex_first
- assert_equal %w[diffie-hellman-group1-sha1] + ec_kex + %w[diffie-hellman-group-exchange-sha256 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha1],
+ assert_equal %w[diffie-hellman-group1-sha1] + x25519_kex + ec_kex + %w[diffie-hellman-group-exchange-sha256 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha1],
algorithms(kex: "diffie-hellman-group1-sha1", append_all_supported_algorithms: true)[:kex]
end
def test_constructor_with_unrecognized_kex_should_not_raise_exception
- assert_equal %w[diffie-hellman-group1-sha1] + ec_kex + %w[diffie-hellman-group-exchange-sha256 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha1],
+ assert_equal %w[diffie-hellman-group1-sha1] + x25519_kex + ec_kex + %w[diffie-hellman-group-exchange-sha256 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha1],
algorithms(kex: %w[bogus diffie-hellman-group1-sha1], append_all_supported_algorithms: true)[:kex]
end
@@ -351,7 +359,7 @@ module Transport
def assert_kexinit(buffer, options={})
assert_equal KEXINIT, buffer.type
assert_equal 16, buffer.read(16).length
- assert_equal options[:kex] || (ec_kex + %w[diffie-hellman-group-exchange-sha256 diffie-hellman-group14-sha1]).join(','), buffer.read_string
+ assert_equal options[:kex] || (x25519_kex + ec_kex + %w[diffie-hellman-group-exchange-sha256 diffie-hellman-group14-sha1]).join(','), buffer.read_string
assert_equal options[:host_key] || (ed_ec_host_keys + %w[ssh-rsa-cert-v01@openssh.com ssh-rsa-cert-v00@openssh.com ssh-rsa]).join(','), buffer.read_string
assert_equal options[:encryption_client] || 'aes256-ctr,aes192-ctr,aes128-ctr', buffer.read_string
assert_equal options[:encryption_server] || 'aes256-ctr,aes192-ctr,aes128-ctr', buffer.read_string