net-ssh 5.0.2 → 7.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -1,97 +1,36 @@
1
- require 'net/ssh/transport/constants'
2
- require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
1
+ require 'net/ssh/transport/kex/abstract5656'
3
2
 
4
- module Net
5
- module SSH
6
- module Transport
3
+ module Net
4
+ module SSH
5
+ module Transport
7
6
  module Kex
8
-
9
7
  # A key-exchange service implementing the "ecdh-sha2-nistp256"
10
8
  # key-exchange algorithm. (defined in RFC 5656)
11
- class EcdhSHA2NistP256 < DiffieHellmanGroup1SHA1
12
- include Loggable
13
- include Constants
14
-
15
- attr_reader :ecdh
16
-
9
+ class EcdhSHA2NistP256 < Abstract5656
17
10
  def digester
18
11
  OpenSSL::Digest::SHA256
19
12
  end
20
-
13
+
21
14
  def curve_name
22
15
  OpenSSL::PKey::EC::CurveNameAlias['nistp256']
23
16
  end
24
-
25
- def initialize(algorithms, connection, data)
26
- @algorithms = algorithms
27
- @connection = connection
28
-
29
- @digester = digester
30
- @data = data.dup
31
- @ecdh = generate_key
32
- @logger = @data.delete(:logger)
33
- end
34
-
17
+
35
18
  private
36
-
37
- def get_message_types
38
- [KEXECDH_INIT, KEXECDH_REPLY]
39
- end
40
-
41
- def build_signature_buffer(result)
42
- response = Net::SSH::Buffer.new
43
- response.write_string data[:client_version_string],
44
- data[:server_version_string],
45
- data[:client_algorithm_packet],
46
- data[:server_algorithm_packet],
47
- result[:key_blob],
48
- ecdh.public_key.to_bn.to_s(2),
49
- result[:server_ecdh_pubkey]
50
- response.write_bignum result[:shared_secret]
51
- response
52
- end
53
-
54
- def generate_key #:nodoc:
55
- OpenSSL::PKey::EC.new(curve_name).generate_key
19
+
20
+ def generate_key # :nodoc:
21
+ OpenSSL::PKey::EC.generate(curve_name)
56
22
  end
57
-
58
- def send_kexinit #:nodoc:
59
- init, reply = get_message_types
60
-
61
- # send the KEXECDH_INIT message
62
- ## byte SSH_MSG_KEX_ECDH_INIT
63
- ## string Q_C, client's ephemeral public key octet string
64
- buffer = Net::SSH::Buffer.from(:byte, init, :mstring, ecdh.public_key.to_bn.to_s(2))
65
- connection.send_message(buffer)
66
-
67
- # expect the following KEXECDH_REPLY message
68
- ## byte SSH_MSG_KEX_ECDH_REPLY
69
- ## string K_S, server's public host key
70
- ## string Q_S, server's ephemeral public key octet string
71
- ## string the signature on the exchange hash
72
- buffer = connection.next_message
73
- raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
74
-
75
- result = Hash.new
76
- result[:key_blob] = buffer.read_string
77
- result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
78
- result[:server_ecdh_pubkey] = buffer.read_string
79
-
80
- # compute shared secret from server's public key and client's private key
23
+
24
+ # compute shared secret from server's public key and client's private key
25
+ def compute_shared_secret(server_ecdh_pubkey)
81
26
  pk = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(curve_name).group,
82
- OpenSSL::BN.new(result[:server_ecdh_pubkey], 2))
83
- result[:shared_secret] = OpenSSL::BN.new(ecdh.dh_compute_key(pk), 2)
84
-
85
- sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
86
- sig_type = sig_buffer.read_string
87
- if sig_type != algorithms.host_key_format
88
- raise Net::SSH::Exception,
89
- "host key algorithm mismatch for signature " +
90
- "'#{sig_type}' != '#{algorithms.host_key_format}'"
91
- end
92
- result[:server_sig] = sig_buffer.read_string
93
-
94
- return result
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)
95
34
  end
96
35
  end
97
36
  end
@@ -1,8 +1,9 @@
1
- module Net
2
- module SSH
3
- module Transport
4
- module Kex
1
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
5
2
 
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
6
7
  # A key-exchange service implementing the "ecdh-sha2-nistp256"
7
8
  # key-exchange algorithm. (defined in RFC 5656)
8
9
  class EcdhSHA2NistP384 < EcdhSHA2NistP256
