net-ssh 5.0.2 → 7.0.1

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 (122) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/config/rubocop_linter_action.yml +4 -0
  5. data/.github/workflows/ci-with-docker.yml +44 -0
  6. data/.github/workflows/ci.yml +87 -0
  7. data/.github/workflows/rubocop.yml +13 -0
  8. data/.gitignore +3 -0
  9. data/.rubocop.yml +19 -2
  10. data/.rubocop_todo.yml +623 -511
  11. data/CHANGES.txt +76 -0
  12. data/Dockerfile +27 -0
  13. data/Dockerfile.openssl3 +17 -0
  14. data/Gemfile +2 -0
  15. data/Gemfile.noed25519 +2 -0
  16. data/Manifest +0 -1
  17. data/README.md +293 -0
  18. data/Rakefile +6 -2
  19. data/appveyor.yml +4 -2
  20. data/docker-compose.yml +23 -0
  21. data/lib/net/ssh/authentication/agent.rb +36 -14
  22. data/lib/net/ssh/authentication/certificate.rb +19 -7
  23. data/lib/net/ssh/authentication/constants.rb +0 -1
  24. data/lib/net/ssh/authentication/ed25519.rb +83 -50
  25. data/lib/net/ssh/authentication/ed25519_loader.rb +5 -8
  26. data/lib/net/ssh/authentication/key_manager.rb +74 -33
  27. data/lib/net/ssh/authentication/methods/abstract.rb +12 -3
  28. data/lib/net/ssh/authentication/methods/hostbased.rb +3 -5
  29. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +5 -3
  30. data/lib/net/ssh/authentication/methods/none.rb +6 -9
  31. data/lib/net/ssh/authentication/methods/password.rb +2 -3
  32. data/lib/net/ssh/authentication/methods/publickey.rb +58 -16
  33. data/lib/net/ssh/authentication/pageant.rb +97 -97
  34. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +2 -3
  35. data/lib/net/ssh/authentication/session.rb +27 -23
  36. data/lib/net/ssh/buffer.rb +91 -40
  37. data/lib/net/ssh/buffered_io.rb +24 -26
  38. data/lib/net/ssh/config.rb +99 -53
  39. data/lib/net/ssh/connection/channel.rb +101 -87
  40. data/lib/net/ssh/connection/constants.rb +0 -4
  41. data/lib/net/ssh/connection/event_loop.rb +30 -25
  42. data/lib/net/ssh/connection/keepalive.rb +12 -12
  43. data/lib/net/ssh/connection/session.rb +115 -111
  44. data/lib/net/ssh/connection/term.rb +56 -58
  45. data/lib/net/ssh/errors.rb +12 -12
  46. data/lib/net/ssh/key_factory.rb +108 -22
  47. data/lib/net/ssh/known_hosts.rb +120 -36
  48. data/lib/net/ssh/loggable.rb +10 -11
  49. data/lib/net/ssh/packet.rb +1 -1
  50. data/lib/net/ssh/prompt.rb +9 -11
  51. data/lib/net/ssh/proxy/command.rb +1 -2
  52. data/lib/net/ssh/proxy/errors.rb +2 -4
  53. data/lib/net/ssh/proxy/http.rb +18 -20
  54. data/lib/net/ssh/proxy/https.rb +8 -10
  55. data/lib/net/ssh/proxy/jump.rb +8 -10
  56. data/lib/net/ssh/proxy/socks4.rb +2 -4
  57. data/lib/net/ssh/proxy/socks5.rb +3 -6
  58. data/lib/net/ssh/service/forward.rb +9 -8
  59. data/lib/net/ssh/test/channel.rb +24 -26
  60. data/lib/net/ssh/test/extensions.rb +37 -35
  61. data/lib/net/ssh/test/kex.rb +6 -8
  62. data/lib/net/ssh/test/local_packet.rb +0 -2
  63. data/lib/net/ssh/test/packet.rb +3 -3
  64. data/lib/net/ssh/test/remote_packet.rb +6 -8
  65. data/lib/net/ssh/test/script.rb +25 -27
  66. data/lib/net/ssh/test/socket.rb +12 -15
  67. data/lib/net/ssh/test.rb +12 -12
  68. data/lib/net/ssh/transport/algorithms.rb +177 -118
  69. data/lib/net/ssh/transport/cipher_factory.rb +34 -50
  70. data/lib/net/ssh/transport/constants.rb +13 -9
  71. data/lib/net/ssh/transport/ctr.rb +8 -14
  72. data/lib/net/ssh/transport/hmac/abstract.rb +20 -5
  73. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  74. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  75. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  76. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  77. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  78. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  79. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  80. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  81. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  82. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  83. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  84. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  85. data/lib/net/ssh/transport/hmac.rb +13 -11
  86. data/lib/net/ssh/transport/identity_cipher.rb +11 -13
  87. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  88. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  89. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  90. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  91. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +5 -19
  92. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  93. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +30 -139
  94. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +1 -8
  95. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  96. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +20 -81
  97. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +5 -4
  98. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +5 -4
  99. data/lib/net/ssh/transport/kex.rb +15 -10
  100. data/lib/net/ssh/transport/key_expander.rb +7 -8
  101. data/lib/net/ssh/transport/openssl.rb +149 -111
  102. data/lib/net/ssh/transport/packet_stream.rb +53 -22
  103. data/lib/net/ssh/transport/server_version.rb +17 -16
  104. data/lib/net/ssh/transport/session.rb +35 -11
  105. data/lib/net/ssh/transport/state.rb +44 -44
  106. data/lib/net/ssh/verifiers/accept_new.rb +7 -2
  107. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +1 -2
  108. data/lib/net/ssh/verifiers/always.rb +10 -4
  109. data/lib/net/ssh/verifiers/never.rb +4 -2
  110. data/lib/net/ssh/version.rb +2 -2
  111. data/lib/net/ssh.rb +17 -9
  112. data/net-ssh-public_cert.pem +18 -19
  113. data/net-ssh.gemspec +9 -7
  114. data/support/ssh_tunnel_bug.rb +3 -3
  115. data.tar.gz.sig +0 -0
  116. metadata +65 -41
  117. metadata.gz.sig +0 -0
  118. data/.travis.yml +0 -52
  119. data/Gemfile.noed25519.lock +0 -41
  120. data/README.rdoc +0 -169
  121. data/lib/net/ssh/ruby_compat.rb +0 -13
  122. data/support/arcfour_check.rb +0 -20
