net-ssh 2.4.0 → 2.5.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.
- 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
|