@@ -1,8 +1,9 @@
1
- module Net
2
- module SSH
3
- module Transport
4
- module Kex
1
+ require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
5
2
 
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ module Kex
6
7
  # A key-exchange service implementing the "ecdh-sha2-nistp521"
7
8
  # key-exchange algorithm. (defined in RFC 5656)
8
9
  class EcdhSHA2NistP521 < EcdhSHA2NistP256
@@ -1,26 +1,31 @@
1
1
  require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
2
2
  require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
3
+ require 'net/ssh/transport/kex/diffie_hellman_group14_sha256'
3
4
  require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
4
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'
5
10
 
6
11
  module Net::SSH::Transport
7
12
  module Kex
8
13
  # Maps the supported key-exchange algorithms as named by the SSH protocol
9
14
  # to their corresponding implementors.
10
15
  MAP = {
16
+ 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
17
+ 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1,
18
+ 'diffie-hellman-group14-sha256' => DiffieHellmanGroup14SHA256,
11
19
  'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
12
- 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
13
- 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1
20
+ 'diffie-hellman-group-exchange-sha256' => DiffieHellmanGroupExchangeSHA256,
21
+ 'ecdh-sha2-nistp256' => EcdhSHA2NistP256,
22
+ 'ecdh-sha2-nistp384' => EcdhSHA2NistP384,
23
+ 'ecdh-sha2-nistp521' => EcdhSHA2NistP521
14
24
  }
15
- MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256 if defined?(DiffieHellmanGroupExchangeSHA256)
16
- if defined?(OpenSSL::PKey::EC)
17
- require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
18
- require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
19
- require 'net/ssh/transport/kex/ecdh_sha2_nistp521'
20
25
 
21
- MAP['ecdh-sha2-nistp256'] = EcdhSHA2NistP256
22
- MAP['ecdh-sha2-nistp384'] = EcdhSHA2NistP384
23
- MAP['ecdh-sha2-nistp521'] = EcdhSHA2NistP521
26
+ if Net::SSH::Transport::Kex::Curve25519Sha256Loader::LOADED
27
+ MAP['curve25519-sha256'] = Curve25519Sha256
28
+ MAP['curve25519-sha256@libssh.org'] = Curve25519Sha256
24
29
  end
25
30
  end
26
31
  end
@@ -1,28 +1,27 @@
1
- module Net
2
- module SSH
1
+ module Net
2
+ module SSH
3
3
  module Transport
4
4
  module KeyExpander
5
-
6
5
  # Generate a key value in accordance with the SSH2 specification.
7
6
  # (RFC4253 7.2. "Output from Key Exchange")
8
- def self.expand_key(bytes, start, options={})
7
+ def self.expand_key(bytes, start, options = {})
9
8
  if bytes == 0
10
9
  return ""
11
10
  end
12
-
11
+
13
12
  k = start[0, bytes]
14
13
  return k if k.length >= bytes
15
-
14
+
16
15
  digester = options[:digester] or raise 'No digester supplied'
17
16
  shared = options[:shared] or raise 'No shared secret supplied'
18
17
  hash = options[:hash] or raise 'No hash supplied'
19
-
18
+
20
19
  while k.length < bytes
21
20
  step = digester.digest(shared + hash + k)
22
21
  bytes_needed = bytes - k.length
23
22
  k << step[0, bytes_needed]
24
23
  end
25
-
24
+
26
25
  return k
27
26
  end
28
27
  end
@@ -2,7 +2,6 @@ require 'openssl'
2
2
  require 'net/ssh/authentication/pub_key_fingerprint'
3
3
 
4
4
  module OpenSSL
5
-
6
5
  # This class is originally defined in the OpenSSL module. As needed, methods
7
6
  # have been added to it by the Net::SSH module for convenience in dealing with
8
7
  # SSH functionality.
@@ -24,7 +23,6 @@ module OpenSSL
24
23
  end
25
24
 
26
25
  module PKey
27
-
28
26
  class PKey
29
27
  include Net::SSH::Authentication::PubKeyFingerprint
30
28
  end
@@ -37,6 +35,7 @@ module OpenSSL
37
35
  # lifted more-or-less directly from OpenSSH, dh.c, dh_pub_is_valid.)
38
36
  def valid?
39
37
  return false if pub_key.nil? || pub_key < 0
38
+
40
39
  bits_set = 0
41
40
  pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set?(i) }
42
41
  return (bits_set > 1 && pub_key < p)
@@ -53,9 +52,7 @@ module OpenSSL
53
52
  "ssh-rsa"