@@ -0,0 +1,130 @@
1
+ require 'net/ssh/buffer'
2
+ require 'net/ssh/errors'
3
+ require 'net/ssh/loggable'
4
+ require 'net/ssh/transport/openssl'
5
+ require 'net/ssh/transport/constants'
6
+
7
+ module Net
8
+ module SSH
9
+ module Transport
10
+ module Kex
11
+ # Abstract class that implement Diffie-Hellman Key Exchange
12
+ # See https://tools.ietf.org/html/rfc4253#page-21
13
+ class Abstract
14
+ include Loggable
15
+ include Constants
16
+
17
+ attr_reader :algorithms
18
+ attr_reader :connection
19
+ attr_reader :data
20
+ attr_reader :dh
21
+
22
+ # Create a new instance of the Diffie-Hellman Key Exchange algorithm.
23
+ # The Diffie-Hellman (DH) key exchange provides a shared secret that
24
+ # cannot be determined by either party alone. The key exchange is
25
+ # combined with a signature with the host key to provide host
26
+ # authentication.
27
+ def initialize(algorithms, connection, data)
28
+ @algorithms = algorithms
29
+ @connection = connection
30
+
31
+ @data = data.dup
32
+ @dh = generate_key
33
+ @logger = @data.delete(:logger)
34
+ end
35
+
36
+ # Perform the key-exchange for the given session, with the given
37
+ # data. This method will return a hash consisting of the
38
+ # following keys:
39
+ #
40
+ # * :session_id
41
+ # * :server_key
42
+ # * :shared_secret
43
+ # * :hashing_algorithm
44
+ #
45
+ # The caller is expected to be able to understand how to use these
46
+ # deliverables.
47
+ def exchange_keys
48
+ result = send_kexinit
49
+ verify_server_key(result[:server_key])
50
+ session_id = verify_signature(result)
51
+ confirm_newkeys
52
+
53
+ {
54
+ session_id: session_id,
55
+ server_key: result[:server_key],
56
+ shared_secret: result[:shared_secret],
57
+ hashing_algorithm: digester
58
+ }
59
+ end
60
+
61
+ def digester
62
+ raise NotImplementedError, 'abstract class: digester not implemented'
63
+ end
64
+
65
+ private
66
+
67
+ def matching?(key_ssh_type, host_key_alg)
68
+ return true if key_ssh_type == host_key_alg
69
+ return true if key_ssh_type == 'ssh-rsa' && ['rsa-sha2-512', 'rsa-sha2-256'].include?(host_key_alg)
70
+ end
71
+
72
+ # Verify that the given key is of the expected type, and that it
73
+ # really is the key for the session's host. Raise Net::SSH::Exception
74
+ # if it is not.
75
+ def verify_server_key(key) # :nodoc:
76
+ unless matching?(key.ssh_type, algorithms.host_key)
77
+ raise Net::SSH::Exception, "host key algorithm mismatch '#{key.ssh_type}' != '#{algorithms.host_key}'"
78
+ end
79
+
80
+ blob, fingerprint = generate_key_fingerprint(key)
81
+
82
+ unless connection.host_key_verifier.verify(key: key, key_blob: blob, fingerprint: fingerprint, session: connection)
83
+ raise Net::SSH::Exception, 'host key verification failed'
84
+ end
85
+ end
86
+
87
+ def generate_key_fingerprint(key)
88
+ blob = Net::SSH::Buffer.from(:key, key).to_s
89
+
90
+ fingerprint = Net::SSH::Authentication::PubKeyFingerprint.fingerprint(blob, @connection.options[:fingerprint_hash] || 'SHA256')
91
+
92
+ [blob, fingerprint]
93
+ rescue StandardError => e
94
+ [nil, "(could not generate fingerprint: #{e.message})"]
95
+ end
96
+
97
+ # Verify the signature that was received. Raise Net::SSH::Exception
98
+ # if the signature could not be verified. Otherwise, return the new
99
+ # session-id.
100
+ def verify_signature(result) # :nodoc:
101
+ response = build_signature_buffer(result)
102
+
103
+ hash = digester.digest(response.to_s)
104
+
105
+ server_key = result[:server_key]
106
+ server_sig = result[:server_sig]
107
+ unless connection.host_key_verifier.verify_signature { server_key.ssh_do_verify(server_sig, hash, host_key: algorithms.host_key) }
108
+ raise Net::SSH::Exception, 'could not verify server signature'
109
+ end
110
+
111
+ hash
112
+ end
113
+
114
+ # Send the NEWKEYS message, and expect the NEWKEYS message in
115
+ # reply.
116
+ def confirm_newkeys # :nodoc:
117
+ # send own NEWKEYS message first (the wodSSHServer won't send first)
118
+ response = Net::SSH::Buffer.new
119
+ response.write_byte(NEWKEYS)
120
+ connection.send_message(response)
121
+
122
+ # wait for the server's NEWKEYS message
123
+ buffer = connection.next_message
124
+ raise Net::SSH::Exception, 'expected NEWKEYS' unless buffer.type == NEWKEYS
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
@@ -0,0 +1,72 @@
1
+ require 'net/ssh/transport/kex/abstract'
2
+
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
7
+ # Implement key-exchange algorithm from Elliptic Curve Algorithm Integration
8
+ # in the Secure Shell Transport Layer (RFC 5656)
9
+ class Abstract5656 < Abstract
10
+ alias ecdh dh
11
+
12
+ def curve_name
13
+ raise NotImplementedError, 'abstract class: curve_name not implemented'
14
+ end
15
+
16
+ private
17
+
18
+ def get_message_types
19
+ [KEXECDH_INIT, KEXECDH_REPLY]
20
+ end
21
+
22
+ def build_signature_buffer(result)
23
+ response = Net::SSH::Buffer.new
24
+ response.write_string data[:client_version_string],
25
+ data[:server_version_string],
26
+ data[:client_algorithm_packet],
27
+ data[:server_algorithm_packet],
28
+ result[:key_blob],
29
+ ecdh_public_key_bytes,
30
+ result[:server_ecdh_pubkey]
31
+ response.write_bignum result[:shared_secret]
32
+ response
33
+ end
34
+
35
+ def send_kexinit # :nodoc:
36
+ init, reply = get_message_types
37
+
38
+ # send the KEXECDH_INIT message
39
+ ## byte SSH_MSG_KEX_ECDH_INIT
40
+ ## string Q_C, client's ephemeral public key octet string
41
+ buffer = Net::SSH::Buffer.from(:byte, init, :mstring, ecdh_public_key_bytes)
42
+ connection.send_message(buffer)
43
+
44
+ # expect the following KEXECDH_REPLY message
45
+ ## byte SSH_MSG_KEX_ECDH_REPLY
46
+ ## string K_S, server's public host key
47
+ ## string Q_S, server's ephemeral public key octet string
48
+ ## string the signature on the exchange hash
49
+ buffer = connection.next_message
50
+ raise Net::SSH::Exception, 'expected REPLY' unless buffer.type == reply
51
+
52
+ result = {}
53
+ result[:key_blob] = buffer.read_string
54
+ result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
55
+ result[:server_ecdh_pubkey] = buffer.read_string
56
+ result[:shared_secret] = compute_shared_secret(result[:server_ecdh_pubkey])
57
+
58
+ sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
59
+ sig_type = sig_buffer.read_string
60
+ if sig_type != algorithms.host_key_format
61
+ raise Net::SSH::Exception, "host key algorithm mismatch for signature '#{sig_type}' != '#{algorithms.host_key_format}'"
62
+ end
63
+
64
+ result[:server_sig] = sig_buffer.read_string
65
+
66
+ result
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,39 @@
1
+ gem 'x25519' # raise if the gem x25519 is not installed
2
+
3
+ require 'x25519'
4
+
5
+ require 'net/ssh/transport/constants'
6
+ require 'net/ssh/transport/kex/abstract5656'
7
+
8
+ module Net
9
+ module SSH
10
+ module Transport
11
+ module Kex
12
+ # A key-exchange service implementing the "curve25519-sha256@libssh.org"
13
+ # key-exchange algorithm. (defined in https://tools.ietf.org/html/draft-ietf-curdle-ssh-curves-06)
14
+ class Curve25519Sha256 < Abstract5656
15
+ def digester
16
+ OpenSSL::Digest::SHA256
17
+ end
18
+
19
+ private
20
+
21
+ def generate_key # :nodoc:
22
+ ::X25519::Scalar.generate
23
+ end
24
+
25
+ ## string Q_C, client's ephemeral public key octet string
26
+ def ecdh_public_key_bytes
27
+ ecdh.public_key.to_bytes
28
+ end
29
+
30
+ # compute shared secret from server's public key and client's private key
31
+ def compute_shared_secret(server_ecdh_pubkey)
32
+ pk = ::X25519::MontgomeryU.new(server_ecdh_pubkey)
33
+ OpenSSL::BN.new(ecdh.diffie_hellman(pk).to_bytes, 2)
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,30 @@
1
+ module Net
2
+ module SSH
3
+ module Transport
4
+ module Kex
5
+ # Loads Curve25519Sha256 support which requires optinal dependencies
6
+ module Curve25519Sha256Loader
7
+ begin
8
+ require 'net/ssh/transport/kex/curve25519_sha256'
9
+ LOADED = true
10
+ ERROR = nil
11
+ rescue LoadError => e
12
+ ERROR = e
13
+ LOADED = false
14
+ end
15
+
16
+ def self.raiseUnlessLoaded(message)
17
+ description = ERROR.is_a?(LoadError) ? dependenciesRequiredForX25519 : ''
18
+ description << "#{ERROR.class} : \"#{ERROR.message}\"\n" if ERROR
19
+ raise NotImplementedError, "#{message}\n#{description}" unless LOADED
20
+ end
21
+
22
+ def self.dependenciesRequiredForX25519
23
+ result = "net-ssh requires the following gems for x25519 support:\n"
24
+ result << " * x25519\n"
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -1,16 +1,12 @@
1
1
  require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
