net-ssh 4.2.0 → 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 (126) hide show
  1. checksums.yaml +5 -5
  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 +7 -0
  9. data/.rubocop.yml +19 -2
  10. data/.rubocop_todo.yml +619 -667
  11. data/CHANGES.txt +110 -1
  12. data/Dockerfile +27 -0
  13. data/Dockerfile.openssl3 +17 -0
  14. data/Gemfile +3 -7
  15. data/{Gemfile.norbnacl → Gemfile.noed25519} +3 -1
  16. data/Manifest +4 -5
  17. data/README.md +293 -0
  18. data/Rakefile +45 -29
  19. data/appveyor.yml +8 -6
  20. data/docker-compose.yml +23 -0
  21. data/lib/net/ssh/authentication/agent.rb +248 -223
  22. data/lib/net/ssh/authentication/certificate.rb +178 -164
  23. data/lib/net/ssh/authentication/constants.rb +17 -15
  24. data/lib/net/ssh/authentication/ed25519.rb +141 -116
  25. data/lib/net/ssh/authentication/ed25519_loader.rb +28 -28
  26. data/lib/net/ssh/authentication/key_manager.rb +79 -36
  27. data/lib/net/ssh/authentication/methods/abstract.rb +62 -47
  28. data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
  29. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +3 -3
  30. data/lib/net/ssh/authentication/methods/none.rb +16 -19
  31. data/lib/net/ssh/authentication/methods/password.rb +15 -16
  32. data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
  33. data/lib/net/ssh/authentication/pageant.rb +468 -465
  34. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  35. data/lib/net/ssh/authentication/session.rb +131 -122
  36. data/lib/net/ssh/buffer.rb +385 -332
  37. data/lib/net/ssh/buffered_io.rb +150 -151
  38. data/lib/net/ssh/config.rb +316 -239
  39. data/lib/net/ssh/connection/channel.rb +635 -613
  40. data/lib/net/ssh/connection/constants.rb +29 -29
  41. data/lib/net/ssh/connection/event_loop.rb +104 -95
  42. data/lib/net/ssh/connection/keepalive.rb +55 -51
  43. data/lib/net/ssh/connection/session.rb +614 -611
  44. data/lib/net/ssh/connection/term.rb +125 -123
  45. data/lib/net/ssh/errors.rb +101 -99
  46. data/lib/net/ssh/key_factory.rb +194 -108
  47. data/lib/net/ssh/known_hosts.rb +212 -134
  48. data/lib/net/ssh/loggable.rb +50 -49
  49. data/lib/net/ssh/packet.rb +83 -79
  50. data/lib/net/ssh/prompt.rb +51 -51
  51. data/lib/net/ssh/proxy/command.rb +105 -91
  52. data/lib/net/ssh/proxy/errors.rb +12 -10
  53. data/lib/net/ssh/proxy/http.rb +81 -81
  54. data/lib/net/ssh/proxy/https.rb +37 -36
  55. data/lib/net/ssh/proxy/jump.rb +49 -48
  56. data/lib/net/ssh/proxy/socks4.rb +2 -6
  57. data/lib/net/ssh/proxy/socks5.rb +14 -17
  58. data/lib/net/ssh/service/forward.rb +365 -362
  59. data/lib/net/ssh/test/channel.rb +145 -143
  60. data/lib/net/ssh/test/extensions.rb +131 -127
  61. data/lib/net/ssh/test/kex.rb +34 -32
  62. data/lib/net/ssh/test/local_packet.rb +46 -44
  63. data/lib/net/ssh/test/packet.rb +87 -84
  64. data/lib/net/ssh/test/remote_packet.rb +32 -30
  65. data/lib/net/ssh/test/script.rb +155 -155
  66. data/lib/net/ssh/test/socket.rb +49 -48
  67. data/lib/net/ssh/test.rb +82 -80
  68. data/lib/net/ssh/transport/algorithms.rb +433 -364
  69. data/lib/net/ssh/transport/cipher_factory.rb +95 -91
  70. data/lib/net/ssh/transport/constants.rb +32 -24
  71. data/lib/net/ssh/transport/ctr.rb +37 -15
  72. data/lib/net/ssh/transport/hmac/abstract.rb +81 -63
  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 +14 -12
  86. data/lib/net/ssh/transport/identity_cipher.rb +54 -52
  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 +33 -40
  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 +112 -217
  94. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -63
  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 +36 -90
  97. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  98. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  99. data/lib/net/ssh/transport/kex.rb +15 -12
  100. data/lib/net/ssh/transport/key_expander.rb +24 -21
  101. data/lib/net/ssh/transport/openssl.rb +158 -133
  102. data/lib/net/ssh/transport/packet_stream.rb +223 -191
  103. data/lib/net/ssh/transport/server_version.rb +55 -56
  104. data/lib/net/ssh/transport/session.rb +306 -259
  105. data/lib/net/ssh/transport/state.rb +178 -176
  106. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  107. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  108. data/lib/net/ssh/verifiers/always.rb +58 -0
  109. data/lib/net/ssh/verifiers/never.rb +19 -0
  110. data/lib/net/ssh/version.rb +55 -53
  111. data/lib/net/ssh.rb +47 -34
  112. data/net-ssh-public_cert.pem +18 -19
  113. data/net-ssh.gemspec +12 -11
  114. data/support/ssh_tunnel_bug.rb +5 -5
  115. data.tar.gz.sig +0 -0
  116. metadata +78 -73
  117. metadata.gz.sig +0 -0
  118. data/.travis.yml +0 -51
  119. data/Gemfile.norbnacl.lock +0 -41
  120. data/README.rdoc +0 -169
  121. data/lib/net/ssh/ruby_compat.rb +0 -24
  122. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  123. data/lib/net/ssh/verifiers/null.rb +0 -12
  124. data/lib/net/ssh/verifiers/secure.rb +0 -52
  125. data/lib/net/ssh/verifiers/strict.rb +0 -24
  126. data/support/arcfour_check.rb +0 -20
