net-ssh-backports 6.3.0.backports

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 (111) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +93 -0
  3. data/.gitignore +13 -0
  4. data/.rubocop.yml +21 -0
  5. data/.rubocop_todo.yml +1074 -0
  6. data/.travis.yml +51 -0
  7. data/CHANGES.txt +698 -0
  8. data/Gemfile +13 -0
  9. data/Gemfile.noed25519 +12 -0
  10. data/ISSUE_TEMPLATE.md +30 -0
  11. data/LICENSE.txt +19 -0
  12. data/Manifest +132 -0
  13. data/README.md +287 -0
  14. data/Rakefile +105 -0
  15. data/THANKS.txt +110 -0
  16. data/appveyor.yml +58 -0
  17. data/lib/net/ssh/authentication/agent.rb +284 -0
  18. data/lib/net/ssh/authentication/certificate.rb +183 -0
  19. data/lib/net/ssh/authentication/constants.rb +20 -0
  20. data/lib/net/ssh/authentication/ed25519.rb +185 -0
  21. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  22. data/lib/net/ssh/authentication/key_manager.rb +297 -0
  23. data/lib/net/ssh/authentication/methods/abstract.rb +69 -0
  24. data/lib/net/ssh/authentication/methods/hostbased.rb +72 -0
  25. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +77 -0
  26. data/lib/net/ssh/authentication/methods/none.rb +34 -0
  27. data/lib/net/ssh/authentication/methods/password.rb +80 -0
  28. data/lib/net/ssh/authentication/methods/publickey.rb +95 -0
  29. data/lib/net/ssh/authentication/pageant.rb +497 -0
  30. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  31. data/lib/net/ssh/authentication/session.rb +163 -0
  32. data/lib/net/ssh/buffer.rb +434 -0
  33. data/lib/net/ssh/buffered_io.rb +202 -0
  34. data/lib/net/ssh/config.rb +406 -0
  35. data/lib/net/ssh/connection/channel.rb +695 -0
  36. data/lib/net/ssh/connection/constants.rb +33 -0
  37. data/lib/net/ssh/connection/event_loop.rb +123 -0
  38. data/lib/net/ssh/connection/keepalive.rb +59 -0
  39. data/lib/net/ssh/connection/session.rb +712 -0
  40. data/lib/net/ssh/connection/term.rb +180 -0
  41. data/lib/net/ssh/errors.rb +106 -0
  42. data/lib/net/ssh/key_factory.rb +218 -0
  43. data/lib/net/ssh/known_hosts.rb +264 -0
  44. data/lib/net/ssh/loggable.rb +62 -0
  45. data/lib/net/ssh/packet.rb +106 -0
  46. data/lib/net/ssh/prompt.rb +62 -0
  47. data/lib/net/ssh/proxy/command.rb +123 -0
  48. data/lib/net/ssh/proxy/errors.rb +16 -0
  49. data/lib/net/ssh/proxy/http.rb +98 -0
  50. data/lib/net/ssh/proxy/https.rb +50 -0
  51. data/lib/net/ssh/proxy/jump.rb +54 -0
  52. data/lib/net/ssh/proxy/socks4.rb +67 -0
  53. data/lib/net/ssh/proxy/socks5.rb +140 -0
  54. data/lib/net/ssh/service/forward.rb +426 -0
  55. data/lib/net/ssh/test/channel.rb +147 -0
  56. data/lib/net/ssh/test/extensions.rb +173 -0
  57. data/lib/net/ssh/test/kex.rb +46 -0
  58. data/lib/net/ssh/test/local_packet.rb +53 -0
  59. data/lib/net/ssh/test/packet.rb +101 -0
  60. data/lib/net/ssh/test/remote_packet.rb +40 -0
  61. data/lib/net/ssh/test/script.rb +180 -0
  62. data/lib/net/ssh/test/socket.rb +65 -0
  63. data/lib/net/ssh/test.rb +94 -0
  64. data/lib/net/ssh/transport/algorithms.rb +502 -0
  65. data/lib/net/ssh/transport/cipher_factory.rb +103 -0
  66. data/lib/net/ssh/transport/constants.rb +40 -0
  67. data/lib/net/ssh/transport/ctr.rb +115 -0
  68. data/lib/net/ssh/transport/hmac/abstract.rb +97 -0
  69. data/lib/net/ssh/transport/hmac/md5.rb +10 -0
  70. data/lib/net/ssh/transport/hmac/md5_96.rb +9 -0
  71. data/lib/net/ssh/transport/hmac/none.rb +13 -0
  72. data/lib/net/ssh/transport/hmac/ripemd160.rb +11 -0
  73. data/lib/net/ssh/transport/hmac/sha1.rb +11 -0
  74. data/lib/net/ssh/transport/hmac/sha1_96.rb +9 -0
  75. data/lib/net/ssh/transport/hmac/sha2_256.rb +11 -0
  76. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +9 -0
  77. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  78. data/lib/net/ssh/transport/hmac/sha2_512.rb +11 -0
  79. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +9 -0
  80. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  81. data/lib/net/ssh/transport/hmac.rb +47 -0
  82. data/lib/net/ssh/transport/identity_cipher.rb +57 -0
  83. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  84. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  85. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  86. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  87. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +37 -0
  88. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  89. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +122 -0
  90. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +72 -0
  91. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +11 -0
  92. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +39 -0
  93. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +21 -0
  94. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +21 -0
  95. data/lib/net/ssh/transport/kex.rb +31 -0
  96. data/lib/net/ssh/transport/key_expander.rb +30 -0
  97. data/lib/net/ssh/transport/openssl.rb +253 -0
  98. data/lib/net/ssh/transport/packet_stream.rb +280 -0
  99. data/lib/net/ssh/transport/server_version.rb +77 -0
  100. data/lib/net/ssh/transport/session.rb +354 -0
  101. data/lib/net/ssh/transport/state.rb +208 -0
  102. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  103. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  104. data/lib/net/ssh/verifiers/always.rb +58 -0
  105. data/lib/net/ssh/verifiers/never.rb +19 -0
  106. data/lib/net/ssh/version.rb +68 -0
  107. data/lib/net/ssh.rb +330 -0
  108. data/net-ssh-public_cert.pem +20 -0
  109. data/net-ssh.gemspec +44 -0
  110. data/support/ssh_tunnel_bug.rb +65 -0
  111. metadata +271 -0