2
 
3
- module Net
4
- module SSH
5
- module Transport
3
+ module Net
4
+ module SSH
5
+ module Transport
6
6
  module Kex
7
-
8
7
  # A key-exchange service implementing the "diffie-hellman-group14-sha1"
9
8
  # key-exchange algorithm. (defined in RFC 4253)
10
9
  class DiffieHellmanGroup14SHA1 < DiffieHellmanGroup1SHA1
11
- include Loggable
12
- include Constants
13
-
14
10
  # The value of 'P', as a string, in hexadecimal
15
11
  P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
16
12
  "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
@@ -28,22 +24,12 @@ module Net
28
24
  "B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" +
29
25
  "3995497C" "EA956AE5" "15D22618" "98FA0510" +
30
26
  "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF"
31
-
27
+
32
28
  # The radix in which P_s represents the value of P
33
29
  P_r = 16
34
-
30
+
35
31
  # The group constant
36
32
  G = 2
37
-
38
- private
39
-
40
- def get_p
41
- OpenSSL::BN.new(P_s, P_r)
42
- end
43
-
44
- def get_g
45
- G
46
- end
47
33
  end
48
34
  end
49
35
  end
@@ -0,0 +1,11 @@
1
+ require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
2
+
3
+ module Net::SSH::Transport::Kex
4
+ # A key-exchange service implementing the "diffie-hellman-group14-sha256"
5
+ # key-exchange algorithm.
6
+ class DiffieHellmanGroup14SHA256 < DiffieHellmanGroup14SHA1
7
+ def digester
8
+ OpenSSL::Digest::SHA256
9
+ end
10
+ end
11
+ end
@@ -1,20 +1,12 @@
1
- require 'net/ssh/buffer'
2
- require 'net/ssh/errors'
3
- require 'net/ssh/loggable'
4
- require 'net/ssh/transport/openssl'
5
- require 'net/ssh/transport/constants'
1
+ require 'net/ssh/transport/kex/abstract'
6
2
 
