net-ssh 4.2.0 → 7.0.1

Sign up to get free protection for your applications and to get access to all the features.
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,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,28 +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
- if defined?(DiffieHellmanGroupExchangeSHA256)
16
- MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256
17
- end
18
- if defined?(OpenSSL::PKey::EC)
19
- require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
20
- require 'net/ssh/transport/kex/ecdh_sha2_nistp384'
21
- require 'net/ssh/transport/kex/ecdh_sha2_nistp521'
22
25
 
23
- MAP['ecdh-sha2-nistp256'] = EcdhSHA2NistP256
24
- MAP['ecdh-sha2-nistp384'] = EcdhSHA2NistP384
25
- 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
26
29
  end
27
30
  end
28
31
  end
@@ -1,27 +1,30 @@
1
- module Net; module SSH; module Transport
2
- module KeyExpander
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
3
11
 
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 ""
9
- end
12
+ k = start[0, bytes]
13
+ return k if k.length >= bytes
10
14
 
11
- k = start[0, bytes]
12
- return k if k.length >= bytes
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'
13
18
 
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'
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
17
24
 
18
- while k.length < bytes
19
- step = digester.digest(shared + hash + k)
20
- bytes_needed = bytes - k.length
21
- k << step[0, bytes_needed]
25
+ return k
26
+ end
27
+ end
22
28
  end
23
-
24
- return k
25
- end
26
29
  end
27
- end; end; end
30
+ end
@@ -1,13 +1,11 @@
1
- # -*- coding: utf-8 -*-
2
1
  require 'openssl'
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.
9
8
  class BN
10
-
11
9
  # Converts a BN object to a string. The format used is that which is
12
10
  # required by the SSH2 protocol.
13
11
  def to_ssh
@@ -16,53 +14,45 @@ module OpenSSL
16
14
  else
17
15
  buf = to_s(2)
18
16
  if buf.getbyte(0)[7] == 1
19
- return [buf.length+1, 0, buf].pack("NCA*")
17
+ return [buf.length + 1, 0, buf].pack("NCA*")
20
18
  else
21
19
  return [buf.length, buf].pack("NA*")
22
20
  end
23
21
  end
24
22
  end
25
-
26
23
  end
27
24
 
28
25
  module PKey
29
-
30
26
  class PKey
31
- def fingerprint
32
- @fingerprint ||= OpenSSL::Digest::MD5.hexdigest(to_blob).scan(/../).join(":")
33
- end
27
+ include Net::SSH::Authentication::PubKeyFingerprint
34
28
  end
35
29
 
36
30
  # This class is originally defined in the OpenSSL module. As needed, methods
37
31
  # have been added to it by the Net::SSH module for convenience in dealing
38
32
  # with SSH functionality.
39
33
  class DH
40
-
41
34
  # Determines whether the pub_key for this key is valid. (This algorithm
42
35
  # lifted more-or-less directly from OpenSSH, dh.c, dh_pub_is_valid.)
43
36
  def valid?
44
37
  return false if pub_key.nil? || pub_key < 0
38
+
45
39
  bits_set = 0
46
40
  pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set?(i) }
47
- return ( bits_set > 1 && pub_key < p )
41
+ return (bits_set > 1 && pub_key < p)
48
42
  end
49
-
50
43
  end
51
44
 
52
45
  # This class is originally defined in the OpenSSL module. As needed, methods
53
46
  # have been added to it by the Net::SSH module for convenience in dealing
54
47
  # with SSH functionality.
55
48
  class RSA
56
-
57
49
  # Returns "ssh-rsa", which is the description of this key type used by the
58
50
  # SSH2 protocol.
59
51
  def ssh_type
60
52
  "ssh-rsa"
61
53
  end
62
54
 
63
- def ssh_signature_type
64
- ssh_type
65
- end
55
+ alias ssh_signature_type ssh_type
66
56
 
67
57
  # Converts the key to a blob, according to the SSH2 protocol.
68
58
  def to_blob
@@ -70,13 +60,30 @@ module OpenSSL
70
60
  end
71
61
 
72
62
  # Verifies the given signature matches the given data.
73
- def ssh_do_verify(sig, data)
74
- 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)
75
74
  end
76
75
 
77
76
  # Returns the signature for the given data.
