net-ssh 2.7.0 → 7.3.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.
- checksums.yaml +7 -0
- checksums.yaml.gz.sig +0 -0
- data/.dockerignore +6 -0
- data/.github/FUNDING.yml +1 -0
- data/.github/config/rubocop_linter_action.yml +4 -0
- data/.github/workflows/ci-with-docker.yml +44 -0
- data/.github/workflows/ci.yml +94 -0
- data/.github/workflows/rubocop.yml +16 -0
- data/.gitignore +15 -0
- data/.rubocop.yml +22 -0
- data/.rubocop_todo.yml +1081 -0
- data/CHANGES.txt +387 -0
- data/DEVELOPMENT.md +23 -0
- data/Dockerfile +29 -0
- data/Dockerfile.openssl3 +17 -0
- data/Gemfile +13 -0
- data/Gemfile.noed25519 +12 -0
- data/Gemfile.norbnacl +12 -0
- data/ISSUE_TEMPLATE.md +30 -0
- data/Manifest +4 -5
- data/README.md +303 -0
- data/Rakefile +174 -40
- data/SECURITY.md +4 -0
- data/THANKS.txt +25 -0
- data/appveyor.yml +58 -0
- data/docker-compose.yml +25 -0
- data/lib/net/ssh/authentication/agent.rb +279 -18
- data/lib/net/ssh/authentication/certificate.rb +183 -0
- data/lib/net/ssh/authentication/constants.rb +17 -15
- data/lib/net/ssh/authentication/ed25519.rb +184 -0
- data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
- data/lib/net/ssh/authentication/key_manager.rb +125 -54
- data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
- data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +19 -12
- data/lib/net/ssh/authentication/methods/none.rb +16 -19
- data/lib/net/ssh/authentication/methods/password.rb +56 -19
- data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
- data/lib/net/ssh/authentication/pageant.rb +483 -246
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
- data/lib/net/ssh/authentication/session.rb +138 -120
- data/lib/net/ssh/buffer.rb +399 -300
- data/lib/net/ssh/buffered_io.rb +154 -150
- data/lib/net/ssh/config.rb +361 -166
- data/lib/net/ssh/connection/channel.rb +640 -596
- data/lib/net/ssh/connection/constants.rb +29 -29
- data/lib/net/ssh/connection/event_loop.rb +123 -0
- data/lib/net/ssh/connection/keepalive.rb +59 -0
- data/lib/net/ssh/connection/session.rb +628 -548
- data/lib/net/ssh/connection/term.rb +125 -123
- data/lib/net/ssh/errors.rb +101 -95
- data/lib/net/ssh/key_factory.rb +198 -100
- data/lib/net/ssh/known_hosts.rb +221 -98
- data/lib/net/ssh/loggable.rb +50 -49
- data/lib/net/ssh/packet.rb +83 -79
- data/lib/net/ssh/prompt.rb +50 -81
- data/lib/net/ssh/proxy/command.rb +108 -60
- data/lib/net/ssh/proxy/errors.rb +12 -10
- data/lib/net/ssh/proxy/http.rb +82 -78
- data/lib/net/ssh/proxy/https.rb +50 -0
- data/lib/net/ssh/proxy/jump.rb +54 -0
- data/lib/net/ssh/proxy/socks4.rb +5 -8
- data/lib/net/ssh/proxy/socks5.rb +18 -20
- data/lib/net/ssh/service/forward.rb +383 -255
- data/lib/net/ssh/test/channel.rb +145 -136
- data/lib/net/ssh/test/extensions.rb +131 -110
- data/lib/net/ssh/test/kex.rb +34 -32
- data/lib/net/ssh/test/local_packet.rb +46 -44
- data/lib/net/ssh/test/packet.rb +89 -70
- data/lib/net/ssh/test/remote_packet.rb +32 -30
- data/lib/net/ssh/test/script.rb +156 -142
- data/lib/net/ssh/test/socket.rb +49 -48
- data/lib/net/ssh/test.rb +82 -77
- data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
- data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
- data/lib/net/ssh/transport/algorithms.rb +472 -348
- data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
- data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
- data/lib/net/ssh/transport/cipher_factory.rb +124 -100
- data/lib/net/ssh/transport/constants.rb +32 -24
- data/lib/net/ssh/transport/ctr.rb +42 -22
- data/lib/net/ssh/transport/gcm_cipher.rb +207 -0
- data/lib/net/ssh/transport/hmac/abstract.rb +97 -63
- data/lib/net/ssh/transport/hmac/md5.rb +0 -2
- data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
- data/lib/net/ssh/transport/hmac/none.rb +0 -2
- data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
- data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
- data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
- data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
- data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
- data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
- data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
- data/lib/net/ssh/transport/hmac.rb +14 -12
- data/lib/net/ssh/transport/identity_cipher.rb +54 -44
- data/lib/net/ssh/transport/kex/abstract.rb +130 -0
- data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
- data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
- data/lib/net/ssh/transport/kex.rb +15 -12
- data/lib/net/ssh/transport/key_expander.rb +24 -20
- data/lib/net/ssh/transport/openssl.rb +161 -124
- data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
- data/lib/net/ssh/transport/packet_stream.rb +246 -183
- data/lib/net/ssh/transport/server_version.rb +57 -51
- data/lib/net/ssh/transport/session.rb +307 -235
- data/lib/net/ssh/transport/state.rb +178 -176
- data/lib/net/ssh/verifiers/accept_new.rb +33 -0
- data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
- data/lib/net/ssh/verifiers/always.rb +58 -0
- data/lib/net/ssh/verifiers/never.rb +19 -0
- data/lib/net/ssh/version.rb +57 -51
- data/lib/net/ssh.rb +140 -40
- data/net-ssh-public_cert.pem +21 -0
- data/net-ssh.gemspec +39 -184
- data/support/ssh_tunnel_bug.rb +5 -5
- data.tar.gz.sig +0 -0
- metadata +205 -99
- metadata.gz.sig +0 -0
- data/README.rdoc +0 -219
- data/Rudyfile +0 -96
- data/gem-public_cert.pem +0 -20
- data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
- data/lib/net/ssh/authentication/agent/socket.rb +0 -170
- data/lib/net/ssh/ruby_compat.rb +0 -51
- data/lib/net/ssh/verifiers/lenient.rb +0 -30
- data/lib/net/ssh/verifiers/null.rb +0 -12
- data/lib/net/ssh/verifiers/secure.rb +0 -54
- data/lib/net/ssh/verifiers/strict.rb +0 -24
- data/setup.rb +0 -1585
- data/support/arcfour_check.rb +0 -20
- data/test/README.txt +0 -47
- data/test/authentication/methods/common.rb +0 -28
- data/test/authentication/methods/test_abstract.rb +0 -51
- data/test/authentication/methods/test_hostbased.rb +0 -114
- data/test/authentication/methods/test_keyboard_interactive.rb +0 -100
- data/test/authentication/methods/test_none.rb +0 -41
- data/test/authentication/methods/test_password.rb +0 -52
- data/test/authentication/methods/test_publickey.rb +0 -148
- data/test/authentication/test_agent.rb +0 -205
- data/test/authentication/test_key_manager.rb +0 -218
- data/test/authentication/test_session.rb +0 -108
- data/test/common.rb +0 -108
- data/test/configs/eqsign +0 -3
- data/test/configs/exact_match +0 -8
- data/test/configs/host_plus +0 -10
- data/test/configs/multihost +0 -4
- data/test/configs/nohost +0 -19
- data/test/configs/numeric_host +0 -4
- data/test/configs/send_env +0 -2
- data/test/configs/substitutes +0 -8
- data/test/configs/wild_cards +0 -14
- data/test/connection/test_channel.rb +0 -467
- data/test/connection/test_session.rb +0 -526
- data/test/known_hosts/github +0 -1
- data/test/manual/test_forward.rb +0 -223
- data/test/start/test_options.rb +0 -36
- data/test/start/test_transport.rb +0 -28
- data/test/test_all.rb +0 -11
- data/test/test_buffer.rb +0 -433
- data/test/test_buffered_io.rb +0 -63
- data/test/test_config.rb +0 -151
- data/test/test_key_factory.rb +0 -173
- data/test/test_known_hosts.rb +0 -13
- data/test/transport/hmac/test_md5.rb +0 -41
- data/test/transport/hmac/test_md5_96.rb +0 -27
- data/test/transport/hmac/test_none.rb +0 -34
- data/test/transport/hmac/test_ripemd160.rb +0 -36
- data/test/transport/hmac/test_sha1.rb +0 -36
- data/test/transport/hmac/test_sha1_96.rb +0 -27
- data/test/transport/hmac/test_sha2_256.rb +0 -37
- data/test/transport/hmac/test_sha2_256_96.rb +0 -27
- data/test/transport/hmac/test_sha2_512.rb +0 -37
- data/test/transport/hmac/test_sha2_512_96.rb +0 -27
- data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
- data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -146
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -92
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -34
- data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
- data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
- data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
- data/test/transport/test_algorithms.rb +0 -330
- data/test/transport/test_cipher_factory.rb +0 -443
- data/test/transport/test_hmac.rb +0 -34
- data/test/transport/test_identity_cipher.rb +0 -40
- data/test/transport/test_packet_stream.rb +0 -1755
- data/test/transport/test_server_version.rb +0 -78
- data/test/transport/test_session.rb +0 -319
- data/test/transport/test_state.rb +0 -181
@@ -1,13 +1,21 @@
|
|
1
|
-
|
1
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
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
|
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-
|
13
|
-
'
|
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
|
-
|
24
|
-
MAP['
|
25
|
-
MAP['
|
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,26 +1,30 @@
|
|
1
|
-
module Net
|
2
|
-
module
|
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
|
-
|
5
|
-
|
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
|
-
|
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'
|
12
18
|
|
13
|
-
|
14
|
-
|
15
|
-
|
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
|
16
24
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
k << step[0, bytes_needed]
|
25
|
+
return k
|
26
|
+
end
|
27
|
+
end
|
21
28
|
end
|
22
|
-
|
23
|
-
return k
|
24
|
-
end
|
25
29
|
end
|
26
|
-
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,63 +14,76 @@ 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
|
-
|
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 (
|
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
|
|
55
|
+
alias ssh_signature_type ssh_type
|
56
|
+
|
63
57
|
# Converts the key to a blob, according to the SSH2 protocol.
|
64
58
|
def to_blob
|
65
59
|
@blob ||= Net::SSH::Buffer.from(:string, ssh_type, :bignum, e, :bignum, n).to_s
|
66
60
|
end
|
67
61
|
|
68
62
|
# Verifies the given signature matches the given data.
|
69
|
-
def ssh_do_verify(sig, data)
|
70
|
-
|
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)
|
71
74
|
end
|
72
75
|
|
73
76
|
# Returns the signature for the given data.
|
74
|
-
def ssh_do_sign(data)
|
75
|
-
|
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)
|
76
87
|
end
|
77
88
|
end
|
78
89
|
|
@@ -80,158 +91,184 @@ module OpenSSL
|
|
80
91
|
# have been added to it by the Net::SSH module for convenience in dealing
|
81
92
|
# with SSH functionality.
|
82
93
|
class DSA
|
83
|
-
|
84
94
|
# Returns "ssh-dss", which is the description of this key type used by the
|
85
95
|
# SSH2 protocol.
|
86
96
|
def ssh_type
|
87
97
|
"ssh-dss"
|
88
98
|
end
|
89
99
|
|
100
|
+
alias ssh_signature_type ssh_type
|
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
|
-
|
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
|
-
|
102
|
-
|
103
|
-
|
104
|
-
return verify(OpenSSL::Digest::
|
113
|
+
OpenSSL::ASN1::Integer(sig_r),
|
114
|
+
OpenSSL::ASN1::Integer(sig_s)
|
115
|
+
])
|
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)
|
109
|
-
sig = sign(
|
110
|
-
a1sig = OpenSSL::ASN1.decode(
|
120
|
+
def ssh_do_sign(data, sig_alg = nil)
|
121
|
+
sig = sign(OpenSSL::Digest::SHA1.new, data)
|
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
|
-
|
116
|
-
|
117
|
-
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
|
118
129
|
|
119
|
-
sig_r = "\0" * (
|
120
|
-
sig_s = "\0" * (
|
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
|
121
132
|
|
122
133
|
return sig_r + sig_s
|
123
134
|
end
|
124
135
|
end
|
125
136
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
end
|
148
|
-
public_key_oct = buffer.read_string
|
149
|
-
begin
|
150
|
-
key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key])
|
151
|
-
group = key.group
|
152
|
-
point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2))
|
153
|
-
key.public_key = point
|
154
|
-
|
155
|
-
return key
|
156
|
-
rescue OpenSSL::PKey::ECError
|
157
|
-
raise NotImplementedError, "unsupported key type `#{type}'"
|
158
|
-
end
|
159
|
-
|
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}')"
|
160
158
|
end
|
161
159
|
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
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}'"
|
166
182
|
end
|
183
|
+
end
|
167
184
|
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
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
|
190
|
+
|
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
|
179
197
|
OpenSSL::Digest::SHA256.new
|
198
|
+
elsif curve_size <= 384
|
199
|
+
OpenSSL::Digest::SHA384.new
|
200
|
+
else
|
201
|
+
OpenSSL::Digest::SHA512.new
|
180
202
|
end
|
203
|
+
else
|
204
|
+
OpenSSL::Digest::SHA256.new
|
181
205
|
end
|
182
|
-
|
206
|
+
end
|
207
|
+
private :digester
|
183
208
|
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
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
|
190
234
|
end
|
191
235
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
a1sig
|
236
|
+
if a1sig.nil?
|
237
|
+
return false
|
238
|
+
else
|
239
|
+
dsa_verify_asn1(digest, a1sig.to_der)
|
240
|
+
end
|
241
|
+
end
|
196
242
|
|
197
|
-
|
198
|
-
|
199
|
-
|
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)
|
200
248
|
|
201
|
-
|
202
|
-
|
249
|
+
sig_r = a1sig.value[0].value
|
250
|
+
sig_s = a1sig.value[1].value
|
203
251
|
|
204
|
-
|
205
|
-
|
206
|
-
OpenSSL::ASN1::Integer(sig_s.to_i(16)),
|
207
|
-
])
|
208
|
-
rescue
|
209
|
-
end
|
252
|
+
Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s
|
253
|
+
end
|
210
254
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
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]}"
|
216
260
|
end
|
217
261
|
|
218
|
-
|
219
|
-
def ssh_do_sign(data)
|
220
|
-
digest = digester.digest(data)
|
221
|
-
sig = dsa_sign_asn1(digest)
|
222
|
-
a1sig = OpenSSL::ASN1.decode( sig )
|
262
|
+
alias ssh_signature_type ssh_type
|
223
263
|
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
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
|
228
270
|
end
|
229
271
|
end
|
230
|
-
else
|
231
|
-
class OpenSSL::PKey::ECError < RuntimeError
|
232
|
-
# for compatibility with interpreters
|
233
|
-
# without EC support (i.e. JRuby)
|
234
|
-
end
|
235
272
|
end
|
236
273
|
end
|
237
274
|
end
|