7
3
  module Net
8
4
  module SSH
9
5
  module Transport
10
6
  module Kex
11
-
12
7
  # A key-exchange service implementing the "diffie-hellman-group1-sha1"
13
8
  # key-exchange algorithm.
14
- class DiffieHellmanGroup1SHA1
15
- include Loggable
16
- include Constants
17
-
9
+ class DiffieHellmanGroup1SHA1 < Abstract
18
10
  # The value of 'P', as a string, in hexadecimal
19
11
  P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
20
12
  "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
@@ -31,67 +23,18 @@ module Net
31
23
  # The group constant
32
24
  G = 2
33
25
 
34
- attr_reader :p
35
- attr_reader :g
36
- attr_reader :digester
37
- attr_reader :algorithms
38
- attr_reader :connection
39
- attr_reader :data
40
- attr_reader :dh
41
-
42
- # Create a new instance of the DiffieHellmanGroup1SHA1 algorithm.
43
- # The data is a Hash of symbols representing information
44
- # required by this algorithm, which was acquired during earlier
45
- # processing.
46
- def initialize(algorithms, connection, data)
47
- @p = get_p
48
- @g = get_g
49
-
50
- @digester = OpenSSL::Digest::SHA1
51
- @algorithms = algorithms
52
- @connection = connection
53
-
54
- @data = data.dup
55
- @dh = generate_key
56
- @logger = @data.delete(:logger)
57
- end
58
-
59
- # Perform the key-exchange for the given session, with the given
60
- # data. This method will return a hash consisting of the
61
- # following keys:
62
- #
63
- # * :session_id
64
- # * :server_key
65
- # * :shared_secret
66
- # * :hashing_algorithm
67
- #
68
- # The caller is expected to be able to understand how to use these
69
- # deliverables.
70
- def exchange_keys
71
- result = send_kexinit
72
- verify_server_key(result[:server_key])
73
- session_id = verify_signature(result)
74
- confirm_newkeys
75
-
76
- return { session_id: session_id,
77
- server_key: result[:server_key],
78
- shared_secret: result[:shared_secret],
79
- hashing_algorithm: digester }
26
+ def digester
27
+ OpenSSL::Digest::SHA1
80
28
  end
