net-ssh 4.1.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gitignore +5 -0
  5. data/.rubocop.yml +8 -2
  6. data/.rubocop_todo.yml +405 -552
  7. data/.travis.yml +23 -22
  8. data/CHANGES.txt +112 -1
  9. data/Gemfile +1 -7
  10. data/{Gemfile.norbnacl → Gemfile.noed25519} +1 -1
  11. data/Manifest +4 -5
  12. data/README.md +287 -0
  13. data/Rakefile +40 -29
  14. data/appveyor.yml +12 -6
  15. data/lib/net/ssh.rb +68 -32
  16. data/lib/net/ssh/authentication/agent.rb +234 -222
  17. data/lib/net/ssh/authentication/certificate.rb +175 -164
  18. data/lib/net/ssh/authentication/constants.rb +17 -14
  19. data/lib/net/ssh/authentication/ed25519.rb +162 -141
  20. data/lib/net/ssh/authentication/ed25519_loader.rb +32 -29
  21. data/lib/net/ssh/authentication/key_manager.rb +40 -9
  22. data/lib/net/ssh/authentication/methods/abstract.rb +53 -47
  23. data/lib/net/ssh/authentication/methods/hostbased.rb +32 -33
  24. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +1 -1
  25. data/lib/net/ssh/authentication/methods/none.rb +10 -10
  26. data/lib/net/ssh/authentication/methods/password.rb +13 -13
  27. data/lib/net/ssh/authentication/methods/publickey.rb +56 -55
  28. data/lib/net/ssh/authentication/pageant.rb +468 -465
  29. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  30. data/lib/net/ssh/authentication/session.rb +130 -122
  31. data/lib/net/ssh/buffer.rb +345 -312
  32. data/lib/net/ssh/buffered_io.rb +163 -163
  33. data/lib/net/ssh/config.rb +316 -238
  34. data/lib/net/ssh/connection/channel.rb +670 -650
  35. data/lib/net/ssh/connection/constants.rb +30 -26
  36. data/lib/net/ssh/connection/event_loop.rb +108 -105
  37. data/lib/net/ssh/connection/keepalive.rb +54 -50
  38. data/lib/net/ssh/connection/session.rb +682 -671
  39. data/lib/net/ssh/connection/term.rb +180 -176
  40. data/lib/net/ssh/errors.rb +101 -99
  41. data/lib/net/ssh/key_factory.rb +195 -108
  42. data/lib/net/ssh/known_hosts.rb +161 -152
  43. data/lib/net/ssh/loggable.rb +57 -55
  44. data/lib/net/ssh/packet.rb +82 -78
  45. data/lib/net/ssh/prompt.rb +55 -53
  46. data/lib/net/ssh/proxy/command.rb +104 -89
  47. data/lib/net/ssh/proxy/errors.rb +12 -8
  48. data/lib/net/ssh/proxy/http.rb +93 -91
  49. data/lib/net/ssh/proxy/https.rb +42 -39
  50. data/lib/net/ssh/proxy/jump.rb +50 -47
  51. data/lib/net/ssh/proxy/socks4.rb +0 -2
  52. data/lib/net/ssh/proxy/socks5.rb +11 -12
  53. data/lib/net/ssh/service/forward.rb +370 -317
  54. data/lib/net/ssh/test.rb +83 -77
  55. data/lib/net/ssh/test/channel.rb +146 -142
  56. data/lib/net/ssh/test/extensions.rb +150 -146
  57. data/lib/net/ssh/test/kex.rb +35 -31
  58. data/lib/net/ssh/test/local_packet.rb +48 -44
  59. data/lib/net/ssh/test/packet.rb +87 -84
  60. data/lib/net/ssh/test/remote_packet.rb +35 -31
  61. data/lib/net/ssh/test/script.rb +173 -171
  62. data/lib/net/ssh/test/socket.rb +59 -55
  63. data/lib/net/ssh/transport/algorithms.rb +430 -364
  64. data/lib/net/ssh/transport/cipher_factory.rb +95 -91
  65. data/lib/net/ssh/transport/constants.rb +33 -25
  66. data/lib/net/ssh/transport/ctr.rb +33 -11
  67. data/lib/net/ssh/transport/hmac.rb +15 -13
  68. data/lib/net/ssh/transport/hmac/abstract.rb +82 -63
  69. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  70. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  71. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  72. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  73. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  74. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  75. data/lib/net/ssh/transport/identity_cipher.rb +55 -51
  76. data/lib/net/ssh/transport/kex.rb +14 -13
  77. data/lib/net/ssh/transport/kex/abstract.rb +123 -0
  78. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  79. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +38 -0
  80. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  81. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  82. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +112 -217
  83. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -62
  84. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  85. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  86. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  87. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  88. data/lib/net/ssh/transport/key_expander.rb +29 -25
  89. data/lib/net/ssh/transport/openssl.rb +116 -116
  90. data/lib/net/ssh/transport/packet_stream.rb +223 -190
  91. data/lib/net/ssh/transport/server_version.rb +64 -66
  92. data/lib/net/ssh/transport/session.rb +306 -257
  93. data/lib/net/ssh/transport/state.rb +198 -196
  94. data/lib/net/ssh/verifiers/accept_new.rb +35 -0
  95. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +34 -0
  96. data/lib/net/ssh/verifiers/always.rb +56 -0
  97. data/lib/net/ssh/verifiers/never.rb +21 -0
  98. data/lib/net/ssh/version.rb +55 -53
  99. data/net-ssh-public_cert.pem +18 -19
  100. data/net-ssh.gemspec +12 -11
  101. data/support/ssh_tunnel_bug.rb +2 -2
  102. metadata +86 -75
  103. metadata.gz.sig +0 -0
  104. data/Gemfile.norbnacl.lock +0 -41
  105. data/README.rdoc +0 -169
  106. data/lib/net/ssh/ruby_compat.rb +0 -24
  107. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  108. data/lib/net/ssh/verifiers/null.rb +0 -12
  109. data/lib/net/ssh/verifiers/secure.rb +0 -52
  110. data/lib/net/ssh/verifiers/strict.rb +0 -24
  111. data/support/arcfour_check.rb +0 -20
