net-ssh 5.0.0.beta1 → 5.0.0.beta2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.rubocop_todo.yml +98 -258
- data/CHANGES.txt +8 -0
- data/Gemfile +1 -3
- data/Rakefile +37 -39
- data/lib/net/ssh.rb +26 -25
- data/lib/net/ssh/authentication/agent.rb +228 -225
- data/lib/net/ssh/authentication/certificate.rb +166 -164
- data/lib/net/ssh/authentication/constants.rb +17 -14
- data/lib/net/ssh/authentication/ed25519.rb +107 -104
- data/lib/net/ssh/authentication/ed25519_loader.rb +32 -28
- data/lib/net/ssh/authentication/key_manager.rb +5 -3
- data/lib/net/ssh/authentication/methods/abstract.rb +53 -47
- data/lib/net/ssh/authentication/methods/hostbased.rb +32 -33
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +2 -4
- data/lib/net/ssh/authentication/methods/none.rb +10 -10
- data/lib/net/ssh/authentication/methods/password.rb +13 -13
- data/lib/net/ssh/authentication/methods/publickey.rb +54 -55
- data/lib/net/ssh/authentication/pageant.rb +468 -465
- data/lib/net/ssh/authentication/pub_key_fingerprint.rb +44 -0
- data/lib/net/ssh/authentication/session.rb +127 -123
- data/lib/net/ssh/buffer.rb +305 -303
- data/lib/net/ssh/buffered_io.rb +163 -162
- data/lib/net/ssh/config.rb +230 -227
- data/lib/net/ssh/connection/channel.rb +659 -654
- data/lib/net/ssh/connection/constants.rb +30 -26
- data/lib/net/ssh/connection/event_loop.rb +108 -104
- data/lib/net/ssh/connection/keepalive.rb +54 -50
- data/lib/net/ssh/connection/session.rb +677 -678
- data/lib/net/ssh/connection/term.rb +180 -176
- data/lib/net/ssh/errors.rb +101 -99
- data/lib/net/ssh/key_factory.rb +108 -108
- data/lib/net/ssh/known_hosts.rb +148 -154
- data/lib/net/ssh/loggable.rb +56 -54
- data/lib/net/ssh/packet.rb +82 -78
- data/lib/net/ssh/prompt.rb +55 -53
- data/lib/net/ssh/proxy/command.rb +103 -102
- data/lib/net/ssh/proxy/errors.rb +12 -8
- data/lib/net/ssh/proxy/http.rb +92 -91
- data/lib/net/ssh/proxy/https.rb +42 -39
- data/lib/net/ssh/proxy/jump.rb +50 -47
- data/lib/net/ssh/proxy/socks4.rb +0 -2
- data/lib/net/ssh/proxy/socks5.rb +11 -11
- data/lib/net/ssh/ruby_compat.rb +1 -0
- data/lib/net/ssh/service/forward.rb +364 -362
- data/lib/net/ssh/test.rb +85 -83
- data/lib/net/ssh/test/channel.rb +146 -142
- data/lib/net/ssh/test/extensions.rb +148 -146
- data/lib/net/ssh/test/kex.rb +35 -31
- data/lib/net/ssh/test/local_packet.rb +48 -44
- data/lib/net/ssh/test/packet.rb +87 -84
- data/lib/net/ssh/test/remote_packet.rb +35 -31
- data/lib/net/ssh/test/script.rb +173 -171
- data/lib/net/ssh/test/socket.rb +59 -55
- data/lib/net/ssh/transport/algorithms.rb +413 -412
- data/lib/net/ssh/transport/cipher_factory.rb +108 -105
- data/lib/net/ssh/transport/constants.rb +35 -31
- data/lib/net/ssh/transport/ctr.rb +1 -1
- data/lib/net/ssh/transport/hmac.rb +1 -1
- data/lib/net/ssh/transport/hmac/abstract.rb +67 -64
- data/lib/net/ssh/transport/hmac/sha2_256_96.rb +1 -1
- data/lib/net/ssh/transport/hmac/sha2_512_96.rb +1 -1
- data/lib/net/ssh/transport/identity_cipher.rb +55 -51
- data/lib/net/ssh/transport/kex.rb +2 -4
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +47 -40
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +201 -197
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -56
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +94 -87
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +17 -10
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +17 -10
- data/lib/net/ssh/transport/key_expander.rb +29 -25
- data/lib/net/ssh/transport/openssl.rb +17 -30
- data/lib/net/ssh/transport/packet_stream.rb +193 -192
- data/lib/net/ssh/transport/server_version.rb +64 -66
- data/lib/net/ssh/transport/session.rb +286 -284
- data/lib/net/ssh/transport/state.rb +198 -196
- data/lib/net/ssh/verifiers/lenient.rb +29 -25
- data/lib/net/ssh/verifiers/null.rb +13 -9
- data/lib/net/ssh/verifiers/secure.rb +45 -45
- data/lib/net/ssh/verifiers/strict.rb +20 -16
- data/lib/net/ssh/version.rb +55 -53
- data/net-ssh.gemspec +4 -4
- data/support/ssh_tunnel_bug.rb +2 -2
- metadata +25 -24
- metadata.gz.sig +0 -0
@@ -1,169 +1,171 @@
|
|
1
1
|
require 'securerandom'
|
2
2
|
|
3
|
-
module Net
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
3
|
+
module Net
|
4
|
+
module SSH
|
5
|
+
module Authentication
|
6
|
+
# Class for representing an SSH certificate.
|
7
|
+
#
|
8
|
+
# http://cvsweb.openbsd.org/cgi-bin/cvsweb/~checkout~/src/usr.bin/ssh/PROTOCOL.certkeys?rev=1.10&content-type=text/plain
|
9
|
+
class Certificate
|
10
|
+
attr_accessor :nonce
|
11
|
+
attr_accessor :key
|
12
|
+
attr_accessor :serial
|
13
|
+
attr_accessor :type
|
14
|
+
attr_accessor :key_id
|
15
|
+
attr_accessor :valid_principals
|
16
|
+
attr_accessor :valid_after
|
17
|
+
attr_accessor :valid_before
|
18
|
+
attr_accessor :critical_options
|
19
|
+
attr_accessor :extensions
|
20
|
+
attr_accessor :reserved
|
21
|
+
attr_accessor :signature_key
|
22
|
+
attr_accessor :signature
|
23
|
+
|
24
|
+
# Read a certificate blob associated with a key of the given type.
|
25
|
+
def self.read_certblob(buffer, type)
|
26
|
+
cert = Certificate.new
|
27
|
+
cert.nonce = buffer.read_string
|
28
|
+
cert.key = buffer.read_keyblob(type)
|
29
|
+
cert.serial = buffer.read_int64
|
30
|
+
cert.type = type_symbol(buffer.read_long)
|
31
|
+
cert.key_id = buffer.read_string
|
32
|
+
cert.valid_principals = buffer.read_buffer.read_all(&:read_string)
|
33
|
+
cert.valid_after = Time.at(buffer.read_int64)
|
34
|
+
cert.valid_before = Time.at(buffer.read_int64)
|
35
|
+
cert.critical_options = read_options(buffer)
|
36
|
+
cert.extensions = read_options(buffer)
|
37
|
+
cert.reserved = buffer.read_string
|
38
|
+
cert.signature_key = buffer.read_buffer.read_key
|
39
|
+
cert.signature = buffer.read_string
|
40
|
+
cert
|
41
|
+
end
|
42
|
+
|
43
|
+
def ssh_type
|
44
|
+
key.ssh_type + "-cert-v01@openssh.com"
|
45
|
+
end
|
46
|
+
|
47
|
+
def ssh_signature_type
|
48
|
+
key.ssh_type
|
49
|
+
end
|
50
|
+
|
51
|
+
# Serializes the certificate (and key).
|
52
|
+
def to_blob
|
53
|
+
Buffer.from(
|
54
|
+
:raw, to_blob_without_signature,
|
55
|
+
:string, signature
|
56
|
+
).to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
def ssh_do_sign(data)
|
60
|
+
key.ssh_do_sign(data)
|
61
|
+
end
|
62
|
+
|
63
|
+
def ssh_do_verify(sig, data)
|
64
|
+
key.ssh_do_verify(sig, data)
|
65
|
+
end
|
66
|
+
|
67
|
+
def to_pem
|
68
|
+
key.to_pem
|
69
|
+
end
|
70
|
+
|
71
|
+
def fingerprint
|
72
|
+
key.fingerprint
|
73
|
+
end
|
74
|
+
|
75
|
+
# Signs the certificate with key.
|
76
|
+
def sign!(key, sign_nonce=nil)
|
77
|
+
# ssh-keygen uses 32 bytes of nonce.
|
78
|
+
self.nonce = sign_nonce || SecureRandom.random_bytes(32)
|
79
|
+
self.signature_key = key
|
80
|
+
self.signature = Net::SSH::Buffer.from(
|
81
|
+
:string, key.ssh_signature_type,
|
82
|
+
:mstring, key.ssh_do_sign(to_blob_without_signature)
|
83
|
+
).to_s
|
84
|
+
self
|
85
|
+
end
|
86
|
+
|
87
|
+
def sign(key, sign_nonce=nil)
|
88
|
+
cert = clone
|
89
|
+
cert.sign!(key, sign_nonce)
|
90
|
+
end
|
91
|
+
|
92
|
+
# Checks whether the certificate's signature was signed by signature key.
|
93
|
+
def signature_valid?
|
94
|
+
buffer = Buffer.new(signature)
|
95
|
+
buffer.read_string # skip signature format
|
96
|
+
signature_key.ssh_do_verify(buffer.read_string, to_blob_without_signature)
|
97
|
+
end
|
98
|
+
|
99
|
+
def self.read_options(buffer)
|
100
|
+
names = []
|
101
|
+
options = buffer.read_buffer.read_all do |b|
|
102
|
+
name = b.read_string
|
103
|
+
names << name
|
104
|
+
data = b.read_string
|
105
|
+
data = Buffer.new(data).read_string unless data.empty?
|
106
|
+
[name, data]
|
107
|
+
end
|
108
|
+
|
109
|
+
raise ArgumentError, "option/extension names must be in sorted order" if names.sort != names
|
110
|
+
|
111
|
+
Hash[options]
|
112
|
+
end
|
113
|
+
private_class_method :read_options
|
114
|
+
|
115
|
+
def self.type_symbol(type)
|
116
|
+
types = { 1 => :user, 2 => :host }
|
117
|
+
raise ArgumentError("unsupported type: #{type}") unless types.include?(type)
|
118
|
+
types.fetch(type)
|
119
|
+
end
|
120
|
+
private_class_method :type_symbol
|
121
|
+
|
122
|
+
private
|
123
|
+
|
124
|
+
def type_value(type)
|
125
|
+
types = { user: 1, host: 2 }
|
126
|
+
raise ArgumentError("unsupported type: #{type}") unless types.include?(type)
|
127
|
+
types.fetch(type)
|
128
|
+
end
|
129
|
+
|
130
|
+
def ssh_time(t)
|
131
|
+
# Times in certificates are represented as a uint64.
|
132
|
+
[[t.to_i, 0].max, 2 << 64 - 1].min
|
133
|
+
end
|
134
|
+
|
135
|
+
def to_blob_without_signature
|
136
|
+
Buffer.from(
|
137
|
+
:string, ssh_type,
|
138
|
+
:string, nonce,
|
139
|
+
:raw, key_without_type,
|
140
|
+
:int64, serial,
|
141
|
+
:long, type_value(type),
|
142
|
+
:string, key_id,
|
143
|
+
:string, valid_principals.inject(Buffer.new) { |acc, elem| acc.write_string(elem) }.to_s,
|
144
|
+
:int64, ssh_time(valid_after),
|
145
|
+
:int64, ssh_time(valid_before),
|
146
|
+
:string, options_to_blob(critical_options),
|
147
|
+
:string, options_to_blob(extensions),
|
148
|
+
:string, reserved,
|
149
|
+
:string, signature_key.to_blob
|
150
|
+
).to_s
|
151
|
+
end
|
152
|
+
|
153
|
+
def key_without_type
|
154
|
+
# key.to_blob gives us e.g. "ssh-rsa,<key>" but we just want "<key>".
|
155
|
+
tmp = Buffer.new(key.to_blob)
|
156
|
+
tmp.read_string # skip the underlying key type
|
157
|
+
tmp.read
|
158
|
+
end
|
159
|
+
|
160
|
+
def options_to_blob(options)
|
161
|
+
options.keys.sort.inject(Buffer.new) do |b, name|
|
162
|
+
b.write_string(name)
|
163
|
+
data = options.fetch(name)
|
164
|
+
data = Buffer.from(:string, data).to_s unless data.empty?
|
165
|
+
b.write_string(data)
|
166
|
+
end.to_s
|
167
|
+
end
|
109
168
|
end
|
110
|
-
|
111
|
-
Hash[options]
|
112
|
-
end
|
113
|
-
private_class_method :read_options
|
114
|
-
|
115
|
-
def self.type_symbol(type)
|
116
|
-
types = {1 => :user, 2 => :host}
|
117
|
-
raise ArgumentError("unsupported type: #{type}") unless types.include?(type)
|
118
|
-
types.fetch(type)
|
119
|
-
end
|
120
|
-
private_class_method :type_symbol
|
121
|
-
|
122
|
-
private
|
123
|
-
|
124
|
-
def type_value(type)
|
125
|
-
types = {user: 1, host: 2}
|
126
|
-
raise ArgumentError("unsupported type: #{type}") unless types.include?(type)
|
127
|
-
types.fetch(type)
|
128
|
-
end
|
129
|
-
|
130
|
-
def ssh_time(t)
|
131
|
-
# Times in certificates are represented as a uint64.
|
132
|
-
[[t.to_i, 0].max, 2<<64 - 1].min
|
133
|
-
end
|
134
|
-
|
135
|
-
def to_blob_without_signature
|
136
|
-
Buffer.from(
|
137
|
-
:string, ssh_type,
|
138
|
-
:string, nonce,
|
139
|
-
:raw, key_without_type,
|
140
|
-
:int64, serial,
|
141
|
-
:long, type_value(type),
|
142
|
-
:string, key_id,
|
143
|
-
:string, valid_principals.inject(Buffer.new) { |acc, elem| acc.write_string(elem) }.to_s,
|
144
|
-
:int64, ssh_time(valid_after),
|
145
|
-
:int64, ssh_time(valid_before),
|
146
|
-
:string, options_to_blob(critical_options),
|
147
|
-
:string, options_to_blob(extensions),
|
148
|
-
:string, reserved,
|
149
|
-
:string, signature_key.to_blob
|
150
|
-
).to_s
|
151
|
-
end
|
152
|
-
|
153
|
-
def key_without_type
|
154
|
-
# key.to_blob gives us e.g. "ssh-rsa,<key>" but we just want "<key>".
|
155
|
-
tmp = Buffer.new(key.to_blob)
|
156
|
-
tmp.read_string # skip the underlying key type
|
157
|
-
tmp.read
|
158
|
-
end
|
159
|
-
|
160
|
-
def options_to_blob(options)
|
161
|
-
options.keys.sort.inject(Buffer.new) do |b, name|
|
162
|
-
b.write_string(name)
|
163
|
-
data = options.fetch(name)
|
164
|
-
data = Buffer.from(:string, data).to_s unless data.empty?
|
165
|
-
b.write_string(data)
|
166
|
-
end.to_s
|
167
169
|
end
|
168
170
|
end
|
169
|
-
end
|
171
|
+
end
|
@@ -1,18 +1,21 @@
|
|
1
|
-
module Net
|
1
|
+
module Net
|
2
|
+
module SSH
|
3
|
+
module Authentication
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
5
|
+
# Describes the constants used by the Net::SSH::Authentication components
|
6
|
+
# of the Net::SSH library. Individual authentication method implemenations
|
7
|
+
# may define yet more constants that are specific to their implementation.
|
8
|
+
module Constants
|
9
|
+
USERAUTH_REQUEST = 50
|
10
|
+
USERAUTH_FAILURE = 51
|
11
|
+
USERAUTH_SUCCESS = 52
|
12
|
+
USERAUTH_BANNER = 53
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
+
USERAUTH_PASSWD_CHANGEREQ = 60
|
15
|
+
USERAUTH_PK_OK = 60
|
14
16
|
|
15
|
-
|
17
|
+
USERAUTH_METHOD_RANGE = 60..79
|
18
|
+
end
|
19
|
+
end
|
16
20
|
end
|
17
|
-
|
18
|
-
end; end; end
|
21
|
+
end
|
@@ -6,144 +6,147 @@ require 'ed25519'
|
|
6
6
|
require 'base64'
|
7
7
|
|
8
8
|
require 'net/ssh/transport/cipher_factory'
|
9
|
+
require 'net/ssh/authentication/pub_key_fingerprint'
|
9
10
|
require 'bcrypt_pbkdf' unless RUBY_PLATFORM == "java"
|
10
11
|
|
11
|
-
module Net
|
12
|
-
module
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
module Net
|
13
|
+
module SSH
|
14
|
+
module Authentication
|
15
|
+
module ED25519
|
16
|
+
class SigningKeyFromFile < SimpleDelegator
|
17
|
+
def initialize(pk,sk)
|
18
|
+
key = ::Ed25519::SigningKey.from_keypair(sk)
|
19
|
+
raise ArgumentError, "pk does not match sk" unless pk == key.verify_key.to_bytes
|
17
20
|
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
super(key)
|
22
|
+
end
|
23
|
+
end
|
21
24
|
|
22
|
-
|
23
|
-
|
25
|
+
class PubKey
|
26
|
+
include Net::SSH::Authentication::PubKeyFingerprint
|
24
27
|
|
25
|
-
|
26
|
-
@verify_key = ::Ed25519::VerifyKey.new(data)
|
27
|
-
end
|
28
|
-
|
29
|
-
def self.read_keyblob(buffer)
|
30
|
-
PubKey.new(buffer.read_string)
|
31
|
-
end
|
28
|
+
attr_reader :verify_key
|
32
29
|
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
def initialize(data)
|
31
|
+
@verify_key = ::Ed25519::VerifyKey.new(data)
|
32
|
+
end
|
36
33
|
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
def self.read_keyblob(buffer)
|
35
|
+
PubKey.new(buffer.read_string)
|
36
|
+
end
|
40
37
|
|
41
|
-
|
42
|
-
|
43
|
-
|
38
|
+
def to_blob
|
39
|
+
Net::SSH::Buffer.from(:mstring,"ssh-ed25519",:string,@verify_key.to_bytes).to_s
|
40
|
+
end
|
44
41
|
|
45
|
-
|
46
|
-
|
47
|
-
|
42
|
+
def ssh_type
|
43
|
+
"ssh-ed25519"
|
44
|
+
end
|
48
45
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
end
|
46
|
+
def ssh_signature_type
|
47
|
+
ssh_type
|
48
|
+
end
|
53
49
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
end
|
50
|
+
def ssh_do_verify(sig,data)
|
51
|
+
@verify_key.verify(sig,data)
|
52
|
+
end
|
58
53
|
|
59
|
-
|
60
|
-
|
54
|
+
def to_pem
|
55
|
+
# TODO this is not pem
|
56
|
+
ssh_type + Base64.encode64(@verify_key.to_bytes)
|
57
|
+
end
|
58
|
+
end
|
61
59
|
|
62
|
-
|
63
|
-
|
64
|
-
MAGIC = "openssh-key-v1"
|
60
|
+
class PrivKey
|
61
|
+
CipherFactory = Net::SSH::Transport::CipherFactory
|
65
62
|
|
66
|
-
|
63
|
+
MBEGIN = "-----BEGIN OPENSSH PRIVATE KEY-----\n"
|
64
|
+
MEND = "-----END OPENSSH PRIVATE KEY-----\n"
|
65
|
+
MAGIC = "openssh-key-v1"
|
67
66
|
|
68
|
-
|
69
|
-
raise ArgumentError.new("Expected #{MBEGIN} at start of private key") unless datafull.start_with?(MBEGIN)
|
70
|
-
raise ArgumentError.new("Expected #{MEND} at end of private key") unless datafull.end_with?(MEND)
|
71
|
-
datab64 = datafull[MBEGIN.size ... -MEND.size]
|
72
|
-
data = Base64.decode64(datab64)
|
73
|
-
raise ArgumentError.new("Expected #{MAGIC} at start of decoded private key") unless data.start_with?(MAGIC)
|
74
|
-
buffer = Net::SSH::Buffer.new(data[MAGIC.size+1 .. -1])
|
67
|
+
attr_reader :sign_key
|
75
68
|
|
76
|
-
|
77
|
-
|
78
|
-
|
69
|
+
def initialize(datafull,password)
|
70
|
+
raise ArgumentError.new("Expected #{MBEGIN} at start of private key") unless datafull.start_with?(MBEGIN)
|
71
|
+
raise ArgumentError.new("Expected #{MEND} at end of private key") unless datafull.end_with?(MEND)
|
72
|
+
datab64 = datafull[MBEGIN.size...-MEND.size]
|
73
|
+
data = Base64.decode64(datab64)
|
74
|
+
raise ArgumentError.new("Expected #{MAGIC} at start of decoded private key") unless data.start_with?(MAGIC)
|
75
|
+
buffer = Net::SSH::Buffer.new(data[MAGIC.size + 1..-1])
|
79
76
|
|
80
|
-
|
81
|
-
|
77
|
+
ciphername = buffer.read_string
|
78
|
+
raise ArgumentError.new("#{ciphername} in private key is not supported") unless
|
79
|
+
CipherFactory.supported?(ciphername)
|
82
80
|
|
83
|
-
|
84
|
-
|
85
|
-
raise ArgumentError.new("Only 1 key is supported in ssh keys #{num_keys} was in private key") unless num_keys == 1
|
86
|
-
_pubkey = buffer.read_string
|
81
|
+
kdfname = buffer.read_string
|
82
|
+
raise ArgumentError.new("Expected #{kdfname} to be or none or bcrypt") unless %w[none bcrypt].include?(kdfname)
|
87
83
|
|
88
|
-
|
84
|
+
kdfopts = Net::SSH::Buffer.new(buffer.read_string)
|
85
|
+
num_keys = buffer.read_long
|
86
|
+
raise ArgumentError.new("Only 1 key is supported in ssh keys #{num_keys} was in private key") unless num_keys == 1
|
87
|
+
_pubkey = buffer.read_string
|
89
88
|
|
90
|
-
|
91
|
-
raise ArgumentError.new("Private key len:#{len} is not a multiple of #{blocksize}") if
|
92
|
-
((len < blocksize) || ((blocksize > 0) && (len % blocksize) != 0))
|
89
|
+
len = buffer.read_long
|
93
90
|
|
94
|
-
|
95
|
-
|
96
|
-
|
91
|
+
keylen, blocksize, ivlen = CipherFactory.get_lengths(ciphername, iv_len: true)
|
92
|
+
raise ArgumentError.new("Private key len:#{len} is not a multiple of #{blocksize}") if
|
93
|
+
((len < blocksize) || ((blocksize > 0) && (len % blocksize) != 0))
|
97
94
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
key = '\x00' * (keylen + ivlen)
|
102
|
-
end
|
95
|
+
if kdfname == 'bcrypt'
|
96
|
+
salt = kdfopts.read_string
|
97
|
+
rounds = kdfopts.read_long
|
103
98
|
|
104
|
-
|
99
|
+
raise "BCryptPbkdf is not implemented for jruby" if RUBY_PLATFORM == "java"
|
100
|
+
key = BCryptPbkdf::key(password, salt, keylen + ivlen, rounds)
|
101
|
+
else
|
102
|
+
key = '\x00' * (keylen + ivlen)
|
103
|
+
end
|
105
104
|
|
106
|
-
|
107
|
-
decoded << cipher.final
|
105
|
+
cipher = CipherFactory.get(ciphername, key: key[0...keylen], iv:key[keylen...keylen + ivlen], decrypt: true)
|
108
106
|
|
109
|
-
|
110
|
-
|
111
|
-
check2 = decoded.read_long
|
107
|
+
decoded = cipher.update(buffer.remainder_as_buffer.to_s)
|
108
|
+
decoded << cipher.final
|
112
109
|
|
113
|
-
|
110
|
+
decoded = Net::SSH::Buffer.new(decoded)
|
111
|
+
check1 = decoded.read_long
|
112
|
+
check2 = decoded.read_long
|
113
|
+
|
114
|
+
raise ArgumentError, "Decrypt failed on private key" if (check1 != check2)
|
114
115
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
_type_name = decoded.read_string
|
117
|
+
pk = decoded.read_string
|
118
|
+
sk = decoded.read_string
|
119
|
+
_comment = decoded.read_string
|
119
120
|
|
120
|
-
|
121
|
-
|
122
|
-
|
121
|
+
@pk = pk
|
122
|
+
@sign_key = SigningKeyFromFile.new(pk,sk)
|
123
|
+
end
|
123
124
|
|
124
|
-
|
125
|
-
|
126
|
-
|
125
|
+
def to_blob
|
126
|
+
public_key.to_blob
|
127
|
+
end
|
127
128
|
|
128
|
-
|
129
|
-
|
130
|
-
|
129
|
+
def ssh_type
|
130
|
+
"ssh-ed25519"
|
131
|
+
end
|
131
132
|
|
132
|
-
|
133
|
-
|
134
|
-
|
133
|
+
def ssh_signature_type
|
134
|
+
ssh_type
|
135
|
+
end
|
135
136
|
|
136
|
-
|
137
|
-
|
138
|
-
|
137
|
+
def public_key
|
138
|
+
PubKey.new(@pk)
|
139
|
+
end
|
139
140
|
|
140
|
-
|
141
|
-
|
142
|
-
|
141
|
+
def ssh_do_sign(data)
|
142
|
+
@sign_key.sign(data)
|
143
|
+
end
|
143
144
|
|
144
|
-
|
145
|
-
|
145
|
+
def self.read(data,password)
|
146
|
+
self.new(data,password)
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
146
150
|
end
|
147
151
|
end
|
148
152
|
end
|
149
|
-
end; end; end
|