81
29
 
82
30
  private
83
31
 
84
- def get_p
85
- OpenSSL::BN.new(P_s, P_r)
86
- end
87
-
88
- def get_g
89
- G
90
- end
91
-
92
- # Returns the DH key parameters for the current connection.
32
+ # Returns the DH key parameters for the current connection. [p, q]
93
33
  def get_parameters
94
- [p, g]
34
+ [
35
+ OpenSSL::BN.new(self.class::P_s, self.class::P_r),
36
+ self.class::G
37
+ ]
95
38
  end
96
39
 
97
40
  # Returns the INIT/REPLY constants used by this algorithm.
@@ -116,26 +59,26 @@ module Net
116
59
 
117
60
  # Generate a DH key with a private key consisting of the given
118
61
  # number of bytes.
119
- def generate_key #:nodoc:
120
- dh = OpenSSL::PKey::DH.new
121
-
122
- if dh.respond_to?(:set_pqg)
123
- p, g = get_parameters
124
- dh.set_pqg(p, nil, g)
62
+ def generate_key # :nodoc:
63
+ p, g = get_parameters
64
+
65
+ asn1 = OpenSSL::ASN1::Sequence(
66
+ [
67
+ OpenSSL::ASN1::Integer(p),
68
+ OpenSSL::ASN1::Integer(g)
69
+ ]
70
+ )
71
+
72
+ dh_params = OpenSSL::PKey::DH.new(asn1.to_der)
73
+ # XXX No private key size check! In theory the latter call should work but fails on OpenSSL 3.0 as
74
+ # dh_paramgen_subprime_len is now reserved for DHX algorithm
75
+ # key = OpenSSL::PKey.generate_key(dh_params, "dh_paramgen_subprime_len" => data[:need_bytes]/8)
76
+ if OpenSSL::PKey.respond_to?(:generate_key)
77
+ OpenSSL::PKey.generate_key(dh_params)
125
78
  else
