sonixlabs-net-ssh 2.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.
Files changed (123) hide show
  1. data/CHANGELOG.rdoc +262 -0
  2. data/Manifest +121 -0
  3. data/README.rdoc +184 -0
  4. data/Rakefile +86 -0
  5. data/Rudyfile +96 -0
  6. data/THANKS.rdoc +19 -0
  7. data/lib/net/ssh.rb +223 -0
  8. data/lib/net/ssh/authentication/agent.rb +179 -0
  9. data/lib/net/ssh/authentication/constants.rb +18 -0
  10. data/lib/net/ssh/authentication/key_manager.rb +253 -0
  11. data/lib/net/ssh/authentication/methods/abstract.rb +60 -0
  12. data/lib/net/ssh/authentication/methods/hostbased.rb +75 -0
  13. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +70 -0
  14. data/lib/net/ssh/authentication/methods/password.rb +43 -0
  15. data/lib/net/ssh/authentication/methods/publickey.rb +96 -0
  16. data/lib/net/ssh/authentication/pageant.rb +264 -0
  17. data/lib/net/ssh/authentication/session.rb +146 -0
  18. data/lib/net/ssh/buffer.rb +340 -0
  19. data/lib/net/ssh/buffered_io.rb +198 -0
  20. data/lib/net/ssh/config.rb +207 -0
  21. data/lib/net/ssh/connection/channel.rb +630 -0
  22. data/lib/net/ssh/connection/constants.rb +33 -0
  23. data/lib/net/ssh/connection/session.rb +597 -0
  24. data/lib/net/ssh/connection/term.rb +178 -0
  25. data/lib/net/ssh/errors.rb +88 -0
  26. data/lib/net/ssh/key_factory.rb +102 -0
  27. data/lib/net/ssh/known_hosts.rb +129 -0
  28. data/lib/net/ssh/loggable.rb +61 -0
  29. data/lib/net/ssh/packet.rb +102 -0
  30. data/lib/net/ssh/prompt.rb +93 -0
  31. data/lib/net/ssh/proxy/command.rb +75 -0
  32. data/lib/net/ssh/proxy/errors.rb +14 -0
  33. data/lib/net/ssh/proxy/http.rb +94 -0
  34. data/lib/net/ssh/proxy/socks4.rb +70 -0
  35. data/lib/net/ssh/proxy/socks5.rb +142 -0
  36. data/lib/net/ssh/ruby_compat.rb +43 -0
  37. data/lib/net/ssh/service/forward.rb +298 -0
  38. data/lib/net/ssh/test.rb +89 -0
  39. data/lib/net/ssh/test/channel.rb +129 -0
  40. data/lib/net/ssh/test/extensions.rb +152 -0
  41. data/lib/net/ssh/test/kex.rb +44 -0
  42. data/lib/net/ssh/test/local_packet.rb +51 -0
  43. data/lib/net/ssh/test/packet.rb +81 -0
  44. data/lib/net/ssh/test/remote_packet.rb +38 -0
  45. data/lib/net/ssh/test/script.rb +157 -0
  46. data/lib/net/ssh/test/socket.rb +64 -0
  47. data/lib/net/ssh/transport/algorithms.rb +386 -0
  48. data/lib/net/ssh/transport/cipher_factory.rb +79 -0
  49. data/lib/net/ssh/transport/constants.rb +30 -0
  50. data/lib/net/ssh/transport/hmac.rb +42 -0
  51. data/lib/net/ssh/transport/hmac/abstract.rb +79 -0
  52. data/lib/net/ssh/transport/hmac/md5.rb +12 -0
  53. data/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
  54. data/lib/net/ssh/transport/hmac/none.rb +15 -0
  55. data/lib/net/ssh/transport/hmac/sha1.rb +13 -0
  56. data/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
  57. data/lib/net/ssh/transport/hmac/sha2_256.rb +15 -0
  58. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +13 -0
  59. data/lib/net/ssh/transport/hmac/sha2_512.rb +14 -0
  60. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +13 -0
  61. data/lib/net/ssh/transport/identity_cipher.rb +55 -0
  62. data/lib/net/ssh/transport/kex.rb +17 -0
  63. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +208 -0
  64. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +80 -0
  65. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +15 -0
  66. data/lib/net/ssh/transport/key_expander.rb +26 -0
  67. data/lib/net/ssh/transport/openssl.rb +127 -0
  68. data/lib/net/ssh/transport/packet_stream.rb +235 -0
  69. data/lib/net/ssh/transport/server_version.rb +71 -0
  70. data/lib/net/ssh/transport/session.rb +278 -0
  71. data/lib/net/ssh/transport/state.rb +206 -0
  72. data/lib/net/ssh/verifiers/lenient.rb +30 -0
  73. data/lib/net/ssh/verifiers/null.rb +12 -0
  74. data/lib/net/ssh/verifiers/strict.rb +53 -0
  75. data/lib/net/ssh/version.rb +62 -0
  76. data/lib/sonixlabs-net-ssh.rb +1 -0
  77. data/net-ssh.gemspec +145 -0
  78. data/setup.rb +1585 -0
  79. data/support/arcfour_check.rb +20 -0
  80. data/support/ssh_tunnel_bug.rb +65 -0
  81. data/test/authentication/methods/common.rb +28 -0
  82. data/test/authentication/methods/test_abstract.rb +51 -0
  83. data/test/authentication/methods/test_hostbased.rb +114 -0
  84. data/test/authentication/methods/test_keyboard_interactive.rb +100 -0
  85. data/test/authentication/methods/test_password.rb +52 -0
  86. data/test/authentication/methods/test_publickey.rb +148 -0
  87. data/test/authentication/test_agent.rb +205 -0
  88. data/test/authentication/test_key_manager.rb +171 -0
  89. data/test/authentication/test_session.rb +106 -0
  90. data/test/common.rb +107 -0
  91. data/test/configs/eqsign +3 -0
  92. data/test/configs/exact_match +8 -0
  93. data/test/configs/host_plus +10 -0
  94. data/test/configs/multihost +4 -0
  95. data/test/configs/wild_cards +14 -0
  96. data/test/connection/test_channel.rb +467 -0
  97. data/test/connection/test_session.rb +488 -0
  98. data/test/test_all.rb +9 -0
  99. data/test/test_buffer.rb +336 -0
  100. data/test/test_buffered_io.rb +63 -0
  101. data/test/test_config.rb +120 -0
  102. data/test/test_key_factory.rb +79 -0
  103. data/test/transport/hmac/test_md5.rb +39 -0
  104. data/test/transport/hmac/test_md5_96.rb +25 -0
  105. data/test/transport/hmac/test_none.rb +34 -0
  106. data/test/transport/hmac/test_sha1.rb +34 -0
  107. data/test/transport/hmac/test_sha1_96.rb +25 -0
  108. data/test/transport/hmac/test_sha2_256.rb +35 -0
  109. data/test/transport/hmac/test_sha2_256_96.rb +25 -0
  110. data/test/transport/hmac/test_sha2_512.rb +35 -0
  111. data/test/transport/hmac/test_sha2_512_96.rb +25 -0
  112. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +146 -0
  113. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +92 -0
  114. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +33 -0
  115. data/test/transport/test_algorithms.rb +308 -0
  116. data/test/transport/test_cipher_factory.rb +213 -0
  117. data/test/transport/test_hmac.rb +34 -0
  118. data/test/transport/test_identity_cipher.rb +40 -0
  119. data/test/transport/test_packet_stream.rb +736 -0
  120. data/test/transport/test_server_version.rb +78 -0
  121. data/test/transport/test_session.rb +315 -0
  122. data/test/transport/test_state.rb +179 -0
  123. metadata +178 -0
