putty-key 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +3 -0
  3. data.tar.gz.sig +1 -0
  4. data/.yardopts +7 -0
  5. data/CHANGES.md +4 -0
  6. data/Gemfile +14 -0
  7. data/LICENSE +19 -0
  8. data/README.md +137 -0
  9. data/Rakefile +110 -0
  10. data/lib/putty/key.rb +25 -0
  11. data/lib/putty/key/error.rb +26 -0
  12. data/lib/putty/key/openssl.rb +182 -0
  13. data/lib/putty/key/ppk.rb +374 -0
  14. data/lib/putty/key/util.rb +128 -0
  15. data/lib/putty/key/version.rb +6 -0
  16. data/putty-key.gemspec +29 -0
  17. data/test/fixtures/dss-1024-encrypted.ppk +17 -0
  18. data/test/fixtures/dss-1024.pem +12 -0
  19. data/test/fixtures/dss-1024.ppk +17 -0
  20. data/test/fixtures/ecdsa-secp256k1.pem +5 -0
  21. data/test/fixtures/ecdsa-sha2-nistp256-encrypted.ppk +10 -0
  22. data/test/fixtures/ecdsa-sha2-nistp256.pem +5 -0
  23. data/test/fixtures/ecdsa-sha2-nistp256.ppk +10 -0
  24. data/test/fixtures/ecdsa-sha2-nistp384-encrypted.ppk +11 -0
  25. data/test/fixtures/ecdsa-sha2-nistp384.pem +6 -0
  26. data/test/fixtures/ecdsa-sha2-nistp384.ppk +11 -0
  27. data/test/fixtures/ecdsa-sha2-nistp521-encrypted.ppk +12 -0
  28. data/test/fixtures/ecdsa-sha2-nistp521.pem +7 -0
  29. data/test/fixtures/ecdsa-sha2-nistp521.ppk +12 -0
  30. data/test/fixtures/rsa-2048-encrypted.ppk +26 -0
  31. data/test/fixtures/rsa-2048.pem +27 -0
  32. data/test/fixtures/rsa-2048.ppk +26 -0
  33. data/test/fixtures/test-blank-comment.ppk +11 -0
  34. data/test/fixtures/test-encrypted.ppk +11 -0
  35. data/test/fixtures/test-invalid-blob-lines.ppk +11 -0
  36. data/test/fixtures/test-invalid-encryption-type.ppk +11 -0
  37. data/test/fixtures/test-invalid-format-1.ppk +11 -0
  38. data/test/fixtures/test-invalid-format-3.ppk +11 -0
  39. data/test/fixtures/test-invalid-private-mac.ppk +11 -0
  40. data/test/fixtures/test-truncated.ppk +10 -0
  41. data/test/fixtures/test-unix-line-endings.ppk +11 -0
  42. data/test/fixtures/test.ppk +11 -0
  43. data/test/openssl_test.rb +252 -0
  44. data/test/ppk_test.rb +247 -0
  45. data/test/test_helper.rb +81 -0
  46. data/test/util_test.rb +180 -0
  47. data/test/version_test.rb +7 -0
  48. metadata +124 -0
  49. metadata.gz.sig +0 -0