126
- dh.p, dh.g = get_parameters
127
- end
128
-
129
- dh.generate_key!
130
- until dh.valid? && dh.priv_key.num_bytes == data[:need_bytes]
131
- if dh.respond_to?(:set_key)
132
- dh.set_key(nil, OpenSSL::BN.rand(data[:need_bytes] * 8))
133
- else
134
- dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
135
- end
136
- dh.generate_key!
79
+ dh_params.generate_key!
80
+ dh_params
137
81
  end
138
- dh
139
82
  end
140
83
 
141
84
  # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
@@ -143,7 +86,7 @@ module Net
143
86
  #
144
87
  # Parse the buffer from a KEXDH_REPLY message, returning a hash of
145
88
  # the extracted values.
146
- def send_kexinit #:nodoc:
89
+ def send_kexinit # :nodoc:
147
90
  init, reply = get_message_types
148
91
 
149
92
  # send the KEXDH_INIT message
@@ -165,66 +108,14 @@ module Net
165
108
  sig_type = sig_buffer.read_string
166
109
  if sig_type != algorithms.host_key_format
167
110
  raise Net::SSH::Exception,
168
- "host key algorithm mismatch for signature " +
169
- "'#{sig_type}' != '#{algorithms.host_key_format}'"
111
+ "host key algorithm mismatch for signature " +
112
+ "'#{sig_type}' != '#{algorithms.host_key_format}'"
170
113
  end
171
114
  result[:server_sig] = sig_buffer.read_string
172
115
 
173
116
  return result
174
117
  end