@@ -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
@@ -0,0 +1,37 @@
1
+ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
+
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
7
+ # A key-exchange service implementing the "diffie-hellman-group14-sha1"
8
+ # key-exchange algorithm. (defined in RFC 4253)
9
+ class DiffieHellmanGroup14SHA1 < DiffieHellmanGroup1SHA1
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
+ end
34
+ end
35
+ end
36
+ end
37
+ 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
@@ -0,0 +1,122 @@
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
28
+ end
29
+
30
+ private
31
+
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
39
+
40
+ # Returns the INIT/REPLY constants used by this algorithm.
41
+ def get_message_types
42
+ [KEXDH_INIT, KEXDH_REPLY]
43
+ end
44
+
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
59
+
60
+ # Generate a DH key with a private key consisting of the given
61
+ # number of bytes.
62
+ def generate_key #:nodoc:
63
+ dh = OpenSSL::PKey::DH.new
64
+
65
+ if dh.respond_to?(:set_pqg)
66
+ p, g = get_parameters
67
+ dh.set_pqg(p, nil, g)
68
+ else
69
+ dh.p, dh.g = get_parameters
70
+ end
71
+
72
+ dh.generate_key!
73
+ until dh.valid? && dh.priv_key.num_bytes == data[:need_bytes]
74
+ if dh.respond_to?(:set_key)
75
+ dh.set_key(nil, OpenSSL::BN.rand(data[:need_bytes] * 8))
76
+ else
77
+ dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
78
+ end
79
+ dh.generate_key!
80
+ end
81
+ dh
82
+ end
83
+
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
118
+ end
119
+ end
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,72 @@
1
+ require 'net/ssh/errors'
2
+ require 'net/ssh/transport/constants'
3
+ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
4
+
5
+ module Net::SSH::Transport::Kex
6
+ # A key-exchange service implementing the
7
+ # "diffie-hellman-group-exchange-sha1" key-exchange algorithm.
8
+ class DiffieHellmanGroupExchangeSHA1 < DiffieHellmanGroup1SHA1
9
+ MINIMUM_BITS = 1024
10
+ MAXIMUM_BITS = 8192
11
+
12
+ private
13
+
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
18
+
19
+ data[:minimum_dh_bits] ||= MINIMUM_BITS
20
+
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
25
+ end
26
+
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
71
+ end
72
+ end
@@ -0,0 +1,11 @@
1
+ require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
2
+
3
+ module Net::SSH::Transport::Kex
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
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,39 @@
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.new(curve_name).generate_key
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
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,21 @@
1
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
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 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
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,21 @@
1
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
2
+
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
7
+ # A key-exchange service implementing the "ecdh-sha2-nistp521"
8
+ # key-exchange algorithm. (defined in RFC 5656)
9
+ class EcdhSHA2NistP521 < EcdhSHA2NistP256
10
+ def digester
11
+ OpenSSL::Digest::SHA512
12
+ end
13
+
14
+ def curve_name
15
+ OpenSSL::PKey::EC::CurveNameAlias['nistp521']
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,31 @@
1
+ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
+ require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
3
+ require 'net/ssh/transport/kex/diffie_hellman_group14_sha256'
4
+ require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
5
+ require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha256'
6
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
7
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
8
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp521'
9
+ require 'net/ssh/transport/kex/curve25519_sha256_loader'
10
+
11
+ module Net::SSH::Transport
12
+ module Kex
13
+ # Maps the supported key-exchange algorithms as named by the SSH protocol
14
+ # to their corresponding implementors.
15
+ MAP = {
16
+ 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
17
+ 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
18
+ 'diffie-hellman-group14-sha256' => DiffieHellmanGroup14SHA256,
19
+ 'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
20
+ 'diffie-hellman-group-exchange-sha256' => DiffieHellmanGroupExchangeSHA256,
21
+ 'ecdh-sha2-nistp256' => EcdhSHA2NistP256,
22
+ 'ecdh-sha2-nistp384' => EcdhSHA2NistP384,
23
+ 'ecdh-sha2-nistp521' => EcdhSHA2NistP521
24
+ }
25
+
26
+ if Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
27
+ MAP['curve25519-sha256'] = Curve25519Sha256
28
+ MAP['curve25519-sha256@libssh.org'] = Curve25519Sha256
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,30 @@
1
+ module Net
2
+ module SSH
3
+ module Transport
4
+ module KeyExpander
5
+ # Generate a key value in accordance with the SSH2 specification.
6
+ # (RFC4253 7.2. "Output from Key Exchange")
7
+ def self.expand_key(bytes, start, options={})
8
+ if bytes == 0
9
+ return ""
10
+ end
11
+
12
+ k = start[0, bytes]
13
+ return k if k.length >= bytes
14
+
15
+ digester = options[:digester] or raise 'No digester supplied'
16
+ shared = options[:shared] or raise 'No shared secret supplied'
17
+ hash = options[:hash] or raise 'No hash supplied'
18
+
19
+ while k.length < bytes
20
+ step = digester.digest(shared + hash + k)
21
+ bytes_needed = bytes - k.length
22
+ k << step[0, bytes_needed]
23
+ end
24
+
25
+ return k
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end