54
53
  end
55
54
 
56
- def ssh_signature_type
57
- ssh_type
58
- end
55
+ alias ssh_signature_type ssh_type
59
56
 
60
57
  # Converts the key to a blob, according to the SSH2 protocol.
61
58
  def to_blob
@@ -63,13 +60,30 @@ module OpenSSL
63
60
  end
64
61
 
65
62
  # Verifies the given signature matches the given data.
66
- def ssh_do_verify(sig, data)
67
- verify(OpenSSL::Digest::SHA1.new, sig, data)
63
+ def ssh_do_verify(sig, data, options = {})
64
+ digester =
65
+ if options[:host_key] == "rsa-sha2-512"
66
+ OpenSSL::Digest::SHA512.new
67
+ elsif options[:host_key] == "rsa-sha2-256"
68
+ OpenSSL::Digest::SHA256.new
69
+ else
70
+ OpenSSL::Digest::SHA1.new
71
+ end
72
+
73
+ verify(digester, sig, data)
68
74
  end
69
75
 
70
76
  # Returns the signature for the given data.
71
- def ssh_do_sign(data)
72
- sign(OpenSSL::Digest::SHA1.new, data)
77
+ def ssh_do_sign(data, sig_alg = nil)
78
+ digester =
79
+ if sig_alg == "rsa-sha2-512"
80
+ OpenSSL::Digest::SHA512.new
81
+ elsif sig_alg == "rsa-sha2-256"
82
+ OpenSSL::Digest::SHA256.new
83
+ else
84
+ OpenSSL::Digest::SHA1.new
85
+ end
86
+ sign(digester, data)
73
87
  end
74
88
  end
75
89
 
@@ -83,36 +97,35 @@ module OpenSSL
83
97
  "ssh-dss"
84
98
  end
85
99
 
86
- def ssh_signature_type
87
- ssh_type
88
- end
100
+ alias ssh_signature_type ssh_type
89
101
 
90
102
  # Converts the key to a blob, according to the SSH2 protocol.
91
103
  def to_blob
92
104
  @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
93
- :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
105
+ :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
94
106
  end
95
107
 
96
108
  # Verifies the given signature matches the given data.
97
- def ssh_do_verify(sig, data)
98
- sig_r = sig[0,20].unpack("H*")[0].to_i(16)
99
- sig_s = sig[20,20].unpack("H*")[0].to_i(16)
109
+ def ssh_do_verify(sig, data, options = {})
110
+ sig_r = sig[0, 20].unpack("H*")[0].to_i(16)
111
+ sig_s = sig[20, 20].unpack("H*")[0].to_i(16)
100
112
  a1sig = OpenSSL::ASN1::Sequence([
101
- OpenSSL::ASN1::Integer(sig_r),
102
- OpenSSL::ASN1::Integer(sig_s)
103
- ])
113
+ OpenSSL::ASN1::Integer(sig_r),
114
+ OpenSSL::ASN1::Integer(sig_s)
115
+ ])
104
116
  return verify(OpenSSL::Digest::SHA1.new, a1sig.to_der, data)
105
117
  end
106
118
 
107
119
  # Signs the given data.
108
- def ssh_do_sign(data)
120
+ def ssh_do_sign(data, sig_alg = nil)
109
121
  sig = sign(OpenSSL::Digest::SHA1.new, data)
110
122
  a1sig = OpenSSL::ASN1.decode(sig)
111
123
 
112
124
  sig_r = a1sig.value[0].value.to_s(2)
113
125
  sig_s = a1sig.value[1].value.to_s(2)
114
126
 
115
- raise OpenSSL::PKey::DSAError, "bad sig size" if sig_r.length > 20 || sig_s.length > 20
127
+ sig_size = params["q"].num_bits / 8
128
+ raise OpenSSL::PKey::DSAError, "bad sig size" if sig_r.length > sig_size || sig_s.length > sig_size
116
129
 
117
130
  sig_r = "\0" * (20 - sig_r.length) + sig_r if sig_r.length < 20
118
131
  sig_s = "\0" * (20 - sig_s.length) + sig_s if sig_s.length < 20
@@ -121,116 +134,141 @@ module OpenSSL
121
134
  end
122
135
  end
123
136
 