@@ -1,227 +1,122 @@
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; module SSH; module Transport; module Kex
8
-
9
- # A key-exchange service implementing the "diffie-hellman-group1-sha1"
10
- # key-exchange algorithm.
11
- class DiffieHellmanGroup1SHA1
12
- include Constants, Loggable
13
-
14
- # The value of 'P', as a string, in hexadecimal
15
- P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
16
- "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
17
- "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
18
- "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
19
- "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
20
- "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
21
- "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
22
- "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"
23
-
24
- # The radix in which P_s represents the value of P
25
- P_r = 16
26
-
27
- # The group constant
28
- G = 2
29
-
30
- attr_reader :p
31
- attr_reader :g
32
- attr_reader :digester
33
- attr_reader :algorithms
34
- attr_reader :connection
35
- attr_reader :data
36
- attr_reader :dh
37
-
38
- # Create a new instance of the DiffieHellmanGroup1SHA1 algorithm.
39
- # The data is a Hash of symbols representing information
40
- # required by this algorithm, which was acquired during earlier
41
- # processing.
42
- def initialize(algorithms, connection, data)
43
- @p = get_p
44
- @g = get_g
45
-
46
- @digester = OpenSSL::Digest::SHA1
47
- @algorithms = algorithms
48
- @connection = connection
49
-
50
- @data = data.dup
51
- @dh = generate_key
52
- @logger = @data.delete(:logger)
53
- end
54
-
55
- # Perform the key-exchange for the given session, with the given
56
- # data. This method will return a hash consisting of the
57
- # following keys:
58
- #
59
- # * :session_id
60
- # * :server_key
61
- # * :shared_secret
62
- # * :hashing_algorithm
63
- #
64
- # The caller is expected to be able to understand how to use these
65
- # deliverables.
66
- def exchange_keys
67
- result = send_kexinit
68
- verify_server_key(result[:server_key])
69
- session_id = verify_signature(result)
70
- confirm_newkeys
71
-
72
- return { session_id: session_id,
73
- server_key: result[:server_key],
74
- shared_secret: result[:shared_secret],
75
- hashing_algorithm: digester }
76
- end
77
-
78
- private
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
-
88
- # Returns the DH key parameters for the current connection.
89
- def get_parameters
90
- [p, g]
91
- end
92
-
93
- # Returns the INIT/REPLY constants used by this algorithm.
94
- def get_message_types
95
- [KEXDH_INIT, KEXDH_REPLY]
96
- end
97
-
98
- # Build the signature buffer to use when verifying a signature from
99
- # the server.
100
- def build_signature_buffer(result)
101
- response = Net::SSH::Buffer.new
102
- response.write_string data[:client_version_string],
103
- data[:server_version_string],
104
- data[:client_algorithm_packet],
105
- data[:server_algorithm_packet],
106
- result[:key_blob]
107
- response.write_bignum dh.pub_key,
108
- result[:server_dh_pubkey],
109
- result[:shared_secret]
110
- response
111
- end
112
-
113
- # Generate a DH key with a private key consisting of the given
114
- # number of bytes.
115
- def generate_key #:nodoc:
116
- dh = OpenSSL::PKey::DH.new
117
-
118
- if dh.respond_to?(:set_pqg)
119
- p, g = get_parameters
120
- dh.set_pqg(p, nil, g)
121
- else
122
- dh.p, dh.g = get_parameters
123
- end
124
-
125
- dh.generate_key!
126
- until dh.valid? && dh.priv_key.num_bytes == data[:need_bytes]
127
- if dh.respond_to?(:set_key)
128
- dh.set_key(nil, OpenSSL::BN.rand(data[:need_bytes] * 8))
129
- else
130
- dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
1
+ require 'net/ssh/transport/kex/abstract'
2
+
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
7
+ # A key-exchange service implementing the "diffie-hellman-group1-sha1"
8
+ # key-exchange algorithm.
9
+ class DiffieHellmanGroup1SHA1 < Abstract
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" "ECE65381" "FFFFFFFF" "FFFFFFFF"
19
+
20
+ # The radix in which P_s represents the value of P
21
+ P_r = 16
22
+
23
+ # The group constant
24
+ G = 2
25
+
26
+ def digester
27
+ OpenSSL::Digest::SHA1
131
28
  end