@@ -3,80 +3,71 @@ 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
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
27
18
 
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
19
+ data[:minimum_dh_bits] ||= MINIMUM_BITS
33
20
 
34
- data[:need_bits ] = need_bits
35
- data[:need_bytes] = need_bits / 8
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
36
25
  end
37
26
 
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)
46
-
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
51
-
52
- p = buffer.read_bignum
53
- g = buffer.read_bignum
54
-
55
- [p, g]
56
- end
57
-
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
72
 
82
73
  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.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
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
@@ -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-nistp521"
4
- # key-exchange algorithm. (defined in RFC 5656)
5
- class EcdhSHA2NistP521 < EcdhSHA2NistP256
6
- def digester
7
- OpenSSL::Digest::SHA512
8
- end
9
- def curve_name
10
- OpenSSL::PKey::EC::CurveNameAlias['nistp521']
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
11
19
  end
12
20
  end
13
- end; end; end; end
21
+ end
@@ -1,27 +1,31 @@
1
- module Net; module SSH; module Transport
2
- module KeyExpander
3
-
4
- # Generate a key value in accordance with the SSH2 specification.
5
- # (RFC4253 7.2. "Output from Key Exchange")
6
- def self.expand_key(bytes, start, options={})
7
- if bytes == 0
8
- return ""
1
+ module Net
2
+ module SSH
3
+ module Transport
4
+ module KeyExpander
5
+
6
+ # Generate a key value in accordance with the SSH2 specification.
7
+ # (RFC4253 7.2. "Output from Key Exchange")
8
+ def self.expand_key(bytes, start, options={})
9
+ if bytes == 0
10
+ return ""
11
+ end
12
+
13
+ k = start[0, bytes]
14
+ return k if k.length >= bytes
15
+
16
+ digester = options[:digester] or raise 'No digester supplied'
17
+ shared = options[:shared] or raise 'No shared secret supplied'
18
+ hash = options[:hash] or raise 'No hash supplied'
19
+
20
+ while k.length < bytes
21
+ step = digester.digest(shared + hash + k)
22
+ bytes_needed = bytes - k.length
23
+ k << step[0, bytes_needed]
24
+ end
25
+
26
+ return k
27
+ end
28
+ end
9
29
  end
10
-
11
- k = start[0, bytes]
12
- return k if k.length >= bytes
13
-
14
- digester = options[:digester] or raise 'No digester supplied'
15
- shared = options[:shared] or raise 'No shared secret supplied'
16
- hash = options[:hash] or raise 'No hash supplied'
17
-
18
- while k.length < bytes
19
- step = digester.digest(shared + hash + k)
20
- bytes_needed = bytes - k.length
21
- k << step[0, bytes_needed]
22
- end
23
-
24
- return k
25
- end
26
30
  end