124
- if defined?(OpenSSL::PKey::EC)
125
- # This class is originally defined in the OpenSSL module. As needed, methods
126
- # have been added to it by the Net::SSH module for convenience in dealing
127
- # with SSH functionality.
128
- class EC
129
- CurveNameAlias = {
130
- "nistp256" => "prime256v1",
131
- "nistp384" => "secp384r1",
132
- "nistp521" => "secp521r1"
133
- }
134
-
135
- CurveNameAliasInv = {
136
- "prime256v1" => "nistp256",
137
- "secp384r1" => "nistp384",
138
- "secp521r1" => "nistp521"
139
- }
140
-
141
- def self.read_keyblob(curve_name_in_type, buffer)
142
- curve_name_in_key = buffer.read_string
143
- raise Net::SSH::Exception, "curve name mismatched (`#{curve_name_in_key}' with `#{curve_name_in_type}')" unless curve_name_in_type == curve_name_in_key
144
- public_key_oct = buffer.read_string
145
- begin
146
- key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
147
- group = key.group
148
- point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
149
- key.public_key = point
150
-
151
- return key
152
- rescue OpenSSL::PKey::ECError
153
- raise NotImplementedError, "unsupported key type `#{type}'"
154
- end
137
+ # This class is originally defined in the OpenSSL module. As needed, methods
138
+ # have been added to it by the Net::SSH module for convenience in dealing
139
+ # with SSH functionality.
140
+ class EC
141
+ CurveNameAlias = {
142
+ 'nistp256' => 'prime256v1',
143
+ 'nistp384' => 'secp384r1',
144
+ 'nistp521' => 'secp521r1'
145
+ }.freeze
146
+
147
+ CurveNameAliasInv = {
148
+ 'prime256v1' => 'nistp256',
149
+ 'secp384r1' => 'nistp384',
150
+ 'secp521r1' => 'nistp521'
151
+ }.freeze
152
+
153
+ def self.read_keyblob(curve_name_in_type, buffer)
154
+ curve_name_in_key = buffer.read_string
155
+
156
+ unless curve_name_in_type == curve_name_in_key
157
+ raise Net::SSH::Exception, "curve name mismatched (`#{curve_name_in_key}' with `#{curve_name_in_type}')"
155
158
  end
156
159
 
157
- # Returns the description of this key type used by the
158
- # SSH2 protocol, like "ecdsa-sha2-nistp256"
159
- def ssh_type
160
- "ecdsa-sha2-#{CurveNameAliasInv[self.group.curve_name]}"
160
+ public_key_oct = buffer.read_string
161
+ begin
162
+ curvename = OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key]
163
+ group = OpenSSL::PKey::EC::Group.new(curvename)
164
+ point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
165
+ asn1 = OpenSSL::ASN1::Sequence(
166
+ [
167
+ OpenSSL::ASN1::Sequence(
168
+ [
169
+ OpenSSL::ASN1::ObjectId("id-ecPublicKey"),
170
+ OpenSSL::ASN1::ObjectId(curvename)
171
+ ]
172
+ ),
173
+ OpenSSL::ASN1::BitString(point.to_octet_string(:uncompressed))
174
+ ]
175
+ )
176
+
177
+ key = OpenSSL::PKey::EC.new(asn1.to_der)
178
+
179
+ return key
180
+ rescue OpenSSL::PKey::ECError
181
+ raise NotImplementedError, "unsupported key type `#{type}'"
161
182
  end
183
+ end
162
184
 
163
- def ssh_signature_type
164
- ssh_type
165
- end
185
+ # Returns the description of this key type used by the
186
+ # SSH2 protocol, like "ecdsa-sha2-nistp256"
187
+ def ssh_type
188
+ "ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
189
+ end
166
190
 
167
- def digester
168
- if self.group.curve_name =~ /^[a-z]+(\d+)\w*\z/
169
- curve_size = $1.to_i
170
- if curve_size <= 256
171
- OpenSSL::Digest::SHA256.new
172
- elsif curve_size <= 384
173
- OpenSSL::Digest::SHA384.new
174
- else
175
- OpenSSL::Digest::SHA512.new
176
- end
177
- else
191
+ alias ssh_signature_type ssh_type
192
+
193
+ def digester
194
+ if group.curve_name =~ /^[a-z]+(\d+)\w*\z/
195
+ curve_size = Regexp.last_match(1).to_i
196
+ if curve_size <= 256
178
197
  OpenSSL::Digest::SHA256.new
198
+ elsif curve_size <= 384
199
+ OpenSSL::Digest::SHA384.new
200
+ else
201
+ OpenSSL::Digest::SHA512.new
179
202
  end