132
- dh.generate_key!
133
- end
134
- dh
135
- end
136
29
 
137
- # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
138
- # resulting buffer.
139
- #
140
- # Parse the buffer from a KEXDH_REPLY message, returning a hash of
141
- # the extracted values.
142
- def send_kexinit #:nodoc:
143
- init, reply = get_message_types
144
-
145
- # send the KEXDH_INIT message
146
- buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
147
- connection.send_message(buffer)
148
-
149
- # expect the KEXDH_REPLY message
150
- buffer = connection.next_message
151
- raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
152
-
153
- result = Hash.new
154
-
155
- result[:key_blob] = buffer.read_string
156
- result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
157
- result[:server_dh_pubkey] = buffer.read_bignum
158
- result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
159
-
160
- sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
161
- sig_type = sig_buffer.read_string
162
- if sig_type != algorithms.host_key
163
- raise Net::SSH::Exception,
164
- "host key algorithm mismatch for signature " +
165
- "'#{sig_type}' != '#{algorithms.host_key}'"
166
- end
167
- result[:server_sig] = sig_buffer.read_string
168
-
169
- return result
170
- end
171
-
172
- # Verify that the given key is of the expected type, and that it
173
- # really is the key for the session's host. Raise Net::SSH::Exception
174
- # if it is not.
175
- def verify_server_key(key) #:nodoc:
176
- if key.ssh_type != algorithms.host_key
177
- raise Net::SSH::Exception,
178
- "host key algorithm mismatch " +
179
- "'#{key.ssh_type}' != '#{algorithms.host_key}'"
180
- end
30
+ private
181
31
 
182
- blob, fingerprint = generate_key_fingerprint(key)
183
-
184
- unless connection.host_key_verifier.verify(key: key, key_blob: blob, fingerprint: fingerprint, session: connection)
185
- raise Net::SSH::Exception, "host key verification failed"
186
- end
187
- end
188
-
189
- def generate_key_fingerprint(key)
190
- blob = Net::SSH::Buffer.from(:key, key).to_s
191
- fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":")
32
+ # Returns the DH key parameters for the current connection. [p, q]
33
+ def get_parameters
34
+ [
35
+ OpenSSL::BN.new(self.class::P_s, self.class::P_r),
36
+ self.class::G
37
+ ]
38
+ end
192
39
 
193
- [blob, fingerprint]
194
- rescue ::Exception => e
195
- [nil, "(could not generate fingerprint: #{e.message})"]
196
- end
40
+ # Returns the INIT/REPLY constants used by this algorithm.
41
+ def get_message_types
42
+ [KEXDH_INIT, KEXDH_REPLY]
43
+ end
197
44
 
198
- # Verify the signature that was received. Raise Net::SSH::Exception
199
- # if the signature could not be verified. Otherwise, return the new
200
- # session-id.
201
- def verify_signature(result) #:nodoc:
202
- response = build_signature_buffer(result)
45
+ # Build the signature buffer to use when verifying a signature from
46
+ # the server.
47
+ def build_signature_buffer(result)
48
+ response = Net::SSH::Buffer.new
49
+ response.write_string data[:client_version_string],
50
+ data[:server_version_string],
51
+ data[:client_algorithm_packet],
52
+ data[:server_algorithm_packet],
53
+ result[:key_blob]
54
+ response.write_bignum dh.pub_key,
55
+ result[:server_dh_pubkey],
56
+ result[:shared_secret]
57
+ response
58
+ end
203
59
 