27
- end; end; end
31
+ end
@@ -1,5 +1,5 @@
1
- # -*- coding: utf-8 -*-
2
1
  require 'openssl'
2
+ require 'net/ssh/authentication/pub_key_fingerprint'
3
3
 
4
4
  module OpenSSL
5
5
 
@@ -7,7 +7,6 @@ module OpenSSL
7
7
  # have been added to it by the Net::SSH module for convenience in dealing with
8
8
  # SSH functionality.
9
9
  class BN
10
-
11
10
  # Converts a BN object to a string. The format used is that which is
12
11
  # required by the SSH2 protocol.
13
12
  def to_ssh
@@ -16,44 +15,38 @@ module OpenSSL
16
15
  else
17
16
  buf = to_s(2)
18
17
  if buf.getbyte(0)[7] == 1
19
- return [buf.length+1, 0, buf].pack("NCA*")
18
+ return [buf.length + 1, 0, buf].pack("NCA*")
20
19
  else
21
20
  return [buf.length, buf].pack("NA*")
22
21
  end
23
22
  end
24
23
  end
25
-
26
24
  end
27
25
 
28
26
  module PKey
29
27
 
30
28
  class PKey
31
- def fingerprint
32
- @fingerprint ||= OpenSSL::Digest::MD5.hexdigest(to_blob).scan(/../).join(":")
33
- end
29
+ include Net::SSH::Authentication::PubKeyFingerprint
34
30
  end
35
31
 
36
32
  # This class is originally defined in the OpenSSL module. As needed, methods
37
33
  # have been added to it by the Net::SSH module for convenience in dealing
38
34
  # with SSH functionality.
39
35
  class DH
40
-
41
36
  # Determines whether the pub_key for this key is valid. (This algorithm
42
37
  # lifted more-or-less directly from OpenSSH, dh.c, dh_pub_is_valid.)
43
38
  def valid?
44
39
  return false if pub_key.nil? || pub_key < 0
45
40
  bits_set = 0
46
41
  pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set?(i) }
47
- return ( bits_set > 1 && pub_key < p )
42
+ return (bits_set > 1 && pub_key < p)
48
43
  end
49
-
50
44
  end
51
45
 
52
46
  # This class is originally defined in the OpenSSL module. As needed, methods
53
47
  # have been added to it by the Net::SSH module for convenience in dealing
54
48
  # with SSH functionality.
55
49
  class RSA
56
-
57
50
  # Returns "ssh-rsa", which is the description of this key type used by the
58
51
  # SSH2 protocol.
59
52
  def ssh_type
@@ -84,7 +77,6 @@ module OpenSSL
84
77
  # have been added to it by the Net::SSH module for convenience in dealing
85
78
  # with SSH functionality.
86
79
  class DSA
87
-
88
80
  # Returns "ssh-dss", which is the description of this key type used by the
89
81
  # SSH2 protocol.
90
82
  def ssh_type
@@ -106,143 +98,151 @@ module OpenSSL
106
98
  sig_r = sig[0,20].unpack("H*")[0].to_i(16)
107
99
  sig_s = sig[20,20].unpack("H*")[0].to_i(16)
108
100
  a1sig = OpenSSL::ASN1::Sequence([
109
- OpenSSL::ASN1::Integer(sig_r),
110
- OpenSSL::ASN1::Integer(sig_s)
111
- ])
112
- return verify(OpenSSL::Digest::DSS1.new, a1sig.to_der, data)
101
+ OpenSSL::ASN1::Integer(sig_r),
102
+ OpenSSL::ASN1::Integer(sig_s)
103
+ ])
104
+ return verify(OpenSSL::Digest::SHA1.new, a1sig.to_der, data)
113
105
  end
114
106
 
115
107
  # Signs the given data.
116
108
  def ssh_do_sign(data)
117
- sig = sign( OpenSSL::Digest::DSS1.new, data)
118
- a1sig = OpenSSL::ASN1.decode( sig )
109
+ sig = sign(OpenSSL::Digest::SHA1.new, data)
110
+ a1sig = OpenSSL::ASN1.decode(sig)
119
111
 
120
112
  sig_r = a1sig.value[0].value.to_s(2)
121
113
  sig_s = a1sig.value[1].value.to_s(2)
122
114
 
123
- if sig_r.length > 20 || sig_s.length > 20
124
- raise OpenSSL::PKey::DSAError, "bad sig size"
125
- end
115
+ raise OpenSSL::PKey::DSAError, "bad sig size" if sig_r.length > 20 || sig_s.length > 20
126
116
 