data/test/ppk_test.rb ADDED
@@ -0,0 +1,247 @@
1
+ require 'test_helper'
2
+ require 'pathname'
3
+
4
+ class PPKTest < Minitest::Test
5
+ TEST_COMMENT = 'This is a test ppk file'.b
6
+ TEST_PUBLIC_BLOB = "\x00\x00\x00\x04test\x00\x00\x00\x4AThis is the public blob from a ppk file created for testing purposes only.".b
7
+ TEST_PRIVATE_BLOB = "\x00\x00\x00\x77This is the private blob from a ppk file created for testing purposes only. It is slightly longer than the public blob.".b
8
+
9
+ def test_initialize
10
+ ppk = PuTTY::Key::PPK.new
11
+ assert_nil(ppk.algorithm)
12
+ assert_nil(ppk.comment)
13
+ assert_nil(ppk.public_blob)
14
+ assert_nil(ppk.private_blob)
15
+ end
16
+
17
+ def test_initialize_invalid_format
18
+ [1,3].each do |format|
19
+ assert_raises(PuTTY::Key::FormatError) { PuTTY::Key::PPK.new(fixture_path("test-invalid-format-#{format}.ppk")) }
20
+ end
21
+ end
22
+
23
+ def test_initialize_invalid_encryption_type
24
+ assert_raises(PuTTY::Key::FormatError) { PuTTY::Key::PPK.new(fixture_path('test-invalid-encryption-type.ppk')) }
25
+ end
26
+
27
+ def test_initialize_invalid_private_mac
28
+ assert_raises(PuTTY::Key::FormatError) { PuTTY::Key::PPK.new(fixture_path('test-invalid-private-mac.ppk')) }
29
+ end
30
+
31
+ def test_initialize_file_not_exists
32
+ temp_dir do |dir|
33
+ assert_raises(Errno::ENOENT) { PuTTY::Key::PPK.new(File.join(dir, 'missing')) }
34
+ end
35
+ end
36
+
37
+ def test_initialize_non_ppk
38
+ assert_raises(PuTTY::Key::FormatError) { PuTTY::Key::PPK.new(fixture_path('rsa-2048.pem')) }
39
+ end
40
+
41
+ def test_initialize_truncated
42
+ assert_raises(PuTTY::Key::FormatError) { PuTTY::Key::PPK.new(fixture_path('test-truncated.ppk')) }
43
+ end
44
+
45
+ def test_initialize_invalid_blob_lines
46
+ assert_raises(PuTTY::Key::FormatError) { PuTTY::Key::PPK.new(fixture_path('test-invalid-blob-lines.ppk')) }
47
+ end
48
+
49
+ def assert_test_ppk_properties(ppk, comment: TEST_COMMENT, encrypted: false)
50
+ assert_equal(Encoding::ASCII_8BIT, ppk.algorithm.encoding)
51
+ assert_equal(Encoding::ASCII_8BIT, ppk.comment.encoding)
52
+ assert_equal(Encoding::ASCII_8BIT, ppk.public_blob.encoding)
53
+ assert_equal(Encoding::ASCII_8BIT, ppk.private_blob.encoding)
54
+ assert_equal('test'.b, ppk.algorithm)
55
+ assert_equal(comment, ppk.comment)
56
+ assert_equal(TEST_PUBLIC_BLOB, ppk.public_blob)
57
+
58
+ if encrypted
59
+ # When loading an encrypted ppk file, the padding added to the private blob cannot be removed.
60
+ assert(ppk.private_blob.start_with?(TEST_PRIVATE_BLOB), "Private blob does not start with #{TEST_PRIVATE_BLOB}")
61
+ else
62
+ assert_equal(TEST_PRIVATE_BLOB, ppk.private_blob)
63
+ end
64
+ end
65
+
66
+ def test_initialize_unencrypted
67
+ ppk = PuTTY::Key::PPK.new(fixture_path('test.ppk'))
68
+ assert_test_ppk_properties(ppk)
69
+ end
70
+
71
+ def test_initialize_blank_comment
72
+ ppk = PuTTY::Key::PPK.new(fixture_path('test-blank-comment.ppk'))
73
+ assert_test_ppk_properties(ppk, comment: ''.b)
74
+ end
75
+
76
+ def test_initialize_encrypted
77
+ ppk = PuTTY::Key::PPK.new(fixture_path('test-encrypted.ppk'), 'Test Passphrase')
78
+ assert_test_ppk_properties(ppk, encrypted: true)
79
+ end
80
+
81
+ def test_initialize_encrypted_no_passphrase
82
+ assert_raises(ArgumentError) { PuTTY::Key::PPK.new(fixture_path('test-encrypted.ppk')) }
83
+ end
84
+
85
+ def test_initialize_encrypted_incorrect_passphrase
86
+ assert_raises(ArgumentError) { PuTTY::Key::PPK.new(fixture_path('test-encrypted.ppk'), 'Not Test Passphrase') }
87
+ end
88
+
89
+ def test_initialize_pathname
90
+ ppk = PuTTY::Key::PPK.new(Pathname.new(fixture_path('test.ppk')))
91
+ assert_test_ppk_properties(ppk)
92
+ end
93
+
94
+ def test_initialize_unix_line_endings
95
+ ppk = PuTTY::Key::PPK.new(fixture_path('test-unix-line-endings.ppk'))
96
+ assert_test_ppk_properties(ppk)
97
+ end
98
+
99
+ def create_test_ppk
100
+ PuTTY::Key::PPK.new.tap do |ppk|
101
+ ppk.algorithm = 'test'
102
+ ppk.comment = TEST_COMMENT
103
+ ppk.public_blob = TEST_PUBLIC_BLOB
104
+ ppk.private_blob = TEST_PRIVATE_BLOB
105
+ end
106
+ end
107
+
108
+ def test_save_path_nil
109
+ ppk = create_test_ppk
110
+ assert_raises(ArgumentError) { ppk.save(nil) }
111
+ end
112
+
113
+ def test_save_passphrase_encryption_type_nil
114
+ ppk = create_test_ppk
115
+ temp_file_name do |file|
116
+ assert_raises(ArgumentError) { ppk.save(file, 'Test Passphrase', encryption_type: nil) }
117
+ end
118
+ end
119
+
120
+ def test_save_passphrase_encryption_type_none
121
+ ppk = create_test_ppk
122
+ temp_file_name do |file|
123
+ assert_raises(ArgumentError) { ppk.save(file, 'Test Passphrase', encryption_type: 'none') }
124
+ end
125
+ end
126
+
127
+ def test_save_passphrase_unsupported_encryption_type
128
+ ppk = create_test_ppk
129
+ temp_file_name do |file|
130
+ assert_raises(ArgumentError) { ppk.save(file, 'Test Passphrase', encryption_type: 'camellia256-cbc') }
131
+ end
132
+ end
133
+
134
+ def test_save_format_nil
135
+ ppk = create_test_ppk
136
+ temp_file_name do |file|
137
+ assert_raises(ArgumentError) { ppk.save(file, 'Test Passphrase', format: nil) }
138
+ end
139
+ end
140
+
141
+ def test_save_format_not_supported
142
+ ppk = create_test_ppk
143
+ temp_file_name do |file|
144
+ [1,3].each do |format|
145
+ assert_raises(ArgumentError) { ppk.save(file, 'Test Passphrase', format: format) }
146
+ end
147
+ end
148
+ end
149
+
150
+ def test_save_dir_not_exists
151
+ ppk = create_test_ppk
152
+ temp_dir do |dir|
153
+ assert_raises(Errno::ENOENT) { ppk.save(File.join(dir, 'missing', 'file')) }
154
+ end
155
+ end
156
+
157
+ def test_save_algorithm_nil
158
+ ppk = create_test_ppk
159
+ ppk.algorithm = nil
160
+ temp_file_name do |file|
161
+ assert_raises(PuTTY::Key::InvalidStateError) { ppk.save(file) }
162
+ end
163
+ end
164
+
165
+ def test_save_public_blob_nil
166
+ ppk = create_test_ppk
167
+ ppk.public_blob = nil
168
+ temp_file_name do |file|
169
+ assert_raises(PuTTY::Key::InvalidStateError) { ppk.save(file) }
170
+ end
171
+ end
172
+
173
+ def test_save_private_blob_nil
174
+ ppk = create_test_ppk
175
+ ppk.private_blob = nil
176
+ temp_file_name do |file|
177
+ assert_raises(PuTTY::Key::InvalidStateError) { ppk.save(file) }
178
+ end
179
+ end
180
+
181
+ def test_save_unencrypted
182
+ ppk = create_test_ppk
183
+ temp_file_name do |file|
184
+ ppk.save(file)
185
+ assert_identical_to_fixture('test.ppk', file)
186
+ end
187
+ end
188
+
189
+ def test_save_passphrase_empty
190
+ ppk = create_test_ppk
191
+ temp_file_name do |file|
192
+ ppk.save(file, '')
193
+ assert_identical_to_fixture('test.ppk', file)
194
+ end
195
+ end
196
+
197
+ def test_save_encrypted
198
+ ppk = create_test_ppk
199
+ temp_file_name do |file|
200
+ ppk.save(file, 'Test Passphrase')
201
+ assert_identical_to_fixture('test-encrypted.ppk', file)
202
+ end
203
+ end
204
+
205
+ def test_save_comment_empty
206
+ ppk = create_test_ppk
207
+ ppk.comment = ''
208
+ temp_file_name do |file|
209
+ ppk.save(file)
210
+ assert_identical_to_fixture('test-blank-comment.ppk', file)
211
+ end
212
+ end
213
+
214
+ def test_save_comment_nil
215
+ ppk = create_test_ppk
216
+ ppk.comment = nil
217
+ temp_file_name do |file|
218
+ ppk.save(file)
219
+ assert_identical_to_fixture('test-blank-comment.ppk', file)
220
+ end
221
+ end
222
+
223
+ def test_save_pathname
224
+ ppk = create_test_ppk
225
+ temp_file_name do |file|
226
+ ppk.save(Pathname.new(file))
227
+ assert_identical_to_fixture('test.ppk', file)
228
+ end
229
+ end
230
+
231
+ def test_save_overwrite
232
+ ppk = create_test_ppk
233
+ temp_file_name do |file|
234
+ File.open(file, 'w') { |f| f.write('not test.ppk') }
235
+ ppk.save(file)
236
+ assert_identical_to_fixture('test.ppk', file)
237
+ end
238
+ end
239
+
240
+ def test_save_result
241
+ ppk = create_test_ppk
242
+ temp_file_name do |file|
243
+ result = ppk.save(file)
244
+ assert_equal(File.size(file), result)
245
+ end
246
+ end
247
+ end
@@ -0,0 +1,81 @@
1
+ TEST_TYPE = (ENV['TEST_TYPE'] || 'refinement').to_sym
2
+ raise "Unrecognized TEST_TYPE: #{TEST_TYPE}" unless [:refinement, :global].include?(TEST_TYPE)
3
+
4
+ TEST_COVERAGE = ENV['TEST_COVERAGE'] != '0'
5
+
6
+ if TEST_COVERAGE
7
+ require 'simplecov'
8
+ require 'coveralls'
9
+
10
+ SimpleCov.command_name TEST_TYPE.to_s
11
+
12
+ SimpleCov.formatters = [
13
+ SimpleCov::Formatter::HTMLFormatter
14
+ ]
15
+
16
+ SimpleCov.start do
17
+ add_filter 'test'
18
+ project_name 'PuTTY::Key'
19
+ end
20
+ end
21
+
22
+ require 'putty/key'
23
+
24
+ require 'fileutils'
25
+ require 'minitest/autorun'
26
+ require 'tmpdir'
27
+
28
+ PuTTY::Key.global_install if TEST_TYPE == :global
29
+
30
+ module TestHelper
31
+ BASE_DIR = File.expand_path(File.dirname(__FILE__))
32
+
33
+ module Assertions
34
+ def assert_files_identical(exp, act, msg = nil)
35
+ msg = message(msg) { "Expected file #{act} to be identical to #{exp}\n\n#{act}:\n#{File.read(act)}\n\n#{exp}:\n#{File.read(exp)}\n" }
36
+ assert(FileUtils.identical?(exp, act), msg)
37
+ end
38
+
39
+ def assert_identical_to_fixture(exp_fixture, act_file, msg = nil)
40
+ assert_files_identical(fixture_path(exp_fixture), act_file, msg)
41
+ end
42
+ end
43
+
44
+ module Fixtures
45
+ FIXTURES_DIR = File.join(BASE_DIR, 'fixtures')
46
+
47
+ def fixture_path(fixture)
48
+ File.join(FIXTURES_DIR, fixture)
49
+ end
50
+
51
+ def load_fixture(fixture)
52
+ File.read(fixture_path(fixture), mode: 'rb')
53
+ end
54
+ end
55
+
56
+ module Utils
57
+ def temp_dir(&block)
58
+ Dir.mktmpdir('putty-key', &block)
59
+ end
60
+
61
+ def temp_file_name(name = nil)
62
+ temp_dir do |dir|
63
+ file = File.join(dir, name || 'test')
64
+ yield file
65
+ end
66
+ end
67
+ end
68
+
69
+ class ::OpenSSL::BN
70
+ # Override to_s so the represented value is visible.
71
+ def inspect
72
+ "#<OpenSSL::BN:#{to_s(16)}>"
73
+ end
74
+ end
75
+ end
76
+
77
+ class Minitest::Test
78
+ include TestHelper::Assertions
79
+ include TestHelper::Fixtures
80
+ include TestHelper::Utils
81
+ end
data/test/util_test.rb ADDED
@@ -0,0 +1,180 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test_helper'
4
+ require 'openssl'
5
+
6
+ # PuTTY::Key::NilValueError and PuTTY::Key::Util are private constants.
7
+ NilValueError = PuTTY::Key.const_get(:NilValueError)
8
+ Util = PuTTY::Key.const_get(:Util)
9
+
10
+ class PPKTest < Minitest::Test
11
+ def test_ssh_pack_empty
12
+ s = Util.ssh_pack
13
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
14
+ assert_equal("".b, s)
15
+ end
16
+
17
+ def test_ssh_pack_nil_element
18
+ assert_raises(NilValueError) { Util.ssh_pack('test', nil, 'test2') }
19
+ end
20
+
21
+ def ssh_pack_string_empty
22
+ s = Util.ssh_pack('')
23
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
24
+ assert_equal("\x00\x00\x00\x00".b, s)
25
+ end
26
+
27
+ def test_ssh_pack_string_utf8
28
+ s = Util.ssh_pack('This is UTF-8: ✓')
29
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
30
+ assert_equal("\x00\x00\x00\x12This is UTF-8: \xe2\x9c\x93".b, s)
31
+ end
32
+
33
+ def test_ssh_pack_string_binary
34
+ s = Util.ssh_pack("\x00\x01\x02\x03\x04".b)
35
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
36
+ assert_equal("\x00\x00\x00\x05\x00\x01\x02\x03\x04".b, s)
37
+ end
38
+
39
+ def test_ssh_pack_bn
40
+ s = Util.ssh_pack(OpenSSL::BN.new(12345678901234567890))
41
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
42
+ assert_equal("\x00\x00\x00\x09\x00\xab\x54\xa9\x8c\xeb\x1f\x0a\xd2".b, s)
43
+ end
44
+
45
+ def test_ssh_pack_bn_postive_msb_unset
46
+ s = Util.ssh_pack(OpenSSL::BN.new(0x7f), OpenSSL::BN.new(0x7fff))
47
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
48
+ assert_equal("\x00\x00\x00\x01\x7f\x00\x00\x00\x02\x7f\xff".b, s)
49
+ end
50
+
51
+ def test_ssh_pack_bn_postive_msb_set
52
+ s = Util.ssh_pack(OpenSSL::BN.new(0x80), OpenSSL::BN.new(0xff), OpenSSL::BN.new(0x8000), OpenSSL::BN.new(0xff00))
53
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
54
+ assert_equal("\x00\x00\x00\x02\x00\x80\x00\x00\x00\x02\x00\xff\x00\x00\x00\x03\x00\x80\x00\x00\x00\x00\x03\x00\xff\x00".b, s)
55
+ end
56
+
57
+ def test_ssh_pack_bn_negative
58
+ s = Util.ssh_pack(OpenSSL::BN.new(-0x01), OpenSSL::BN.new(-0x80), OpenSSL::BN.new(-0x81), OpenSSL::BN.new(-0x0100))
59
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
60
+ assert_equal("\x00\x00\x00\x01\xff\x00\x00\x00\x01\x80\x00\x00\x00\x02\xff\x7f\x00\x00\x00\x02\xff\x00".b, s)
61
+ end
62
+
63
+ def test_ssh_pack_bn_zero
64
+ s = Util.ssh_pack(OpenSSL::BN.new(0))
65
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
66
+ assert_equal("\x00\x00\x00\x00".b, s)
67
+ end
68
+
69
+ def test_ssh_pack_bn_rfc_4251_mpint_examples
70
+ s = Util.ssh_pack(OpenSSL::BN.new(0x0), OpenSSL::BN.new(0x9a378f9b2e332a7), OpenSSL::BN.new(0x80), OpenSSL::BN.new(-0x1234), OpenSSL::BN.new(-0xdeadbeef))
71
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
72
+ assert_equal("\x00\x00\x00\x00\x00\x00\x00\x08\x09\xa3\x78\xf9\xb2\xe3\x32\xa7\x00\x00\x00\x02\x00\x80\x00\x00\x00\x02\xed\xcc\x00\x00\x00\x05\xff\x21\x52\x41\x11".b, s)
73
+ end
74
+
75
+ def test_ssh_pack_mixed
76
+ s = Util.ssh_pack('string1', OpenSSL::BN.new(42), 'string2', OpenSSL::BN.new(1764))
77
+ assert_equal(Encoding::ASCII_8BIT, s.encoding)
78
+ assert_equal("\x00\x00\x00\x07string1\x00\x00\x00\x01\x2a\x00\x00\x00\x07string2\x00\x00\x00\x02\x06\xe4".b, s)
79
+ end
80
+
81
+ def test_ssh_unpack_encoded_nil
82
+ assert_raises(ArgumentError) { Util.ssh_unpack(nil) }
83
+ end
84
+
85
+ def test_ssh_unpack_encoded_not_binary
86
+ assert_raises(ArgumentError) { Util.ssh_unpack('\x00\x00\x00\x12This is UTF-8: ✓', :string) }
87
+ end
88
+
89
+ def test_ssh_unpack_spec_empty
90
+ assert_equal([], Util.ssh_unpack("\x00\x00\x00\x06string".b))
91
+ end
92
+
93
+ def test_ssh_unpack_spec_invalid
94
+ assert_raises(ArgumentError) { Util.ssh_unpack("\x00\x00\x00\x07string1\x00\x00\x00\x07string2\x00\x00\x00\x07string3".b, :string, :unknown, :string) }
95
+ end
96
+
97
+ def test_ssh_unpack_spec_longer_than_encoded
98
+ assert_raises(PuTTY::Key::FormatError) { Util.ssh_unpack("\x00\x00\x00\x06string".b, :string, :string) }
99
+ end
100
+
101
+ def test_ssh_unpack_encoded_truncated_value
102
+ assert_raises(PuTTY::Key::FormatError) { Util.ssh_unpack("\x00\x00\x00\x06str".b, :string) }
103
+ end
104
+
105
+ def test_ssh_unpack_encoded_truncated_length
106
+ assert_raises(PuTTY::Key::FormatError) { Util.ssh_unpack("\x00\x00".b, :string) }
107
+ end
108
+
109
+ def test_ssh_unpack_encoded_missing_value
110
+ assert_raises(PuTTY::Key::FormatError) { Util.ssh_unpack("\x00\x00\x00\x06".b, :string) }
111
+ end
112
+
113
+ def test_ssh_unpack_string_empty
114
+ a = Util.ssh_unpack("\x00\x00\x00\x00".b, :string)
115
+ assert_equal([''.b], a)
116
+ assert_kind_of(String, a[0])
117
+ assert_equal(Encoding::ASCII_8BIT, a[0].encoding)
118
+ end
119
+
120
+ def test_ssh_unpack_string_utf8
121
+ a = Util.ssh_unpack("\x00\x00\x00\x12This is UTF-8: \xe2\x9c\x93".b, :string)
122
+ assert_equal(["This is UTF-8: \xe2\x9c\x93".b], a)
123
+ assert_kind_of(String, a[0])
124
+ assert_equal(Encoding::ASCII_8BIT, a[0].encoding)
125
+ end
126
+
127
+ def test_ssh_unpack_string_binary
128
+ a = Util.ssh_unpack("\x00\x00\x00\x05\x00\x01\x02\x03\x04".b, :string)
129
+ assert_equal(["\x00\x01\x02\x03\x04".b], a)
130
+ assert_kind_of(String, a[0])
131
+ assert_equal(Encoding::ASCII_8BIT, a[0].encoding)
132
+ end
133
+
134
+ def test_ssh_unpack_bn
135
+ a = Util.ssh_unpack("\x00\x00\x00\x09\x00\xab\x54\xa9\x8c\xeb\x1f\x0a\xd2".b, :mpint)
136
+ assert_equal([OpenSSL::BN.new(12345678901234567890)], a)
137
+ assert_kind_of(OpenSSL::BN, a[0])
138
+ end
139
+
140
+ def test_ssh_unpack_bn_positive_msb_unset
141
+ a = Util.ssh_unpack("\x00\x00\x00\x01\x7f\x00\x00\x00\x02\x7f\xff".b, :mpint, :mpint)
142
+ assert_equal([OpenSSL::BN.new(0x7f), OpenSSL::BN.new(0x7fff)], a)
143
+ a.each {|o| assert_kind_of(OpenSSL::BN, o) }
144
+ end
145
+
146
+ def test_ssh_unpack_bn_positive_msb_set
147
+ a = Util.ssh_unpack("\x00\x00\x00\x02\x00\x80\x00\x00\x00\x02\x00\xff\x00\x00\x00\x03\x00\x80\x00\x00\x00\x00\x03\x00\xff\x00".b, :mpint, :mpint, :mpint, :mpint)
148
+ assert_equal([OpenSSL::BN.new(0x80), OpenSSL::BN.new(0xff), OpenSSL::BN.new(0x8000), OpenSSL::BN.new(0xff00)], a)
149
+ a.each {|o| assert_kind_of(OpenSSL::BN, o) }
150
+ end
151
+
152
+ def test_ssh_unpack_bn_negative
153
+ a = Util.ssh_unpack("\x00\x00\x00\x01\xff\x00\x00\x00\x01\x80\x00\x00\x00\x02\xff\x7f\x00\x00\x00\x02\xff\x00".b, :mpint, :mpint, :mpint, :mpint)
154
+ assert_equal([OpenSSL::BN.new(-0x01), OpenSSL::BN.new(-0x80), OpenSSL::BN.new(-0x81), OpenSSL::BN.new(-0x0100)], a)
155
+ a.each {|o| assert_kind_of(OpenSSL::BN, o) }
156
+ end
157
+
158
+ def test_ssh_unpack_bn_zero
159
+ a = Util.ssh_unpack("\x00\x00\x00\x00".b, :mpint)
160
+ assert_equal([OpenSSL::BN.new(0)], a)
161
+ assert_kind_of(OpenSSL::BN, a[0])
162
+ end
163
+
164
+ def test_ssh_unpack_bn_rfc_4251_mpint_examples
165
+ a = Util.ssh_unpack("\x00\x00\x00\x00\x00\x00\x00\x08\x09\xa3\x78\xf9\xb2\xe3\x32\xa7\x00\x00\x00\x02\x00\x80\x00\x00\x00\x02\xed\xcc\x00\x00\x00\x05\xff\x21\x52\x41\x11".b, :mpint, :mpint, :mpint, :mpint, :mpint)
166
+ assert_equal([OpenSSL::BN.new(0x0), OpenSSL::BN.new(0x9a378f9b2e332a7), OpenSSL::BN.new(0x80), OpenSSL::BN.new(-0x1234), OpenSSL::BN.new(-0xdeadbeef)], a)
167
+ a.each {|o| assert_kind_of(OpenSSL::BN, o) }
168
+ end
169
+
170
+ def test_ssh_unpack_mixed
171
+ a = Util.ssh_unpack("\x00\x00\x00\x07string1\x00\x00\x00\x01\x2a\x00\x00\x00\x07string2\x00\x00\x00\x02\x06\xe4".b, :string, :mpint, :string, :mpint)
172
+ assert_equal(['string1', OpenSSL::BN.new(42), 'string2', OpenSSL::BN.new(1764)], a)
173
+ assert_kind_of(String, a[0])
174
+ assert_kind_of(OpenSSL::BN, a[1])
175
+ assert_kind_of(String, a[2])
176
+ assert_kind_of(OpenSSL::BN, a[3])
177
+ assert_equal(Encoding::ASCII_8BIT, a[0].encoding)
178
+ assert_equal(Encoding::ASCII_8BIT, a[2].encoding)
179
+ end
180
+ end