204
- hash = @digester.digest(response.to_s)
60
+ # Generate a DH key with a private key consisting of the given
61
+ # number of bytes.
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)
78
+ else
79
+ dh_params.generate_key!
80
+ dh_params
81
+ end
82
+ end
205
83
 
206
- unless result[:server_key].ssh_do_verify(result[:server_sig], hash)
207
- raise Net::SSH::Exception, "could not verify server signature"
84
+ # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
85
+ # resulting buffer.
86
+ #
87
+ # Parse the buffer from a KEXDH_REPLY message, returning a hash of
88
+ # the extracted values.
89
+ def send_kexinit # :nodoc:
90
+ init, reply = get_message_types
91
+
92
+ # send the KEXDH_INIT message
93
+ buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
94
+ connection.send_message(buffer)
95
+
96
+ # expect the KEXDH_REPLY message
97
+ buffer = connection.next_message
98
+ raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
99
+
100
+ result = Hash.new
101
+
102
+ result[:key_blob] = buffer.read_string
103
+ result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
104
+ result[:server_dh_pubkey] = buffer.read_bignum
105
+ result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
106
+
107
+ sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
108
+ sig_type = sig_buffer.read_string
109
+ if sig_type != algorithms.host_key_format
110
+ raise Net::SSH::Exception,
111
+ "host key algorithm mismatch for signature " +
112
+ "'#{sig_type}' != '#{algorithms.host_key_format}'"
113
+ end
114
+ result[:server_sig] = sig_buffer.read_string
115
+
116
+ return result
117
+ end
208
118
  end
209
-
210
- return hash
211
- end
212
-
213
- # Send the NEWKEYS message, and expect the NEWKEYS message in
214
- # reply.
215
- def confirm_newkeys #:nodoc:
216
- # send own NEWKEYS message first (the wodSSHServer won't send first)
217
- response = Net::SSH::Buffer.new
218
- response.write_byte(NEWKEYS)
219
- connection.send_message(response)
220
-
221
- # wait for the server's NEWKEYS message
222
- buffer = connection.next_message
223
- raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
224
119
  end
120
+ end
225
121
  end
226
-
227
- end; end; end; end
122
+ end
@@ -3,80 +3,70 @@ 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
- # Compute the number of bits needed for the given number of bytes.
21
- def compute_need_bits
22
-
23
- # for Compatibility: OpenSSH requires (need_bits * 2 + 1) length of parameter
24
- need_bits = data[:need_bytes] * 8 * 2 + 1
25
-
26
- data[:minimum_dh_bits] ||= MINIMUM_BITS
27
-
28
- if need_bits < data[:minimum_dh_bits]
29
- need_bits = data[:minimum_dh_bits]
30
- elsif need_bits > MAXIMUM_BITS
31
- need_bits = MAXIMUM_BITS
32
- end
33
-
34
- data[:need_bits ] = need_bits
35
- data[:need_bytes] = need_bits / 8
36
- end
37
-
38
- # Returns the DH key parameters for the given session.
39
- def get_parameters
40
- compute_need_bits
41
-
42
- # request the DH key parameters for the given number of bits.
43
- buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, data[:minimum_dh_bits],
44
- :long, data[:need_bits], :long, MAXIMUM_BITS)
45
- connection.send_message(buffer)
14
+ # Compute the number of bits needed for the given number of bytes.
15
+ def compute_need_bits
16
+ # for Compatibility: OpenSSH requires (need_bits * 2 + 1) length of parameter
17
+ need_bits = data[:need_bytes] * 8 * 2 + 1
46
18
 
47
- buffer = connection.next_message
48
- unless buffer.type == KEXDH_GEX_GROUP
49
- raise Net::SSH::Exception, "expected KEXDH_GEX_GROUP, got #{buffer.type}"
50
- end
19
+ data[:minimum_dh_bits] ||= MINIMUM_BITS
51
20
 
52
- p = buffer.read_bignum
53
- g = buffer.read_bignum
54
-
55
- [p, g]
21
+ if need_bits < data[:minimum_dh_bits]
22
+ need_bits = data[:minimum_dh_bits]
23
+ elsif need_bits > MAXIMUM_BITS
24
+ need_bits = MAXIMUM_BITS
56
25
  end
57
26
 