127
- sig_r = "\0" * ( 20 - sig_r.length ) + sig_r if sig_r.length < 20
128
- sig_s = "\0" * ( 20 - sig_s.length ) + sig_s if sig_s.length < 20
117
+ sig_r = "\0" * (20 - sig_r.length) + sig_r if sig_r.length < 20
118
+ sig_s = "\0" * (20 - sig_s.length) + sig_s if sig_s.length < 20
129
119
 
130
120
  return sig_r + sig_s
131
121
  end
132
122
  end
133
123
 
134
- if defined?(OpenSSL::PKey::EC)
135
- # This class is originally defined in the OpenSSL module. As needed, methods
136
- # have been added to it by the Net::SSH module for convenience in dealing
137
- # with SSH functionality.
138
- class EC
139
- CurveNameAlias = {
140
- "nistp256" => "prime256v1",
141
- "nistp384" => "secp384r1",
142
- "nistp521" => "secp521r1",
143
- }
144
-
145
- CurveNameAliasInv = {
146
- "prime256v1" => "nistp256",
147
- "secp384r1" => "nistp384",
148
- "secp521r1" => "nistp521",
149
- }
150
-
151
- def self.read_keyblob(curve_name_in_type, buffer)
152
- curve_name_in_key = buffer.read_string
153
- unless curve_name_in_type == curve_name_in_key
154
- raise Net::SSH::Exception, "curve name mismatched (`#{curve_name_in_key}' with `#{curve_name_in_type}')"
155
- end
156
- public_key_oct = buffer.read_string
157
- begin
158
- key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
159
- group = key.group
160
- point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
161
- key.public_key = point
162
-
163
- return key
164
- rescue OpenSSL::PKey::ECError
165
- raise NotImplementedError, "unsupported key type `#{type}'"
166
- end
167
-
124
+ # This class is originally defined in the OpenSSL module. As needed, methods
125
+ # have been added to it by the Net::SSH module for convenience in dealing
126
+ # with SSH functionality.
127
+ class EC
128
+ CurveNameAlias = {
129
+ 'nistp256' => 'prime256v1',
130
+ 'nistp384' => 'secp384r1',
131
+ 'nistp521' => 'secp521r1'
132
+ }.freeze
133
+
134
+ CurveNameAliasInv = {
135
+ 'prime256v1' => 'nistp256',
136
+ 'secp384r1' => 'nistp384',
137
+ 'secp521r1' => 'nistp521'
138
+ }.freeze
139
+
140
+ def self.read_keyblob(curve_name_in_type, buffer)
141
+ curve_name_in_key = buffer.read_string
142
+
143
+ unless curve_name_in_type == curve_name_in_key
144
+ raise Net::SSH::Exception, "curve name mismatched (`#{curve_name_in_key}' with `#{curve_name_in_type}')"
168
145
  end
169
146
 
170
- # Returns the description of this key type used by the
171
- # SSH2 protocol, like "ecdsa-sha2-nistp256"
172
- def ssh_type
173
- "ecdsa-sha2-#{CurveNameAliasInv[self.group.curve_name]}"
174
- end
147
+ public_key_oct = buffer.read_string
148
+ begin
149
+ key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
150
+ group = key.group
151
+ point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
152
+ key.public_key = point
175
153
 
176
- def ssh_signature_type
177
- ssh_type
154
+ return key
155
+ rescue OpenSSL::PKey::ECError
156
+ raise NotImplementedError, "unsupported key type `#{type}'"
178
157
  end
158
+ end
179
159
 
180
- def digester
181
- if self.group.curve_name =~ /^[a-z]+(\d+)\w*\z/
182
- curve_size = $1.to_i
183
- if curve_size <= 256
184
- OpenSSL::Digest::SHA256.new
185
- elsif curve_size <= 384
186
- OpenSSL::Digest::SHA384.new
187
- else
188
- OpenSSL::Digest::SHA512.new
189
- end
190
- else
160
+ # Returns the description of this key type used by the
161
+ # SSH2 protocol, like "ecdsa-sha2-nistp256"
162
+ def ssh_type
163
+ "ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
164
+ end
165
+
166
+ def ssh_signature_type
167
+ ssh_type
168
+ end
169
+
170
+ def digester
171
+ if group.curve_name =~ /^[a-z]+(\d+)\w*\z/
172
+ curve_size = Regexp.last_match(1).to_i
173
+ if curve_size <= 256
191
174
  OpenSSL::Digest::SHA256.new