203
+ else
204
+ OpenSSL::Digest::SHA256.new
180
205
  end
181
- private :digester
206
+ end
207
+ private :digester
182
208
 
183
- # Converts the key to a blob, according to the SSH2 protocol.
184
- def to_blob
185
- @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
186
- :string, CurveNameAliasInv[self.group.curve_name],
187
- :mstring, self.public_key.to_bn.to_s(2)).to_s
188
- @blob
209
+ # Converts the key to a blob, according to the SSH2 protocol.
210
+ def to_blob
211
+ @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
212
+ :string, CurveNameAliasInv[group.curve_name],
213
+ :mstring, public_key.to_bn.to_s(2)).to_s
214
+ @blob
215
+ end
216
+
217
+ # Verifies the given signature matches the given data.
218
+ def ssh_do_verify(sig, data, options = {})
219
+ digest = digester.digest(data)
220
+ a1sig = nil
221
+
222
+ begin
223
+ sig_r_len = sig[0, 4].unpack('H*')[0].to_i(16)
224
+ sig_l_len = sig[4 + sig_r_len, 4].unpack('H*')[0].to_i(16)
225
+
226
+ sig_r = sig[4, sig_r_len].unpack('H*')[0]
227
+ sig_s = sig[4 + sig_r_len + 4, sig_l_len].unpack('H*')[0]
228
+
229
+ a1sig = OpenSSL::ASN1::Sequence([
230
+ OpenSSL::ASN1::Integer(sig_r.to_i(16)),
231
+ OpenSSL::ASN1::Integer(sig_s.to_i(16))
232
+ ])
233
+ rescue StandardError
189
234
  end
190
235
 
191
- # Verifies the given signature matches the given data.
192
- def ssh_do_verify(sig, data)
193
- digest = digester.digest(data)
194
- a1sig = nil
236
+ if a1sig.nil?
237
+ return false
238
+ else
239
+ dsa_verify_asn1(digest, a1sig.to_der)
240
+ end
241
+ end
195
242
 
196
- begin
197
- sig_r_len = sig[0,4].unpack("H*")[0].to_i(16)
198
- sig_l_len = sig[4 + sig_r_len,4].unpack("H*")[0].to_i(16)
243
+ # Returns the signature for the given data.
244
+ def ssh_do_sign(data, sig_alg = nil)
245
+ digest = digester.digest(data)
246
+ sig = dsa_sign_asn1(digest)
247
+ a1sig = OpenSSL::ASN1.decode(sig)
199
248
 
200
- sig_r = sig[4,sig_r_len].unpack("H*")[0]
201
- sig_s = sig[4 + sig_r_len + 4,sig_l_len].unpack("H*")[0]
249
+ sig_r = a1sig.value[0].value
250
+ sig_s = a1sig.value[1].value
202
251
 
203
- a1sig = OpenSSL::ASN1::Sequence([
204
- OpenSSL::ASN1::Integer(sig_r.to_i(16)),
205
- OpenSSL::ASN1::Integer(sig_s.to_i(16))
206
- ])
207
- rescue StandardError
208
- end
252
+ Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
253
+ end
209
254
 
210
- if a1sig == nil
211
- return false
212
- else
213
- dsa_verify_asn1(digest, a1sig.to_der)
214
- end
255
+ class Point
256
+ # Returns the description of this key type used by the
257
+ # SSH2 protocol, like "ecdsa-sha2-nistp256"
258
+ def ssh_type
259
+ "ecdsa-sha2-#{CurveNameAliasInv[group.curve_name]}"
215
260
  end
216
261
 
217
- # Returns the signature for the given data.
218
- def ssh_do_sign(data)
219
- digest = digester.digest(data)
220
- sig = dsa_sign_asn1(digest)
221
- a1sig = OpenSSL::ASN1.decode(sig)
222
-
223
- sig_r = a1sig.value[0].value
224
- sig_s = a1sig.value[1].value
262
+ alias ssh_signature_type ssh_type
225
263
 
226
- return Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
264
+ # Converts the key to a blob, according to the SSH2 protocol.
265
+ def to_blob
266
+ @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
267
+ :string, CurveNameAliasInv[group.curve_name],
268
+ :mstring, to_bn.to_s(2)).to_s
269
+ @blob
227
270
  end
228
271
  end
229
- else
230
- class OpenSSL::PKey::ECError < RuntimeError
231
- # for compatibility with interpreters
232
- # without EC support (i.e. JRuby)
233
- end
234
272
  end
235
273
  end
236
274
  end