58
- # Returns the INIT/REPLY constants used by this algorithm.
59
- def get_message_types
60
- [KEXDH_GEX_INIT, KEXDH_GEX_REPLY]
61
- end
62
-
63
- # Build the signature buffer to use when verifying a signature from
64
- # the server.
65
- def build_signature_buffer(result)
66
- response = Net::SSH::Buffer.new
67
- response.write_string data[:client_version_string],
68
- data[:server_version_string],
69
- data[:client_algorithm_packet],
70
- data[:server_algorithm_packet],
71
- result[:key_blob]
72
- response.write_long MINIMUM_BITS,
73
- data[:need_bits],
74
- MAXIMUM_BITS
75
- response.write_bignum dh.p, dh.g, dh.pub_key,
76
- result[:server_dh_pubkey],
77
- result[:shared_secret]
78
- response
79
- end
27
+ data[:need_bits] = need_bits
28
+ data[:need_bytes] = need_bits / 8
29
+ end
30
+
31
+ # Returns the DH key parameters for the given session.
32
+ def get_parameters
33
+ compute_need_bits
34
+
35
+ # request the DH key parameters for the given number of bits.
36
+ buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, data[:minimum_dh_bits],
37
+ :long, data[:need_bits], :long, MAXIMUM_BITS)
38
+ connection.send_message(buffer)
39
+
40
+ buffer = connection.next_message
41
+ raise Net::SSH::Exception, "expected KEXDH_GEX_GROUP, got #{buffer.type}" unless buffer.type == KEXDH_GEX_GROUP
42
+
43
+ p = buffer.read_bignum
44
+ g = buffer.read_bignum
45
+
46
+ [p, g]
47
+ end
48
+
49
+ # Returns the INIT/REPLY constants used by this algorithm.
50
+ def get_message_types
51
+ [KEXDH_GEX_INIT, KEXDH_GEX_REPLY]
52
+ end
53
+
54
+ # Build the signature buffer to use when verifying a signature from
55
+ # the server.
56
+ def build_signature_buffer(result)
57
+ response = Net::SSH::Buffer.new
58
+ response.write_string data[:client_version_string],
59
+ data[:server_version_string],
60
+ data[:client_algorithm_packet],
61
+ data[:server_algorithm_packet],
62
+ result[:key_blob]
63
+ response.write_long MINIMUM_BITS,
64
+ data[:need_bits],
65
+ MAXIMUM_BITS
66
+ response.write_bignum dh.p, dh.g, dh.pub_key,
67
+ result[:server_dh_pubkey],
68
+ result[:shared_secret]
69
+ response
70
+ end
80
71
  end
81
-
82
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
@@ -1,93 +1,39 @@
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, :mstring, 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}'"
1
+ require 'net/ssh/transport/kex/abstract5656'
2
+
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
7
+ # A key-exchange service implementing the "ecdh-sha2-nistp256"
8
+ # key-exchange algorithm. (defined in RFC 5656)
9
+ class EcdhSHA2NistP256 < Abstract5656
10
+ def digester
11
+ OpenSSL::Digest::SHA256
12
+ end
13
+
14
+ def curve_name
15
+ OpenSSL::PKey::EC::CurveNameAlias['nistp256']
16
+ end
17
+
18
+ private
19
+
20
+ def generate_key # :nodoc:
21
+ OpenSSL::PKey::EC.generate(curve_name)
22
+ end
23
+
24
+ # compute shared secret from server's public key and client's private key
25
+ def compute_shared_secret(server_ecdh_pubkey)
26
+ pk = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(curve_name).group,
27
+ OpenSSL::BN.new(server_ecdh_pubkey, 2))
28
+ OpenSSL::BN.new(ecdh.dh_compute_key(pk), 2)
29
+ end
30
+
31
+ ## string Q_C, client's ephemeral public key octet string
32
+ def ecdh_public_key_bytes
33
+ ecdh.public_key.to_bn.to_s(2)
34
+ end
35
+ end
87
36
  end
88
- result[:server_sig] = sig_buffer.read_string
89
-
90
- return result
91
37
  end
92
38
  end
93
- end; end; end; end
39
+ end
@@ -1,13 +1,21 @@
1
- module Net; module SSH; module Transport; module Kex
1
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
2
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']
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
7
+ # A key-exchange service implementing the "ecdh-sha2-nistp256"
8
+ # key-exchange algorithm. (defined in RFC 5656)
9
+ class EcdhSHA2NistP384 < EcdhSHA2NistP256
10
+ def digester
11
+ OpenSSL::Digest::SHA384
12
+ end
13
+
14
+ def curve_name
15
+ OpenSSL::PKey::EC::CurveNameAlias['nistp384']
16
+ end
17
+ end
18
+ end
11
19
  end
12
20
  end
13
- end; end; end; end
21
+ end