175
+ elsif curve_size <= 384
176
+ OpenSSL::Digest::SHA384.new
177
+ else
178
+ OpenSSL::Digest::SHA512.new
192
179
  end
180
+ else
181
+ OpenSSL::Digest::SHA256.new
193
182
  end
194
- private :digester
183
+ end
184
+ private :digester
195
185
 
196
- # Converts the key to a blob, according to the SSH2 protocol.
197
- def to_blob
198
- @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
199
- :string, CurveNameAliasInv[self.group.curve_name],
200
- :mstring, self.public_key.to_bn.to_s(2)).to_s
201
- @blob
202
- end
186
+ # Converts the key to a blob, according to the SSH2 protocol.
187
+ def to_blob
188
+ @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
189
+ :string, CurveNameAliasInv[group.curve_name],
190
+ :mstring, public_key.to_bn.to_s(2)).to_s
191
+ @blob
192
+ end
203
193
 
204
- # Verifies the given signature matches the given data.
205
- def ssh_do_verify(sig, data)
206
- digest = digester.digest(data)
207
- a1sig = nil
194
+ # Verifies the given signature matches the given data.
195
+ def ssh_do_verify(sig, data)
196
+ digest = digester.digest(data)
197
+ a1sig = nil
208
198
 
209
- begin
210
- sig_r_len = sig[0,4].unpack("H*")[0].to_i(16)
211
- sig_l_len = sig[4+sig_r_len,4].unpack("H*")[0].to_i(16)
199
+ begin
200
+ sig_r_len = sig[0, 4].unpack('H*')[0].to_i(16)
201
+ sig_l_len = sig[4 + sig_r_len, 4].unpack('H*')[0].to_i(16)
212
202
 
213
- sig_r = sig[4,sig_r_len].unpack("H*")[0]
214
- sig_s = sig[4+sig_r_len+4,sig_l_len].unpack("H*")[0]
203
+ sig_r = sig[4, sig_r_len].unpack('H*')[0]
204
+ sig_s = sig[4 + sig_r_len + 4, sig_l_len].unpack('H*')[0]
215
205
 
216
- a1sig = OpenSSL::ASN1::Sequence([
217
- OpenSSL::ASN1::Integer(sig_r.to_i(16)),
218
- OpenSSL::ASN1::Integer(sig_s.to_i(16)),
219
- ])
220
- rescue
221
- end
206
+ a1sig = OpenSSL::ASN1::Sequence([
207
+ OpenSSL::ASN1::Integer(sig_r.to_i(16)),
208
+ OpenSSL::ASN1::Integer(sig_s.to_i(16))
209
+ ])
210
+ rescue StandardError
211
+ end
222
212
 
223
- if a1sig == nil
224
- return false
225
- else
226
- dsa_verify_asn1(digest, a1sig.to_der)
227
- end
213
+ if a1sig.nil?
214
+ return false
215
+ else
216
+ dsa_verify_asn1(digest, a1sig.to_der)
228
217
  end
218
+ end
229
219
 
230
- # Returns the signature for the given data.
231
- def ssh_do_sign(data)
232
- digest = digester.digest(data)
233
- sig = dsa_sign_asn1(digest)
234
- a1sig = OpenSSL::ASN1.decode( sig )
220
+ # Returns the signature for the given data.
221
+ def ssh_do_sign(data)
222
+ digest = digester.digest(data)
223
+ sig = dsa_sign_asn1(digest)
224
+ a1sig = OpenSSL::ASN1.decode(sig)
235
225
 
236
- sig_r = a1sig.value[0].value
237
- sig_s = a1sig.value[1].value
226
+ sig_r = a1sig.value[0].value
227
+ sig_s = a1sig.value[1].value
238
228
 
239
- return Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
240
- end
229
+ Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
241
230
  end
242
- else
243
- class OpenSSL::PKey::ECError < RuntimeError
244
- # for compatibility with interpreters
245
- # without EC support (i.e. JRuby)
231
+
232
+ class Point
233
+ # Returns the description of this key type used by the
234
+ # SSH2 protocol, like "ecdsa-sha2-nistp256"
235
+ def ssh_type
236
+ "ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
237
+ end
238
+
239
+ # Converts the key to a blob, according to the SSH2 protocol.
240
+ def to_blob
241
+ @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
242
+ :string, CurveNameAliasInv[group.curve_name],
243
+ :mstring, to_bn.to_s(2)).to_s
244
+ @blob
245
+ end
246
246
  end
247
247
  end
248
248
  end