175
-
176
- # Verify that the given key is of the expected type, and that it
177
- # really is the key for the session's host. Raise Net::SSH::Exception
178
- # if it is not.
179
- def verify_server_key(key) #:nodoc:
180
- if key.ssh_type != algorithms.host_key
181
- raise Net::SSH::Exception,
182
- "host key algorithm mismatch " +
183
- "'#{key.ssh_type}' != '#{algorithms.host_key}'"
184
- end
185
-
186
- blob, fingerprint = generate_key_fingerprint(key)
187
-
188
- raise Net::SSH::Exception, "host key verification failed" unless connection.host_key_verifier.verify(key: key, key_blob: blob, fingerprint: fingerprint, session: connection)
189
- end
190
-
191
- def generate_key_fingerprint(key)
192
- blob = Net::SSH::Buffer.from(:key, key).to_s
193
-
194
- fingerprint = Net::SSH::Authentication::PubKeyFingerprint.fingerprint(blob, @connection.options[:fingerprint_hash] || 'SHA256')
195
-
196
- [blob, fingerprint]
197
- rescue ::Exception => e
198
- [nil, "(could not generate fingerprint: #{e.message})"]
199
- end
200
-
201
- # Verify the signature that was received. Raise Net::SSH::Exception
202
- # if the signature could not be verified. Otherwise, return the new
203
- # session-id.
204
- def verify_signature(result) #:nodoc:
205
- response = build_signature_buffer(result)
206
-
207
- hash = @digester.digest(response.to_s)
208
-
209
- raise Net::SSH::Exception, "could not verify server signature" unless result[:server_key].ssh_do_verify(result[:server_sig], hash)
210
-
211
- return hash
212
- end
213
-
214
- # Send the NEWKEYS message, and expect the NEWKEYS message in
215
- # reply.
216
- def confirm_newkeys #:nodoc:
217
- # send own NEWKEYS message first (the wodSSHServer won't send first)
218
- response = Net::SSH::Buffer.new
219
- response.write_byte(NEWKEYS)
220
- connection.send_message(response)
221
-
222
- # wait for the server's NEWKEYS message
223
- buffer = connection.next_message
224
- raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
225
- end
226
118
  end
227
-
228
119
  end
229
120
  end
230
121
  end
@@ -3,18 +3,12 @@ require 'net/ssh/transport/constants'
3
3
  require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
4
4
 
5
5
  module Net::SSH::Transport::Kex
6
-
7
6
  # A key-exchange service implementing the
8
7
  # "diffie-hellman-group-exchange-sha1" key-exchange algorithm.
9
8
  class DiffieHellmanGroupExchangeSHA1 < DiffieHellmanGroup1SHA1
10
9
  MINIMUM_BITS = 1024
11
10
  MAXIMUM_BITS = 8192
12
11
 
13
- KEXDH_GEX_GROUP = 31
14
- KEXDH_GEX_INIT = 32
15
- KEXDH_GEX_REPLY = 33
16
- KEXDH_GEX_REQUEST = 34
17
-
18
12
  private
19
13
 
20
14
  # Compute the number of bits needed for the given number of bytes.
@@ -40,7 +34,7 @@ module Net::SSH::Transport::Kex
40
34
 
41
35
  # request the DH key parameters for the given number of bits.
42
36
  buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, data[:minimum_dh_bits],
43
- :long, data[:need_bits], :long, MAXIMUM_BITS)
37
+ :long, data[:need_bits], :long, MAXIMUM_BITS)
44
38
  connection.send_message(buffer)
45
39
 
46
40
  buffer = connection.next_message
@@ -75,5 +69,4 @@ module Net::SSH::Transport::Kex
75
69
  response
76
70
  end
77
71
  end
78
-
79
72
  end
@@ -1,15 +1,11 @@
1
1
  require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
2
2
 
3
3
  module Net::SSH::Transport::Kex
4
- if defined?(OpenSSL::Digest::SHA256)
5
- # A key-exchange service implementing the
6
- # "diffie-hellman-group-exchange-sha256" key-exchange algorithm.
7
- class DiffieHellmanGroupExchangeSHA256 < DiffieHellmanGroupExchangeSHA1
8
- def initialize(*args)
9
- super(*args)
10
-
11
- @digester = OpenSSL::Digest::SHA256
12
- end
4
+ # A key-exchange service implementing the
5
+ # "diffie-hellman-group-exchange-sha256" key-exchange algorithm.
6
+ class DiffieHellmanGroupExchangeSHA256 < DiffieHellmanGroupExchangeSHA1
7
+ def digester
8
+ OpenSSL::Digest::SHA256
13
9
  end
14
10
  end
15
11
  end