@@ -0,0 +1,208 @@
1
+ require 'net/ssh/buffer'
2
+ require 'net/ssh/errors'
3
+ require 'net/ssh/loggable'
4
+ require 'net/ssh/transport/openssl'
5
+ require 'net/ssh/transport/constants'
6
+
7
+ module Net; module SSH; module Transport; module Kex
8
+
9
+ # A key-exchange service implementing the "diffie-hellman-group1-sha1"
10
+ # key-exchange algorithm.
11
+ class DiffieHellmanGroup1SHA1
12
+ include Constants, Loggable
13
+
14
+ # The value of 'P', as a string, in hexadecimal
15
+ P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" +
16
+ "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" +
17
+ "020BBEA6" "3B139B22" "514A0879" "8E3404DD" +
18
+ "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" +
19
+ "4FE1356D" "6D51C245" "E485B576" "625E7EC6" +
20
+ "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" +
21
+ "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" +
22
+ "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF"
23
+
24
+ # The radix in which P_s represents the value of P
25
+ P_r = 16
26
+
27
+ # The group constant
28
+ G = 2
29
+
30
+ attr_reader :p
31
+ attr_reader :g
32
+ attr_reader :digester
33
+ attr_reader :algorithms
34
+ attr_reader :connection
35
+ attr_reader :data
36
+ attr_reader :dh
37
+
38
+ # Create a new instance of the DiffieHellmanGroup1SHA1 algorithm.
39
+ # The data is a Hash of symbols representing information
40
+ # required by this algorithm, which was acquired during earlier
41
+ # processing.
42
+ def initialize(algorithms, connection, data)
43
+ @p = OpenSSL::BN.new(P_s, P_r)
44
+ @g = G
45
+
46
+ @digester = OpenSSL::Digest::SHA1
47
+ @algorithms = algorithms
48
+ @connection = connection
49
+
50
+ @data = data.dup
51
+ @dh = generate_key
52
+ @logger = @data.delete(:logger)
53
+ end
54
+
55
+ # Perform the key-exchange for the given session, with the given
56
+ # data. This method will return a hash consisting of the
57
+ # following keys:
58
+ #
59
+ # * :session_id
60
+ # * :server_key
61
+ # * :shared_secret
62
+ # * :hashing_algorithm
63
+ #
64
+ # The caller is expected to be able to understand how to use these
65
+ # deliverables.
66
+ def exchange_keys
67
+ result = send_kexinit
68
+ verify_server_key(result[:server_key])
69
+ session_id = verify_signature(result)
70
+ confirm_newkeys
71
+
72
+ return { :session_id => session_id,
73
+ :server_key => result[:server_key],
74
+ :shared_secret => result[:shared_secret],
75
+ :hashing_algorithm => digester }
76
+ end
77
+
78
+ private
79
+
80
+ # Returns the DH key parameters for the current connection.
81
+ def get_parameters
82
+ [p, g]
83
+ end
84
+
85
+ # Returns the INIT/REPLY constants used by this algorithm.
86
+ def get_message_types
87
+ [KEXDH_INIT, KEXDH_REPLY]
88
+ end
89
+
90
+ # Build the signature buffer to use when verifying a signature from
91
+ # the server.
92
+ def build_signature_buffer(result)
93
+ response = Net::SSH::Buffer.new
94
+ response.write_string data[:client_version_string],
95
+ data[:server_version_string],
96
+ data[:client_algorithm_packet],
97
+ data[:server_algorithm_packet],
98
+ result[:key_blob]
99
+ response.write_bignum dh.pub_key,
100
+ result[:server_dh_pubkey],
101
+ result[:shared_secret]
102
+ response
103
+ end
104
+
105
+ # Generate a DH key with a private key consisting of the given
106
+ # number of bytes.
107
+ def generate_key #:nodoc:
108
+ dh = OpenSSL::PKey::DH.new
109
+
110
+ dh.p, dh.g = get_parameters
111
+ dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8)
112
+
113
+ dh.generate_key! until dh.valid?
114
+
115
+ dh
116
+ end
117
+
118
+ # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the
119
+ # resulting buffer.
120
+ #
121
+ # Parse the buffer from a KEXDH_REPLY message, returning a hash of
122
+ # the extracted values.
123
+ def send_kexinit #:nodoc:
124
+ init, reply = get_message_types
125
+
126
+ # send the KEXDH_INIT message
127
+ buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key)
128
+ connection.send_message(buffer)
129
+
130
+ # expect the KEXDH_REPLY message
131
+ buffer = connection.next_message
132
+ raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply
133
+
134
+ result = Hash.new
135
+
136
+ result[:key_blob] = buffer.read_string
137
+ result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key
138
+ result[:server_dh_pubkey] = buffer.read_bignum
139
+ result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2)
140
+
141
+ sig_buffer = Net::SSH::Buffer.new(buffer.read_string)
142
+ sig_type = sig_buffer.read_string
143
+ if sig_type != algorithms.host_key
144
+ raise Net::SSH::Exception,
145
+ "host key algorithm mismatch for signature " +
146
+ "'#{sig_type}' != '#{algorithms.host_key}'"
147
+ end
148
+ result[:server_sig] = sig_buffer.read_string
149
+
150
+ return result
151
+ end
152
+
153
+ # Verify that the given key is of the expected type, and that it
154
+ # really is the key for the session's host. Raise Net::SSH::Exception
155
+ # if it is not.
156
+ def verify_server_key(key) #:nodoc:
157
+ if key.ssh_type != algorithms.host_key
158
+ raise Net::SSH::Exception,
159
+ "host key algorithm mismatch " +
160
+ "'#{key.ssh_type}' != '#{algorithms.host_key}'"
161
+ end
162
+
163
+ blob, fingerprint = generate_key_fingerprint(key)
164
+
165
+ unless connection.host_key_verifier.verify(:key => key, :key_blob => blob, :fingerprint => fingerprint, :session => connection)
166
+ raise Net::SSH::Exception, "host key verification failed"
167
+ end
168
+ end
169
+
170
+ def generate_key_fingerprint(key)
171
+ blob = Net::SSH::Buffer.from(:key, key).to_s
172
+ fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":")
173
+
174
+ [blob, fingerprint]
175
+ rescue ::Exception => e
176
+ [nil, "(could not generate fingerprint: #{e.message})"]
177
+ end
178
+
179
+ # Verify the signature that was received. Raise Net::SSH::Exception
180
+ # if the signature could not be verified. Otherwise, return the new
181
+ # session-id.
182
+ def verify_signature(result) #:nodoc:
183
+ response = build_signature_buffer(result)
184
+
185
+ hash = @digester.digest(response.to_s)
186
+
187
+ unless result[:server_key].ssh_do_verify(result[:server_sig], hash)
188
+ raise Net::SSH::Exception, "could not verify server signature"
189
+ end
190
+
191
+ return hash
192
+ end
193
+
194
+ # Send the NEWKEYS message, and expect the NEWKEYS message in
195
+ # reply.
196
+ def confirm_newkeys #:nodoc:
197
+ # send own NEWKEYS message first (the wodSSHServer won't send first)
198
+ response = Net::SSH::Buffer.new
199
+ response.write_byte(NEWKEYS)
200
+ connection.send_message(response)
201
+
202
+ # wait for the server's NEWKEYS message
203
+ buffer = connection.next_message
204
+ raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS
205
+ end
206
+ end
207
+
208
+ end; end; end; end
@@ -0,0 +1,80 @@
1
+ require 'net/ssh/errors'
2
+ require 'net/ssh/transport/constants'
3
+ require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
4
+
5
+ module Net::SSH::Transport::Kex
6
+
7
+ # A key-exchange service implementing the
8
+ # "diffie-hellman-group-exchange-sha1" key-exchange algorithm.
9
+ class DiffieHellmanGroupExchangeSHA1 < DiffieHellmanGroup1SHA1
10
+ MINIMUM_BITS = 1024
11
+ MAXIMUM_BITS = 8192
12
+
13
+ KEXDH_GEX_GROUP = 31
14
+ KEXDH_GEX_INIT = 32
15
+ KEXDH_GEX_REPLY = 33
16
+ KEXDH_GEX_REQUEST = 34
17
+
18
+ private
19
+
20
+ # Compute the number of bits needed for the given number of bytes.
21
+ def compute_need_bits
22
+
23
+ # for Compatibility: OpenSSH requires (need_bits * 2 + 1) length of parameter
24
+ need_bits = data[:need_bytes] * 8 * 2 + 1
25
+
26
+ if need_bits < MINIMUM_BITS
27
+ need_bits = MINIMUM_BITS
28
+ elsif need_bits > MAXIMUM_BITS
29
+ need_bits = MAXIMUM_BITS
30
+ end
31
+
32
+ data[:need_bits ] = need_bits
33
+ data[:need_bytes] = need_bits / 8
34
+ end
35
+
36
+ # Returns the DH key parameters for the given session.
37
+ def get_parameters
38
+ compute_need_bits
39
+
40
+ # request the DH key parameters for the given number of bits.
41
+ buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, MINIMUM_BITS,
42
+ :long, data[:need_bits], :long, MAXIMUM_BITS)
43
+ connection.send_message(buffer)
44
+
45
+ buffer = connection.next_message
46
+ unless buffer.type == KEXDH_GEX_GROUP
47
+ raise Net::SSH::Exception, "expected KEXDH_GEX_GROUP, got #{buffer.type}"
48
+ end
49
+
50
+ p = buffer.read_bignum
51
+ g = buffer.read_bignum
52
+
53
+ [p, g]
54
+ end
55
+
56
+ # Returns the INIT/REPLY constants used by this algorithm.
57
+ def get_message_types
58
+ [KEXDH_GEX_INIT, KEXDH_GEX_REPLY]
59
+ end
60
+
61
+ # Build the signature buffer to use when verifying a signature from
62
+ # the server.
63
+ def build_signature_buffer(result)
64
+ response = Net::SSH::Buffer.new
65
+ response.write_string data[:client_version_string],
66
+ data[:server_version_string],
67
+ data[:client_algorithm_packet],
68
+ data[:server_algorithm_packet],
69
+ result[:key_blob]
70
+ response.write_long MINIMUM_BITS,
71
+ data[:need_bits],
72
+ MAXIMUM_BITS
73
+ response.write_bignum dh.p, dh.g, dh.pub_key,
74
+ result[:server_dh_pubkey],
75
+ result[:shared_secret]
76
+ response
77
+ end
78
+ end
79
+
80
+ end
@@ -0,0 +1,15 @@
1
+ require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
2
+
3
+ module Net::SSH::Transport::Kex
4
+ if defined?(OpenSSL::Digest::SHA256)
5
+ # A key-exchange service implementing the
6
+ # "diffie-hellman-group-exchange-sha256" key-exchange algorithm.
7
+ class DiffieHellmanGroupExchangeSHA256 < DiffieHellmanGroupExchangeSHA1
8
+ def initialize(*args)
9
+ super(*args)
10
+
11
+ @digester = OpenSSL::Digest::SHA256
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ module Net; module SSH; module Transport
2
+ module KeyExpander
3
+
4
+ # Generate a key value in accordance with the SSH2 specification.
5
+ # (RFC4253 7.2. "Output from Key Exchange")
6
+ def self.expand_key(bytes, start, options={})
7
+ if bytes == 0
8
+ return ""
9
+ end
10
+
11
+ k = start[0, bytes]
12
+
13
+ digester = options[:digester] or raise 'No digester supplied'
14
+ shared = options[:shared] or raise 'No shared secret supplied'
15
+ hash = options[:hash] or raise 'No hash supplied'
16
+
17
+ while k.length < bytes
18
+ step = digester.digest(shared + hash + k)
19
+ bytes_needed = bytes - k.length
20
+ k << step[0, bytes_needed]
21
+ end
22
+
23
+ return k
24
+ end
25
+ end
26
+ end; end; end
@@ -0,0 +1,127 @@
1
+ require 'openssl'
2
+
3
+ module OpenSSL
4
+
5
+ # This class is originally defined in the OpenSSL module. As needed, methods
6
+ # have been added to it by the Net::SSH module for convenience in dealing with
7
+ # SSH functionality.
8
+ class BN
9
+
10
+ # Converts a BN object to a string. The format used is that which is
11
+ # required by the SSH2 protocol.
12
+ def to_ssh
13
+ if zero?
14
+ return [0].pack("N")
15
+ else
16
+ buf = to_s(2)
17
+ if buf.getbyte(0)[7] == 1
18
+ return [buf.length+1, 0, buf].pack("NCA*")
19
+ else
20
+ return [buf.length, buf].pack("NA*")
21
+ end
22
+ end
23
+ end
24
+
25
+ end
26
+
27
+ module PKey
28
+
29
+ class PKey
30
+ def fingerprint
31
+ @fingerprint ||= OpenSSL::Digest::MD5.hexdigest(to_blob).scan(/../).join(":")
32
+ end
33
+ end
34
+
35
+ # This class is originally defined in the OpenSSL module. As needed, methods
36
+ # have been added to it by the Net::SSH module for convenience in dealing
37
+ # with SSH functionality.
38
+ class DH
39
+
40
+ # Determines whether the pub_key for this key is valid. (This algorithm
41
+ # lifted more-or-less directly from OpenSSH, dh.c, dh_pub_is_valid.)
42
+ def valid?
43
+ return false if pub_key.nil? || pub_key < 0
44
+ bits_set = 0
45
+ pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set?(i) }
46
+ return ( bits_set > 1 && pub_key < p )
47
+ end
48
+
49
+ end
50
+
51
+ # This class is originally defined in the OpenSSL module. As needed, methods
52
+ # have been added to it by the Net::SSH module for convenience in dealing
53
+ # with SSH functionality.
54
+ class RSA
55
+
56
+ # Returns "ssh-rsa", which is the description of this key type used by the
57
+ # SSH2 protocol.
58
+ def ssh_type
59
+ "ssh-rsa"
60
+ end
61
+
62
+ # Converts the key to a blob, according to the SSH2 protocol.
63
+ def to_blob
64
+ @blob ||= Net::SSH::Buffer.from(:string, ssh_type, :bignum, e, :bignum, n).to_s
65
+ end
66
+
67
+ # Verifies the given signature matches the given data.
68
+ def ssh_do_verify(sig, data)
69
+ verify(OpenSSL::Digest::SHA1.new, sig, data)
70
+ end
71
+
72
+ # Returns the signature for the given data.
73
+ def ssh_do_sign(data)
74
+ sign(OpenSSL::Digest::SHA1.new, data)
75
+ end
76
+ end
77
+
78
+ # This class is originally defined in the OpenSSL module. As needed, methods
79
+ # have been added to it by the Net::SSH module for convenience in dealing
80
+ # with SSH functionality.
81
+ class DSA
82
+
83
+ # Returns "ssh-dss", which is the description of this key type used by the
84
+ # SSH2 protocol.
85
+ def ssh_type
86
+ "ssh-dss"
87
+ end
88
+
89
+ # Converts the key to a blob, according to the SSH2 protocol.
90
+ def to_blob
91
+ @blob ||= Net::SSH::Buffer.from(:string, ssh_type,
92
+ :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s
93
+ end
94
+
95
+ # Verifies the given signature matches the given data.
96
+ def ssh_do_verify(sig, data)
97
+ sig_r = sig[0,20].unpack("H*")[0].to_i(16)
98
+ sig_s = sig[20,20].unpack("H*")[0].to_i(16)
99
+ a1sig = OpenSSL::ASN1::Sequence([
100
+ OpenSSL::ASN1::Integer(sig_r),
101
+ OpenSSL::ASN1::Integer(sig_s)
102
+ ])
103
+ return verify(OpenSSL::Digest::DSS1.new, a1sig.to_der, data)
104
+ end
105
+
106
+ # Signs the given data.
107
+ def ssh_do_sign(data)
108
+ sig = sign( OpenSSL::Digest::DSS1.new, data)
109
+ a1sig = OpenSSL::ASN1.decode( sig )
110
+
111
+ sig_r = a1sig.value[0].value.to_s(2)
112
+ sig_s = a1sig.value[1].value.to_s(2)
113
+
114
+ if sig_r.length > 20 || sig_s.length > 20
115
+ raise OpenSSL::PKey::DSAError, "bad sig size"
116
+ end
117
+
118
+ sig_r = "\0" * ( 20 - sig_r.length ) + sig_r if sig_r.length < 20
119
+ sig_s = "\0" * ( 20 - sig_s.length ) + sig_s if sig_s.length < 20
120
+
121
+ return sig_r + sig_s
122
+ end
123
+ end
124
+
125
+ end
126
+
127
+ end