net-ssh 2.4.0 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +21 -0
- data/Manifest +11 -0
- data/lib/net/ssh/authentication/key_manager.rb +1 -1
- data/lib/net/ssh/authentication/session.rb +12 -4
- data/lib/net/ssh/buffer.rb +12 -2
- data/lib/net/ssh/key_factory.rb +7 -2
- data/lib/net/ssh/known_hosts.rb +12 -2
- data/lib/net/ssh/ruby_compat.rb +8 -0
- data/lib/net/ssh/transport/algorithms.rb +22 -1
- data/lib/net/ssh/transport/cipher_factory.rb +32 -5
- data/lib/net/ssh/transport/constants.rb +3 -1
- data/lib/net/ssh/transport/ctr.rb +95 -0
- data/lib/net/ssh/transport/hmac.rb +8 -5
- data/lib/net/ssh/transport/hmac/ripemd160.rb +13 -0
- data/lib/net/ssh/transport/kex.rb +11 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +44 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +11 -3
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +93 -0
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +13 -0
- data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +13 -0
- data/lib/net/ssh/transport/openssl.rb +111 -1
- data/lib/net/ssh/version.rb +1 -1
- data/net-ssh.gemspec +12 -4
- data/test/authentication/test_key_manager.rb +48 -1
- data/test/test_buffer.rb +92 -2
- data/test/test_key_factory.rb +42 -0
- data/test/transport/hmac/test_ripemd160.rb +34 -0
- data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +13 -0
- data/test/transport/kex/test_ecdh_sha2_nistp256.rb +161 -0
- data/test/transport/kex/test_ecdh_sha2_nistp384.rb +37 -0
- data/test/transport/kex/test_ecdh_sha2_nistp521.rb +37 -0
- data/test/transport/test_algorithms.rb +41 -19
- data/test/transport/test_cipher_factory.rb +255 -27
- data/test/transport/test_packet_stream.rb +1009 -0
- metadata +13 -4
- data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
- data/lib/net/ssh/authentication/agent/socket.rb +0 -170
data/test/test_buffer.rb
CHANGED
@@ -290,7 +290,7 @@ class TestBuffer < Test::Unit::TestCase
|
|
290
290
|
key.pub_key = 0xeeccaa8866442200
|
291
291
|
|
292
292
|
buffer.write_key(key)
|
293
|
-
|
293
|
+
assert_equal "start\0\0\0\7ssh-dss\0\0\0\011\0\xff\xee\xdd\xcc\xbb\xaa\x99\x88\0\0\0\010\x77\x66\x55\x44\x33\x22\x11\x00\0\0\0\011\0\xff\xdd\xbb\x99\x77\x55\x33\x11\0\0\0\011\0\xee\xcc\xaa\x88\x66\x44\x22\x00", buffer.to_s
|
294
294
|
end
|
295
295
|
|
296
296
|
def test_write_rsa_key_should_write_argument_to_end_of_buffer
|
@@ -304,6 +304,67 @@ class TestBuffer < Test::Unit::TestCase
|
|
304
304
|
assert_equal "start\0\0\0\7ssh-rsa\0\0\0\011\0\xff\xee\xdd\xcc\xbb\xaa\x99\x88\0\0\0\010\x77\x66\x55\x44\x33\x22\x11\x00", buffer.to_s
|
305
305
|
end
|
306
306
|
|
307
|
+
if defined?(OpenSSL::PKey::EC)
|
308
|
+
def test_read_key_blob_should_read_ecdsa_sha2_nistp256_keys
|
309
|
+
random_ecdsa_sha2_nistp256 { |buffer|
|
310
|
+
buffer.read_keyblob("ecdsa-sha2-nistp256")
|
311
|
+
}
|
312
|
+
end
|
313
|
+
def test_read_key_blob_should_read_ecdsa_sha2_nistp384_keys
|
314
|
+
random_ecdsa_sha2_nistp384 { |buffer|
|
315
|
+
buffer.read_keyblob("ecdsa-sha2-nistp384")
|
316
|
+
}
|
317
|
+
end
|
318
|
+
def test_read_key_blob_should_read_ecdsa_sha2_nistp521_keys
|
319
|
+
random_ecdsa_sha2_nistp521 { |buffer|
|
320
|
+
buffer.read_keyblob("ecdsa-sha2-nistp521")
|
321
|
+
}
|
322
|
+
end
|
323
|
+
|
324
|
+
def test_read_key_should_read_ecdsa_sha2_nistp256_key_type_and_keyblob
|
325
|
+
random_ecdsa_sha2_nistp256 do |buffer|
|
326
|
+
b2 = Net::SSH::Buffer.from(:string, "ecdsa-sha2-nistp256", :raw, buffer)
|
327
|
+
b2.read_key
|
328
|
+
end
|
329
|
+
end
|
330
|
+
def test_read_key_should_read_ecdsa_sha2_nistp384_key_type_and_keyblob
|
331
|
+
random_ecdsa_sha2_nistp384 do |buffer|
|
332
|
+
b2 = Net::SSH::Buffer.from(:string, "ecdsa-sha2-nistp384", :raw, buffer)
|
333
|
+
b2.read_key
|
334
|
+
end
|
335
|
+
end
|
336
|
+
def test_read_key_should_read_ecdsa_sha2_nistp521_key_type_and_keyblob
|
337
|
+
random_ecdsa_sha2_nistp521 do |buffer|
|
338
|
+
b2 = Net::SSH::Buffer.from(:string, "ecdsa-sha2-nistp521", :raw, buffer)
|
339
|
+
b2.read_key
|
340
|
+
end
|
341
|
+
end
|
342
|
+
|
343
|
+
def test_write_ecdsa_sha2_nistp256_key_should_write_argument_to_end_of_buffer
|
344
|
+
buffer = new("start")
|
345
|
+
key = OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIISGj5vAJCWt2KPI8NwaWVDSNLl2vbRxDIOkY+n6O0VVoAoGCCqGSM49\nAwEHoUQDQgAEnKbs0yEogTKT4QRu8T9nb2svl2mEWXb6g224oCpD2o6TYNXNw54H\nmWkdCv+kFCqSlfSi5fqFhrXdfEY6zSzQYQ==\n-----END EC PRIVATE KEY-----\n")
|
346
|
+
|
347
|
+
buffer.write_key(key)
|
348
|
+
assert_equal "start\000\000\000\023ecdsa-sha2-nistp256\000\000\000\bnistp256\000\000\000A\004\234\246\354\323!(\2012\223\341\004n\361?gok/\227i\204Yv\372\203m\270\240*C\332\216\223`\325\315\303\236\a\231i\035\n\377\244\024*\222\225\364\242\345\372\205\206\265\335|F:\315,\320a", buffer.to_s
|
349
|
+
end
|
350
|
+
|
351
|
+
def test_write_ecdsa_sha2_nistp384_key_should_write_argument_to_end_of_buffer
|
352
|
+
buffer = new("start")
|
353
|
+
key = OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDBAfxJpzhsR7O+wMol6BcDgualR8rJBvYegUDYbBUrDnPzDx2/gD1lZ\nnwG1FuD2s9igBwYFK4EEACKhZANiAATsfiU4Kxyvvj1DdvFYsdDnZIT7loRlan9I\n8geCWPPl6x7NFRP+awrnTaarMgieGqxG8IQaIA0SsDOICfbDBkuatRi0S1Et/in4\nZwVEZvO81Ro5YSrjuUDAsytnI6OXS28=\n-----END EC PRIVATE KEY-----\n")
|
354
|
+
|
355
|
+
buffer.write_key(key)
|
356
|
+
assert_equal "start\000\000\000\023ecdsa-sha2-nistp384\000\000\000\bnistp384\000\000\000a\004\354~%8+\034\257\276=Cv\361X\261\320\347d\204\373\226\204ej\177H\362\a\202X\363\345\353\036\315\025\023\376k\n\347M\246\2532\b\236\032\254F\360\204\032 \r\022\2603\210\t\366\303\006K\232\265\030\264KQ-\376)\370g\005Df\363\274\325\0329a*\343\271@\300\263+g#\243\227Ko", buffer.to_s
|
357
|
+
end
|
358
|
+
|
359
|
+
def test_write_ecdsa_sha2_nistp521_key_should_write_argument_to_end_of_buffer
|
360
|
+
buffer = new("start")
|
361
|
+
key = OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMIHbAgEBBEGhnQF/SFo4Vym88HnCfc6BR8WwYqDh9wNTPeqzR8auxIpp0GKQlCG2\nuHzyteJX5/YalV8empYhEzNmNLNn8x7j0aAHBgUrgQQAI6GBiQOBhgAEAYygOgV9\nVI8UyLQ3BDlv+rb3es+ufrIcj++cqcc9QcmRn237NiWRr/1NKy2AKijsEdACtZXo\nxPC0x9Vs9ieC2oR+ANOBubcxPl2giDnBYm8ywAmmlXsP5ByAM17k97CzW5O+Z/uO\nbxGUzzhoXTNcjqpAckhRVKdnh6FL/rKelT0tBYi+\n-----END EC PRIVATE KEY-----\n")
|
362
|
+
|
363
|
+
buffer.write_key(key)
|
364
|
+
assert_equal "start\000\000\000\023ecdsa-sha2-nistp521\000\000\000\bnistp521\000\000\000\205\004\001\214\240:\005}T\217\024\310\2647\0049o\372\266\367z\317\256~\262\034\217\357\234\251\307=A\311\221\237m\3736%\221\257\375M+-\200*(\354\021\320\002\265\225\350\304\360\264\307\325l\366'\202\332\204~\000\323\201\271\2671>]\240\2109\301bo2\300\t\246\225{\017\344\034\2003^\344\367\260\263[\223\276g\373\216o\021\224\3178h]3\\\216\252@rHQT\247g\207\241K\376\262\236\225=-\005\210\276", buffer.to_s
|
365
|
+
end
|
366
|
+
end
|
367
|
+
|
307
368
|
private
|
308
369
|
|
309
370
|
def random_rsa
|
@@ -330,7 +391,36 @@ class TestBuffer < Test::Unit::TestCase
|
|
330
391
|
assert_equal n4, key.pub_key
|
331
392
|
end
|
332
393
|
|
394
|
+
if defined?(OpenSSL::PKey::EC)
|
395
|
+
def random_ecdsa_sha2_nistp256
|
396
|
+
k = OpenSSL::PKey::EC.new("prime256v1").generate_key
|
397
|
+
buffer = Net::SSH::Buffer.from(:string, "nistp256",
|
398
|
+
:string, k.public_key.to_bn.to_s(2))
|
399
|
+
key = yield(buffer)
|
400
|
+
assert_equal "ecdsa-sha2-nistp256", key.ssh_type
|
401
|
+
assert_equal k.public_key, key.public_key
|
402
|
+
end
|
403
|
+
|
404
|
+
def random_ecdsa_sha2_nistp384
|
405
|
+
k = OpenSSL::PKey::EC.new("secp384r1").generate_key
|
406
|
+
buffer = Net::SSH::Buffer.from(:string, "nistp384",
|
407
|
+
:string, k.public_key.to_bn.to_s(2))
|
408
|
+
key = yield(buffer)
|
409
|
+
assert_equal "ecdsa-sha2-nistp384", key.ssh_type
|
410
|
+
assert_equal k.public_key, key.public_key
|
411
|
+
end
|
412
|
+
|
413
|
+
def random_ecdsa_sha2_nistp521
|
414
|
+
k = OpenSSL::PKey::EC.new("secp521r1").generate_key
|
415
|
+
buffer = Net::SSH::Buffer.from(:string, "nistp521",
|
416
|
+
:string, k.public_key.to_bn.to_s(2))
|
417
|
+
key = yield(buffer)
|
418
|
+
assert_equal "ecdsa-sha2-nistp521", key.ssh_type
|
419
|
+
assert_equal k.public_key, key.public_key
|
420
|
+
end
|
421
|
+
end
|
422
|
+
|
333
423
|
def new(*args)
|
334
424
|
Net::SSH::Buffer.new(*args)
|
335
425
|
end
|
336
|
-
end
|
426
|
+
end
|
data/test/test_key_factory.rb
CHANGED
@@ -55,6 +55,34 @@ class TestKeyFactory < Test::Unit::TestCase
|
|
55
55
|
assert_equal rsa_key.to_blob, Net::SSH::KeyFactory.load_public_key(@key_file).to_blob
|
56
56
|
end
|
57
57
|
|
58
|
+
if defined?(OpenSSL::PKey::EC)
|
59
|
+
def test_load_unencrypted_private_ecdsa_sha2_nistp256_key_should_return_key
|
60
|
+
File.expects(:read).with("/key-file").returns(ecdsa_sha2_nistp256_key.to_pem)
|
61
|
+
assert_equal ecdsa_sha2_nistp256_key.to_der, Net::SSH::KeyFactory.load_private_key("/key-file").to_der
|
62
|
+
end
|
63
|
+
def test_load_unencrypted_private_ecdsa_sha2_nistp384_key_should_return_key
|
64
|
+
File.expects(:read).with("/key-file").returns(ecdsa_sha2_nistp384_key.to_pem)
|
65
|
+
assert_equal ecdsa_sha2_nistp384_key.to_der, Net::SSH::KeyFactory.load_private_key("/key-file").to_der
|
66
|
+
end
|
67
|
+
def test_load_unencrypted_private_ecdsa_sha2_nistp521_key_should_return_key
|
68
|
+
File.expects(:read).with("/key-file").returns(ecdsa_sha2_nistp521_key.to_pem)
|
69
|
+
assert_equal ecdsa_sha2_nistp521_key.to_der, Net::SSH::KeyFactory.load_private_key("/key-file").to_der
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_load_public_ecdsa_sha2_nistp256_key_should_return_key
|
73
|
+
File.expects(:read).with("/key-file").returns(public(ecdsa_sha2_nistp256_key))
|
74
|
+
assert_equal ecdsa_sha2_nistp256_key.to_blob, Net::SSH::KeyFactory.load_public_key("/key-file").to_blob
|
75
|
+
end
|
76
|
+
def test_load_public_ecdsa_sha2_nistp384_key_should_return_key
|
77
|
+
File.expects(:read).with("/key-file").returns(public(ecdsa_sha2_nistp384_key))
|
78
|
+
assert_equal ecdsa_sha2_nistp384_key.to_blob, Net::SSH::KeyFactory.load_public_key("/key-file").to_blob
|
79
|
+
end
|
80
|
+
def test_load_public_ecdsa_sha2_nistp521_key_should_return_key
|
81
|
+
File.expects(:read).with("/key-file").returns(public(ecdsa_sha2_nistp521_key))
|
82
|
+
assert_equal ecdsa_sha2_nistp521_key.to_blob, Net::SSH::KeyFactory.load_public_key("/key-file").to_blob
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
58
86
|
private
|
59
87
|
|
60
88
|
def rsa_key
|
@@ -67,6 +95,20 @@ class TestKeyFactory < Test::Unit::TestCase
|
|
67
95
|
@dsa_key ||= OpenSSL::PKey::DSA.new("0\201\367\002\001\000\002A\000\203\316/\037u\272&J\265\003l3\315d\324h\372{\t8\252#\331_\026\006\035\270\266\255\343\353Z\302\276\335\336\306\220\375\202L\244\244J\206>\346\b\315\211\302L\246x\247u\a\376\366\345\302\016#\002\025\000\244\274\302\221Og\275/\302+\356\346\360\024\373wI\2573\361\002@\027\215\270r*\f\213\350C\245\021:\350 \006\\\376\345\022`\210b\262\3643\023XLKS\320\370\002\276\347A\nU\204\276\324\256`=\026\240\330\306J\316V\213\024\e\030\215\355\006\037q\337\356ln\002@\017\257\034\f\260\333'S\271#\237\230E\321\312\027\021\226\331\251Vj\220\305\316\036\v\266+\000\230\270\177B\003?t\a\305]e\344\261\334\023\253\323\251\223M\2175)a(\004\"lI8\312\303\307\a\002\024_\aznW\345\343\203V\326\246ua\203\376\201o\350\302\002")
|
68
96
|
end
|
69
97
|
|
98
|
+
if defined?(OpenSSL::PKey::EC)
|
99
|
+
def ecdsa_sha2_nistp256_key
|
100
|
+
@ecdsa_sha2_nistp256_key ||= OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINv6pPVLlkqvT1v5MJlWgaSWGwqupISG4U79bUXQDNCaoAoGCCqGSM49\nAwEHoUQDQgAElqubvi/GkSme+bwtncU1NiE0dWQ0EO07VufUQg8lUJ5+Fi6f96qa\n95T1zwOMQhY1h8PP9rQIZr4S48vN/ZnQLw==\n-----END EC PRIVATE KEY-----\n")
|
101
|
+
end
|
102
|
+
|
103
|
+
def ecdsa_sha2_nistp384_key
|
104
|
+
@ecdsa_sha2_nistp384_key ||= OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDBxwkmydCn4mP4KMhlMpeBvIroQolWKVNoRPXpG7brFgK+Yiikqw8wd\nIZW5OlL4y3mgBwYFK4EEACKhZANiAARkoIR1oABi+aQJbKcmvzeYSKURQOyXM0HU\nR4T68v4hd/lJE4fFQRczj3wAaECe9u3CWI/oDlow4Vr0vab82ZGjIoblxblKQWYl\nyzENgzl226waGg1bLBo8Auilyf1B5yI=\n-----END EC PRIVATE KEY-----\n")
|
105
|
+
end
|
106
|
+
|
107
|
+
def ecdsa_sha2_nistp521_key
|
108
|
+
@ecdsa_sha2_nistp521_key ||= OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMIHbAgEBBEHQ2i7kjEGQHQB4pUQW9a2eCLWR2S5Go8U3CDyfbRCrYEp/pTSgI8uu\nMXyR3bf3SjqFQgZ6MZk5lkyrissJuwmvZKAHBgUrgQQAI6GBiQOBhgAEAN14FACK\nbs/KTqw4rxijeozGTVJTh1hNzBl2XaIhM4Fv8o3fE/pvogymyFu53GCng6gC4dmx\n/hycF41iIM29xVKPAeBnRNl6MdFBjuthOmE8eCRezgk1Bak8aBDUrzNT8OQssscw\npvQK4nc6ga/wTDaQGy5kV8tCOHNs2wKH+p2LpWTJ\n-----END EC PRIVATE KEY-----\n")
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
70
112
|
def encrypted(key, password)
|
71
113
|
key.export(OpenSSL::Cipher::Cipher.new("des-ede3-cbc"), password)
|
72
114
|
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/transport/hmac/ripemd160'
|
3
|
+
|
4
|
+
module Transport; module HMAC
|
5
|
+
|
6
|
+
class TestRipemd160 < Test::Unit::TestCase
|
7
|
+
def test_expected_digest_class
|
8
|
+
assert_equal OpenSSL::Digest::RIPEMD160, subject.digest_class
|
9
|
+
assert_equal OpenSSL::Digest::RIPEMD160, subject.new.digest_class
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_expected_key_length
|
13
|
+
assert_equal 20, subject.key_length
|
14
|
+
assert_equal 20, subject.new.key_length
|
15
|
+
end
|
16
|
+
|
17
|
+
def test_expected_mac_length
|
18
|
+
assert_equal 20, subject.mac_length
|
19
|
+
assert_equal 20, subject.new.mac_length
|
20
|
+
end
|
21
|
+
|
22
|
+
def test_expected_digest
|
23
|
+
hmac = subject.new("1234567890123456")
|
24
|
+
assert_equal "\xE4\x10\t\xB3\xD8,\x14\xA0k\x10\xB5\x0F?\x0E\x96q\x02\x16;E", hmac.digest("hello world")
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def subject
|
30
|
+
Net::SSH::Transport::HMAC::RIPEMD160
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
end; end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/transport/kex/diffie_hellman_group14_sha1'
|
3
|
+
require 'transport/kex/test_diffie_hellman_group1_sha1'
|
4
|
+
require 'ostruct'
|
5
|
+
|
6
|
+
module Transport; module Kex
|
7
|
+
|
8
|
+
class TestDiffieHellmanGroup14SHA1 < TestDiffieHellmanGroup1SHA1
|
9
|
+
def subject
|
10
|
+
Net::SSH::Transport::Kex::DiffieHellmanGroup14SHA1
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end; end
|
@@ -0,0 +1,161 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
unless defined?(OpenSSL::PKey::EC)
|
4
|
+
puts "Skipping tests for ecdh-sha2-nistp256 key exchange"
|
5
|
+
else
|
6
|
+
require 'common'
|
7
|
+
require 'transport/kex/test_diffie_hellman_group1_sha1'
|
8
|
+
require 'net/ssh/transport/kex/ecdh_sha2_nistp256'
|
9
|
+
require 'ostruct'
|
10
|
+
|
11
|
+
module Transport; module Kex
|
12
|
+
|
13
|
+
class TestEcdhSHA2NistP256 < Test::Unit::TestCase
|
14
|
+
include Net::SSH::Transport::Constants
|
15
|
+
|
16
|
+
def setup
|
17
|
+
@ecdh = @algorithms = @connection = @server_key =
|
18
|
+
@packet_data = @shared_secret = nil
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_exchange_keys_should_return_expected_results_when_successful
|
22
|
+
result = exchange!
|
23
|
+
assert_equal session_id, result[:session_id]
|
24
|
+
assert_equal server_host_key.to_blob, result[:server_key].to_blob
|
25
|
+
assert_equal shared_secret, result[:shared_secret]
|
26
|
+
assert_equal digester, result[:hashing_algorithm]
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_exchange_keys_with_unverifiable_host_should_raise_exception
|
30
|
+
connection.verifier { false }
|
31
|
+
assert_raises(Net::SSH::Exception) { exchange! }
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_exchange_keys_with_signature_key_type_mismatch_should_raise_exception
|
35
|
+
assert_raises(Net::SSH::Exception) { exchange! :key_type => "ssh-dss" }
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_exchange_keys_with_host_key_type_mismatch_should_raise_exception
|
39
|
+
algorithms :host_key => "ssh-dss"
|
40
|
+
assert_raises(Net::SSH::Exception) { exchange! :key_type => "ssh-dss" }
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_exchange_keys_when_server_signature_could_not_be_verified_should_raise_exception
|
44
|
+
@signature = "1234567890"
|
45
|
+
assert_raises(Net::SSH::Exception) { exchange! }
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_exchange_keys_should_pass_expected_parameters_to_host_key_verifier
|
49
|
+
verified = false
|
50
|
+
connection.verifier do |data|
|
51
|
+
verified = true
|
52
|
+
assert_equal server_host_key.to_blob, data[:key].to_blob
|
53
|
+
|
54
|
+
blob = b(:key, data[:key]).to_s
|
55
|
+
fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":")
|
56
|
+
|
57
|
+
assert_equal blob, data[:key_blob]
|
58
|
+
assert_equal fingerprint, data[:fingerprint]
|
59
|
+
assert_equal connection, data[:session]
|
60
|
+
|
61
|
+
true
|
62
|
+
end
|
63
|
+
|
64
|
+
assert_nothing_raised { exchange! }
|
65
|
+
assert verified
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
|
70
|
+
def digester
|
71
|
+
OpenSSL::Digest::SHA256
|
72
|
+
end
|
73
|
+
|
74
|
+
def subject
|
75
|
+
Net::SSH::Transport::Kex::EcdhSHA2NistP256
|
76
|
+
end
|
77
|
+
|
78
|
+
def ecparam
|
79
|
+
"prime256v1"
|
80
|
+
end
|
81
|
+
|
82
|
+
def key_type
|
83
|
+
"ecdsa-sha2-nistp256"
|
84
|
+
end
|
85
|
+
|
86
|
+
def exchange!(options={})
|
87
|
+
connection.expect do |t, buffer|
|
88
|
+
assert_equal KEXECDH_INIT, buffer.type
|
89
|
+
assert_equal ecdh.ecdh.public_key.to_bn.to_s(2), buffer.read_string
|
90
|
+
t.return(KEXECDH_REPLY,
|
91
|
+
:string, b(:key, server_host_key),
|
92
|
+
:string, server_ecdh_pubkey.to_bn.to_s(2),
|
93
|
+
:string, b(:string, options[:key_type] || key_type,
|
94
|
+
:string, signature))
|
95
|
+
connection.expect do |t2, buffer2|
|
96
|
+
assert_equal NEWKEYS, buffer2.type
|
97
|
+
t2.return(NEWKEYS)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
ecdh.exchange_keys
|
101
|
+
end
|
102
|
+
|
103
|
+
def ecdh
|
104
|
+
@ecdh ||= subject.new(algorithms, connection, packet_data)
|
105
|
+
end
|
106
|
+
|
107
|
+
def algorithms(options={})
|
108
|
+
@algorithms ||= OpenStruct.new(:host_key => options[:server_host_key] || "ecdsa-sha2-nistp256")
|
109
|
+
end
|
110
|
+
|
111
|
+
def connection
|
112
|
+
@connection ||= MockTransport.new
|
113
|
+
end
|
114
|
+
|
115
|
+
def server_key
|
116
|
+
@server_key ||= OpenSSL::PKey::EC.new(ecparam).generate_key
|
117
|
+
end
|
118
|
+
|
119
|
+
def server_host_key
|
120
|
+
@server_host_key ||= OpenSSL::PKey::EC.new("prime256v1").generate_key
|
121
|
+
end
|
122
|
+
|
123
|
+
def packet_data
|
124
|
+
@packet_data ||= { :client_version_string => "client version string",
|
125
|
+
:server_version_string => "server version string",
|
126
|
+
:server_algorithm_packet => "server algorithm packet",
|
127
|
+
:client_algorithm_packet => "client algorithm packet" }
|
128
|
+
end
|
129
|
+
|
130
|
+
def server_ecdh_pubkey
|
131
|
+
@server_ecdh_pubkey ||= server_key.public_key
|
132
|
+
end
|
133
|
+
|
134
|
+
def shared_secret
|
135
|
+
@shared_secret ||= OpenSSL::BN.new(ecdh.ecdh.dh_compute_key(server_ecdh_pubkey), 2)
|
136
|
+
end
|
137
|
+
|
138
|
+
def session_id
|
139
|
+
@session_id ||= begin
|
140
|
+
buffer = Net::SSH::Buffer.from(:string, packet_data[:client_version_string],
|
141
|
+
:string, packet_data[:server_version_string],
|
142
|
+
:string, packet_data[:client_algorithm_packet],
|
143
|
+
:string, packet_data[:server_algorithm_packet],
|
144
|
+
:string, Net::SSH::Buffer.from(:key, server_host_key),
|
145
|
+
:string, ecdh.ecdh.public_key.to_bn.to_s(2),
|
146
|
+
:string, server_ecdh_pubkey.to_bn.to_s(2),
|
147
|
+
:bignum, shared_secret)
|
148
|
+
digester.digest(buffer.to_s)
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def signature
|
153
|
+
@signature ||= server_host_key.ssh_do_sign(session_id)
|
154
|
+
end
|
155
|
+
|
156
|
+
def b(*args)
|
157
|
+
Net::SSH::Buffer.from(*args)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end; end;
|
161
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
unless defined?(OpenSSL::PKey::EC)
|
4
|
+
puts "Skipping tests for ecdh-sha2-nistp384 key exchange"
|
5
|
+
else
|
6
|
+
module Transport; module Kex
|
7
|
+
class TestEcdhSHA2NistP384 < TestEcdhSHA2NistP256
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@ecdh = @algorithms = @connection = @server_key =
|
11
|
+
@packet_data = @shared_secret = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_exchange_keys_should_return_expected_results_when_successful
|
15
|
+
result = exchange!
|
16
|
+
assert_equal session_id, result[:session_id]
|
17
|
+
assert_equal server_host_key.to_blob, result[:server_key].to_blob
|
18
|
+
assert_equal shared_secret, result[:shared_secret]
|
19
|
+
assert_equal digester, result[:hashing_algorithm]
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def digester
|
25
|
+
OpenSSL::Digest::SHA384
|
26
|
+
end
|
27
|
+
|
28
|
+
def subject
|
29
|
+
Net::SSH::Transport::Kex::EcdhSHA2NistP384
|
30
|
+
end
|
31
|
+
|
32
|
+
def ecparam
|
33
|
+
"secp384r1"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end; end
|
37
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
unless defined?(OpenSSL::PKey::EC)
|
4
|
+
puts "Skipping tests for ecdh-sha2-nistp521 key exchange"
|
5
|
+
else
|
6
|
+
module Transport; module Kex
|
7
|
+
class TestEcdhSHA2NistP521 < TestEcdhSHA2NistP256
|
8
|
+
|
9
|
+
def setup
|
10
|
+
@ecdh = @algorithms = @connection = @server_key =
|
11
|
+
@packet_data = @shared_secret = nil
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_exchange_keys_should_return_expected_results_when_successful
|
15
|
+
result = exchange!
|
16
|
+
assert_equal session_id, result[:session_id]
|
17
|
+
assert_equal server_host_key.to_blob, result[:server_key].to_blob
|
18
|
+
assert_equal shared_secret, result[:shared_secret]
|
19
|
+
assert_equal digester, result[:hashing_algorithm]
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def digester
|
25
|
+
OpenSSL::Digest::SHA512
|
26
|
+
end
|
27
|
+
|
28
|
+
def subject
|
29
|
+
Net::SSH::Transport::Kex::EcdhSHA2NistP521
|
30
|
+
end
|
31
|
+
|
32
|
+
def ecparam
|
33
|
+
"secp521r1"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end; end
|
37
|
+
end
|