78
- def ssh_do_sign(data)
79
- 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)
80
87
  end
81
88
  end
82
89
 
@@ -84,166 +91,184 @@ module OpenSSL
84
91
  # have been added to it by the Net::SSH module for convenience in dealing
85
92
  # with SSH functionality.
86
93
  class DSA
87
-
88
94
  # Returns "ssh-dss", which is the description of this key type used by the
89
95
  # SSH2 protocol.
90
96
  def ssh_type
91
97
  "ssh-dss"
92
98
  end
93
99
 
94
- def ssh_signature_type
95
- ssh_type
96
- end
100
+ alias ssh_signature_type ssh_type
97
101
 
98
102
  # Converts the key to a blob, according to the SSH2 protocol.
99
103
  def to_blob
100
104
  @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
101
- :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
105
+ :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
102
106
  end
103
107
 
104
108
  # Verifies the given signature matches the given data.
105
- def ssh_do_verify(sig, data)
106
- sig_r = sig[0,20].unpack("H*")[0].to_i(16)
107
- 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)
108
112
  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)
113
+ OpenSSL::ASN1::Integer(sig_r),
114
+ OpenSSL::ASN1::Integer(sig_s)
115
+ ])
116
+ return verify(OpenSSL::Digest::SHA1.new, a1sig.to_der, data)
113
117
  end
114
118
 
115
119
  # Signs the given data.
116
- def ssh_do_sign(data)
117
- sig = sign( OpenSSL::Digest::DSS1.new, data)
118
- a1sig = OpenSSL::ASN1.decode( sig )
120
+ def ssh_do_sign(data, sig_alg = nil)
121
+ sig = sign(OpenSSL::Digest::SHA1.new, data)
122
+ a1sig = OpenSSL::ASN1.decode(sig)
119
123
 
120
124
  sig_r = a1sig.value[0].value.to_s(2)
121
125
  sig_s = a1sig.value[1].value.to_s(2)
122
126
 
123
- if sig_r.length > 20 || sig_s.length > 20
124
- raise OpenSSL::PKey::DSAError, "bad sig size"
125
- end
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
126
129
 
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
130
+ sig_r = "\0" * (20 - sig_r.length) + sig_r if sig_r.length < 20
131
+ sig_s = "\0" * (20 - sig_s.length) + sig_s if sig_s.length < 20
129
132
 
130
133
  return sig_r + sig_s
131
134
  end
132
135
  end
133
136
 
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
-
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}')"
168
158
  end
169
159
 
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]}"
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}'"
174
182
  end
183
+ end
175
184
 
176
- def ssh_signature_type
177
- ssh_type
178
- 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
179
190
 
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
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
191
197
  OpenSSL::Digest::SHA256.new
198
+ elsif curve_size <= 384
199
+ OpenSSL::Digest::SHA384.new
200
+ else
201
+ OpenSSL::Digest::SHA512.new
192
202
  end
203
+ else
204
+ OpenSSL::Digest::SHA256.new
193
205
  end
194
- private :digester
206
+ end
207
+ private :digester
195
208
 
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
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
202
234
  end
203
235
 
204
- # Verifies the given signature matches the given data.
205
- def ssh_do_verify(sig, data)
206
- digest = digester.digest(data)
207
- a1sig = nil
236
+ if a1sig.nil?
237
+ return false
238
+ else
239
+ dsa_verify_asn1(digest, a1sig.to_der)
240
+ end
241
+ end
208
242
 
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)
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)
212
248
 
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]
249
+ sig_r = a1sig.value[0].value
250
+ sig_s = a1sig.value[1].value
215
251
 
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
252
+ Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
253
+ end
222
254
 
223
- if a1sig == nil
224
- return false
225
- else
226
- dsa_verify_asn1(digest, a1sig.to_der)
227
- 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]}"
228
260
  end
229
261
 
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 )
262
+ alias ssh_signature_type ssh_type
235
263
 
236
- sig_r = a1sig.value[0].value
237
- sig_s = a1sig.value[1].value
238
-
239
- 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
240
270
  end
241
271
  end
242
- else
243
- class OpenSSL::PKey::ECError < RuntimeError
244
- # for compatibility with interpreters
245
- # without EC support (i.e. JRuby)
246
- end
247
272
  end
248
273
  end
249
274
  end