net-ssh 2.7.0 → 7.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 (199) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/FUNDING.yml +1 -0
  5. data/.github/config/rubocop_linter_action.yml +4 -0
  6. data/.github/workflows/ci-with-docker.yml +44 -0
  7. data/.github/workflows/ci.yml +94 -0
  8. data/.github/workflows/rubocop.yml +16 -0
  9. data/.gitignore +15 -0
  10. data/.rubocop.yml +22 -0
  11. data/.rubocop_todo.yml +1081 -0
  12. data/CHANGES.txt +387 -0
  13. data/DEVELOPMENT.md +23 -0
  14. data/Dockerfile +29 -0
  15. data/Dockerfile.openssl3 +17 -0
  16. data/Gemfile +13 -0
  17. data/Gemfile.noed25519 +12 -0
  18. data/Gemfile.norbnacl +12 -0
  19. data/ISSUE_TEMPLATE.md +30 -0
  20. data/Manifest +4 -5
  21. data/README.md +303 -0
  22. data/Rakefile +174 -40
  23. data/SECURITY.md +4 -0
  24. data/THANKS.txt +25 -0
  25. data/appveyor.yml +58 -0
  26. data/docker-compose.yml +25 -0
  27. data/lib/net/ssh/authentication/agent.rb +279 -18
  28. data/lib/net/ssh/authentication/certificate.rb +183 -0
  29. data/lib/net/ssh/authentication/constants.rb +17 -15
  30. data/lib/net/ssh/authentication/ed25519.rb +184 -0
  31. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  32. data/lib/net/ssh/authentication/key_manager.rb +125 -54
  33. data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
  34. data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
  35. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +19 -12
  36. data/lib/net/ssh/authentication/methods/none.rb +16 -19
  37. data/lib/net/ssh/authentication/methods/password.rb +56 -19
  38. data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
  39. data/lib/net/ssh/authentication/pageant.rb +483 -246
  40. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  41. data/lib/net/ssh/authentication/session.rb +138 -120
  42. data/lib/net/ssh/buffer.rb +399 -300
  43. data/lib/net/ssh/buffered_io.rb +154 -150
  44. data/lib/net/ssh/config.rb +361 -166
  45. data/lib/net/ssh/connection/channel.rb +640 -596
  46. data/lib/net/ssh/connection/constants.rb +29 -29
  47. data/lib/net/ssh/connection/event_loop.rb +123 -0
  48. data/lib/net/ssh/connection/keepalive.rb +59 -0
  49. data/lib/net/ssh/connection/session.rb +628 -548
  50. data/lib/net/ssh/connection/term.rb +125 -123
  51. data/lib/net/ssh/errors.rb +101 -95
  52. data/lib/net/ssh/key_factory.rb +198 -100
  53. data/lib/net/ssh/known_hosts.rb +221 -98
  54. data/lib/net/ssh/loggable.rb +50 -49
  55. data/lib/net/ssh/packet.rb +83 -79
  56. data/lib/net/ssh/prompt.rb +50 -81
  57. data/lib/net/ssh/proxy/command.rb +108 -60
  58. data/lib/net/ssh/proxy/errors.rb +12 -10
  59. data/lib/net/ssh/proxy/http.rb +82 -78
  60. data/lib/net/ssh/proxy/https.rb +50 -0
  61. data/lib/net/ssh/proxy/jump.rb +54 -0
  62. data/lib/net/ssh/proxy/socks4.rb +5 -8
  63. data/lib/net/ssh/proxy/socks5.rb +18 -20
  64. data/lib/net/ssh/service/forward.rb +383 -255
  65. data/lib/net/ssh/test/channel.rb +145 -136
  66. data/lib/net/ssh/test/extensions.rb +131 -110
  67. data/lib/net/ssh/test/kex.rb +34 -32
  68. data/lib/net/ssh/test/local_packet.rb +46 -44
  69. data/lib/net/ssh/test/packet.rb +89 -70
  70. data/lib/net/ssh/test/remote_packet.rb +32 -30
  71. data/lib/net/ssh/test/script.rb +156 -142
  72. data/lib/net/ssh/test/socket.rb +49 -48
  73. data/lib/net/ssh/test.rb +82 -77
  74. data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
  75. data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
  76. data/lib/net/ssh/transport/algorithms.rb +472 -348
  77. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  78. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  79. data/lib/net/ssh/transport/cipher_factory.rb +124 -100
  80. data/lib/net/ssh/transport/constants.rb +32 -24
  81. data/lib/net/ssh/transport/ctr.rb +42 -22
  82. data/lib/net/ssh/transport/gcm_cipher.rb +207 -0
  83. data/lib/net/ssh/transport/hmac/abstract.rb +97 -63
  84. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  85. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  86. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  87. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  88. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  89. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  90. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  91. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  92. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  93. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  94. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  95. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  96. data/lib/net/ssh/transport/hmac.rb +14 -12
  97. data/lib/net/ssh/transport/identity_cipher.rb +54 -44
  98. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  99. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  100. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  101. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  102. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  103. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  104. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
  105. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
  106. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  107. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  108. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  109. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  110. data/lib/net/ssh/transport/kex.rb +15 -12
  111. data/lib/net/ssh/transport/key_expander.rb +24 -20
  112. data/lib/net/ssh/transport/openssl.rb +161 -124
  113. data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  114. data/lib/net/ssh/transport/packet_stream.rb +246 -183
  115. data/lib/net/ssh/transport/server_version.rb +57 -51
  116. data/lib/net/ssh/transport/session.rb +307 -235
  117. data/lib/net/ssh/transport/state.rb +178 -176
  118. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  119. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  120. data/lib/net/ssh/verifiers/always.rb +58 -0
  121. data/lib/net/ssh/verifiers/never.rb +19 -0
  122. data/lib/net/ssh/version.rb +57 -51
  123. data/lib/net/ssh.rb +140 -40
  124. data/net-ssh-public_cert.pem +21 -0
  125. data/net-ssh.gemspec +39 -184
  126. data/support/ssh_tunnel_bug.rb +5 -5
  127. data.tar.gz.sig +0 -0
  128. metadata +205 -99
  129. metadata.gz.sig +0 -0
  130. data/README.rdoc +0 -219
  131. data/Rudyfile +0 -96
  132. data/gem-public_cert.pem +0 -20
  133. data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
  134. data/lib/net/ssh/authentication/agent/socket.rb +0 -170
  135. data/lib/net/ssh/ruby_compat.rb +0 -51
  136. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  137. data/lib/net/ssh/verifiers/null.rb +0 -12
  138. data/lib/net/ssh/verifiers/secure.rb +0 -54
  139. data/lib/net/ssh/verifiers/strict.rb +0 -24
  140. data/setup.rb +0 -1585
  141. data/support/arcfour_check.rb +0 -20
  142. data/test/README.txt +0 -47
  143. data/test/authentication/methods/common.rb +0 -28
  144. data/test/authentication/methods/test_abstract.rb +0 -51
  145. data/test/authentication/methods/test_hostbased.rb +0 -114
  146. data/test/authentication/methods/test_keyboard_interactive.rb +0 -100
  147. data/test/authentication/methods/test_none.rb +0 -41
  148. data/test/authentication/methods/test_password.rb +0 -52
  149. data/test/authentication/methods/test_publickey.rb +0 -148
  150. data/test/authentication/test_agent.rb +0 -205
  151. data/test/authentication/test_key_manager.rb +0 -218
  152. data/test/authentication/test_session.rb +0 -108
  153. data/test/common.rb +0 -108
  154. data/test/configs/eqsign +0 -3
  155. data/test/configs/exact_match +0 -8
  156. data/test/configs/host_plus +0 -10
  157. data/test/configs/multihost +0 -4
  158. data/test/configs/nohost +0 -19
  159. data/test/configs/numeric_host +0 -4
  160. data/test/configs/send_env +0 -2
  161. data/test/configs/substitutes +0 -8
  162. data/test/configs/wild_cards +0 -14
  163. data/test/connection/test_channel.rb +0 -467
  164. data/test/connection/test_session.rb +0 -526
  165. data/test/known_hosts/github +0 -1
  166. data/test/manual/test_forward.rb +0 -223
  167. data/test/start/test_options.rb +0 -36
  168. data/test/start/test_transport.rb +0 -28
  169. data/test/test_all.rb +0 -11
  170. data/test/test_buffer.rb +0 -433
  171. data/test/test_buffered_io.rb +0 -63
  172. data/test/test_config.rb +0 -151
  173. data/test/test_key_factory.rb +0 -173
  174. data/test/test_known_hosts.rb +0 -13
  175. data/test/transport/hmac/test_md5.rb +0 -41
  176. data/test/transport/hmac/test_md5_96.rb +0 -27
  177. data/test/transport/hmac/test_none.rb +0 -34
  178. data/test/transport/hmac/test_ripemd160.rb +0 -36
  179. data/test/transport/hmac/test_sha1.rb +0 -36
  180. data/test/transport/hmac/test_sha1_96.rb +0 -27
  181. data/test/transport/hmac/test_sha2_256.rb +0 -37
  182. data/test/transport/hmac/test_sha2_256_96.rb +0 -27
  183. data/test/transport/hmac/test_sha2_512.rb +0 -37
  184. data/test/transport/hmac/test_sha2_512_96.rb +0 -27
  185. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
  186. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -146
  187. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -92
  188. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -34
  189. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
  190. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
  191. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
  192. data/test/transport/test_algorithms.rb +0 -330
  193. data/test/transport/test_cipher_factory.rb +0 -443
  194. data/test/transport/test_hmac.rb +0 -34
  195. data/test/transport/test_identity_cipher.rb +0 -40
  196. data/test/transport/test_packet_stream.rb +0 -1755
  197. data/test/transport/test_server_version.rb +0 -78
  198. data/test/transport/test_session.rb +0 -319
  199. data/test/transport/test_state.rb +0 -181
@@ -0,0 +1,207 @@
1
+ require 'net/ssh/loggable'
2
+
3
+ module Net
4
+ module SSH
5
+ module Transport
6
+ ## Extension module for aes(128|256)gcm ciphers
7
+ module GCMCipher
8
+ # rubocop:disable Metrics/AbcSize
9
+ def self.extended(orig)
10
+ # rubocop:disable Metrics/BlockLength
11
+ orig.class_eval do
12
+ include Net::SSH::Loggable
13
+
14
+ attr_reader :cipher
15
+ attr_reader :key
16
+ attr_accessor :nonce
17
+
18
+ #
19
+ # Semantically gcm cipher supplies the OpenSSL iv interface with a nonce
20
+ # as it is not randomly generated due to being supplied from a counter.
21
+ # The RFC's use IV and nonce interchangeably.
22
+ #
23
+ def initialize(encrypt:, key:)
24
+ @cipher = OpenSSL::Cipher.new(algo_name)
25
+ @key = key
26
+ key_len = @cipher.key_len
27
+ if key.size != key_len
28
+ error_message = "#{cipher_name}: keylength does not match"
29
+ error { error_message }
30
+ raise error_message
31
+ end
32
+ encrypt ? @cipher.encrypt : @cipher.decrypt
33
+ @cipher.key = key
34
+
35
+ @nonce = {
36
+ fixed: nil,
37
+ invocation_counter: 0
38
+ }
39
+ end
40
+
41
+ def update_cipher_mac(payload, _sequence_number)
42
+ #
43
+ # --- RFC 5647 7.3 ---
44
+ # When using AES-GCM with secure shell, the packet_length field is to
45
+ # be treated as additional authenticated data, not as plaintext.
46
+ #
47
+ length_data = [payload.bytesize].pack('N')
48
+
49
+ cipher.auth_data = length_data
50
+
51
+ encrypted_data = cipher.update(payload) << cipher.final
52
+
53
+ mac = cipher.auth_tag
54
+
55
+ incr_nonce
56
+ length_data + encrypted_data + mac
57
+ end
58
+
59
+ #
60
+ # --- RFC 5647 ---
61
+ # uint32 packet_length; // 0 <= packet_length < 2^32
62
+ #
63
+ def read_length(data, _sequence_number)
64
+ data.unpack1('N')
65
+ end
66
+
67
+ #
68
+ # --- RFC 5647 ---
69
+ # In AES-GCM secure shell, the inputs to the authenticated encryption
70
+ # are:
71
+ # PT (Plain Text)
72
+ # byte padding_length; // 4 <= padding_length < 256
73
+ # byte[n1] payload; // n1 = packet_length-padding_length-1
74
+ # byte[n2] random_padding; // n2 = padding_length
75
+ # AAD (Additional Authenticated Data)
76
+ # uint32 packet_length; // 0 <= packet_length < 2^32
77
+ # IV (Initialization Vector)
78
+ # As described in section 7.1.
79
+ # BK (Block Cipher Key)
80
+ # The appropriate Encryption Key formed during the Key Exchange.
81
+ #
82
+ def read_and_mac(data, mac, _sequence_number)
83
+ # The authentication tag will be placed in the MAC field at the end of the packet
84
+
85
+ # OpenSSL does not verify auth tag length
86
+ # GCM mode allows arbitrary sizes for the auth_tag up to 128 bytes and a single
87
+ # byte allows authentication to pass. If single byte auth tags are possible
88
+ # an attacker would require no more than 256 attempts to forge a valid tag.
89
+ #
90
+ raise 'incorrect auth_tag length' unless mac.to_s.length == mac_length
91
+
92
+ packet_length = data.unpack1('N')
93
+
94
+ cipher.auth_tag = mac.to_s
95
+ cipher.auth_data = [packet_length].pack('N')
96
+
97
+ result = cipher.update(data[4...]) << cipher.final
98
+ incr_nonce
99
+ result
100
+ end
101
+
102
+ def mac_length
103
+ 16
104
+ end
105
+
106
+ def block_size
107
+ 16
108
+ end
109
+
110
+ def self.block_size
111
+ 16
112
+ end
113
+
114
+ #
115
+ # --- RFC 5647 ---
116
+ # N_MIN minimum nonce (IV) length 12 octets
117
+ # N_MAX maximum nonce (IV) length 12 octets
118
+ #
119
+ def iv_len
120
+ 12
121
+ end
122
+
123
+ #
124
+ # --- RFC 5288 ---
125
+ # Each value of the nonce_explicit MUST be distinct for each distinct
126
+ # invocation of the GCM encrypt function for any fixed key. Failure to
127
+ # meet this uniqueness requirement can significantly degrade security.
128
+ # The nonce_explicit MAY be the 64-bit sequence number.
129
+ #
130
+ # --- RFC 5116 ---
131
+ # (2.1) Applications that can generate distinct nonces SHOULD use the nonce
132
+ # formation method defined in Section 3.2, and MAY use any
133
+ # other method that meets the uniqueness requirement.
134
+ #
135
+ # (3.2) The following method to construct nonces is RECOMMENDED.
136
+ #
137
+ # <- variable -> <- variable ->
138
+ # - - - - - - - - - - - - - -
139
+ # | fixed | counter |
140
+ #
141
+ # Initial octets consist of a fixed field and final octets consist of a
142
+ # Counter field. Implementations SHOULD support 12-octet nonces in which
143
+ # the Counter field is four octets long.
144
+ # The Counter fields of successive nonces form a monotonically increasing
145
+ # sequence, when those fields are regarded as unsignd integers in network
146
+ # byte order.
147
+ # The Counter part SHOULD be equal to zero for the first nonce and increment
148
+ # by one for each successive nonce that is generated.
149
+ # The Fixed field MUST remain constant for all nonces that are generated for
150
+ # a given encryption device.
151
+ #
152
+ # --- RFC 5647 ---
153
+ # The invocation field is treated as a 64-bit integer and is increment after
154
+ # each invocation of AES-GCM to process a binary packet.
155
+ # AES-GCM produces a keystream in blocks of 16-octets that is used to
156
+ # encrypt the plaintext. This keystream is produced by encrypting the
157
+ # following 16-octet data structure:
158
+ #
159
+ # uint32 fixed; // 4 octets
160
+ # uint64 invocation_counter; // 8 octets
161
+ # unit32 block_counter; // 4 octets
162
+ #
163
+ # The block_counter is initially set to one (1) and increment as each block
164
+ # of key is produced.
165
+ #
166
+ # The reader is reminded that SSH requires that the data to be encrypted
167
+ # MUST be padded out to a multiple of the block size (16-octets for AES-GCM).
168
+ #
169
+ def incr_nonce
170
+ return if nonce[:fixed].nil?
171
+
172
+ nonce[:invocation_counter] = [nonce[:invocation_counter].to_s.unpack1('B*').to_i(2) + 1].pack('Q>*')
173
+
174
+ apply_nonce
175
+ end
176
+
177
+ def nonce=(iv_s)
178
+ return if nonce[:fixed]
179
+
180
+ nonce[:fixed] = iv_s[0...4]
181
+ nonce[:invocation_counter] = iv_s[4...12]
182
+
183
+ apply_nonce
184
+ end
185
+
186
+ def apply_nonce
187
+ cipher.iv = "#{nonce[:fixed]}#{nonce[:invocation_counter]}"
188
+ end
189
+
190
+ #
191
+ # --- RFC 5647 ---
192
+ # If AES-GCM is selected as the encryption algorithm for a given
193
+ # tunnel, AES-GCM MUST also be selected as the Message Authentication
194
+ # Code (MAC) algorithm. Conversely, if AES-GCM is selected as the MAC
195
+ # algorithm, it MUST also be selected as the encryption algorithm.
196
+ #
197
+ def implicit_mac?
198
+ true
199
+ end
200
+ end
201
+ end
202
+ # rubocop:enable Metrics/BlockLength
203
+ end
204
+ # rubocop:enable Metrics/AbcSize
205
+ end
206
+ end
207
+ end
@@ -1,79 +1,113 @@
1
1
  require 'openssl'
2
2
  require 'openssl/digest'
3
3
 
4
- module Net; module SSH; module Transport; module HMAC
4
+ module Net
5
+ module SSH
6
+ module Transport
7
+ module HMAC
8
+ # The base class of all OpenSSL-based HMAC algorithm wrappers.
9
+ class Abstract
10
+ class << self
11
+ def aead(*v)
12
+ @aead = false if !defined?(@aead)
13
+ if v.empty?
14
+ @aead = superclass.aead if @aead.nil? && superclass.respond_to?(:aead)
15
+ return @aead
16
+ elsif v.length == 1
17
+ @aead = v.first
18
+ else
19
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
20
+ end
21
+ end
5
22
 
6
- # The base class of all OpenSSL-based HMAC algorithm wrappers.
7
- class Abstract
23
+ def etm(*v)
24
+ @etm = false if !defined?(@etm)
25
+ if v.empty?
26
+ @etm = superclass.etm if @etm.nil? && superclass.respond_to?(:etm)
27
+ return @etm
28
+ elsif v.length == 1
29
+ @etm = v.first
30
+ else
31
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
32
+ end
33
+ end
8
34
 
9
- class <<self
10
- def key_length(*v)
11
- @key_length = nil if !defined?(@key_length)
12
- if v.empty?
13
- @key_length = superclass.key_length if @key_length.nil? && superclass.respond_to?(:key_length)
14
- return @key_length
15
- elsif v.length == 1
16
- @key_length = v.first
17
- else
18
- raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
19
- end
20
- end
35
+ def key_length(*v)
36
+ @key_length = nil if !defined?(@key_length)
37
+ if v.empty?
38
+ @key_length = superclass.key_length if @key_length.nil? && superclass.respond_to?(:key_length)
39
+ return @key_length
40
+ elsif v.length == 1
41
+ @key_length = v.first
42
+ else
43
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
44
+ end
45
+ end
21
46
 
22
- def mac_length(*v)
23
- @mac_length = nil if !defined?(@mac_length)
24
- if v.empty?
25
- @mac_length = superclass.mac_length if @mac_length.nil? && superclass.respond_to?(:mac_length)
26
- return @mac_length
27
- elsif v.length == 1
28
- @mac_length = v.first
29
- else
30
- raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
31
- end
32
- end
47
+ def mac_length(*v)
48
+ @mac_length = nil if !defined?(@mac_length)
49
+ if v.empty?
50
+ @mac_length = superclass.mac_length if @mac_length.nil? && superclass.respond_to?(:mac_length)
51
+ return @mac_length
52
+ elsif v.length == 1
53
+ @mac_length = v.first
54
+ else
55
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
56
+ end
57
+ end
33
58
 
34
- def digest_class(*v)
35
- @digest_class = nil if !defined?(@digest_class)
36
- if v.empty?
37
- @digest_class = superclass.digest_class if @digest_class.nil? && superclass.respond_to?(:digest_class)
38
- return @digest_class
39
- elsif v.length == 1
40
- @digest_class = v.first
41
- else
42
- raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
43
- end
44
- end
45
- end
59
+ def digest_class(*v)
60
+ @digest_class = nil if !defined?(@digest_class)
61
+ if v.empty?
62
+ @digest_class = superclass.digest_class if @digest_class.nil? && superclass.respond_to?(:digest_class)
63
+ return @digest_class
64
+ elsif v.length == 1
65
+ @digest_class = v.first
66
+ else
67
+ raise ArgumentError, "wrong number of arguments (#{v.length} for 1)"
68
+ end
69
+ end
70
+ end
46
71
 
47
- def key_length
48
- self.class.key_length
49
- end
72
+ def aead
73
+ self.class.aead
74
+ end
50
75
 
51
- def mac_length
52
- self.class.mac_length
53
- end
76
+ def etm
77
+ self.class.etm
78
+ end
54
79
 
55
- def digest_class
56
- self.class.digest_class
57
- end
80
+ def key_length
81
+ self.class.key_length
82
+ end
58
83
 
59
- # The key in use for this instance.
60
- attr_reader :key
84
+ def mac_length
85
+ self.class.mac_length
86
+ end
61
87
 
62
- def initialize(key=nil)
63
- self.key = key
64
- end
88
+ def digest_class
89
+ self.class.digest_class
90
+ end
65
91
 
66
- # Sets the key to the given value, truncating it so that it is the correct
67
- # length.
68
- def key=(value)
69
- @key = value ? value.to_s[0,key_length] : nil
70
- end
92
+ # The key in use for this instance.
93
+ attr_reader :key
71
94
 
72
- # Compute the HMAC digest for the given data string.
73
- def digest(data)
74
- OpenSSL::HMAC.digest(digest_class.new, key, data)[0,mac_length]
75
- end
95
+ def initialize(key = nil)
96
+ self.key = key
97
+ end
76
98
 
77
- end
99
+ # Sets the key to the given value, truncating it so that it is the correct
100
+ # length.
101
+ def key=(value)
102
+ @key = value ? value.to_s[0, key_length] : nil
103
+ end
78
104
 
79
- end; end; end; end
105
+ # Compute the HMAC digest for the given data string.
106
+ def digest(data)
107
+ OpenSSL::HMAC.digest(digest_class.new, key, data)[0, mac_length]
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -1,12 +1,10 @@
1
1
  require 'net/ssh/transport/hmac/abstract'
2
2
 
3
3
  module Net::SSH::Transport::HMAC
4
-
5
4
  # The MD5 HMAC algorithm.
6
5
  class MD5 < Abstract
7
6
  mac_length 16
8
7
  key_length 16
9
8
  digest_class OpenSSL::Digest::MD5
10
9
  end
11
-
12
10
  end
@@ -1,11 +1,9 @@
1
1
  require 'net/ssh/transport/hmac/md5'
2
2
 
3
3
  module Net::SSH::Transport::HMAC
4
-
5
4
  # The MD5-96 HMAC algorithm. This returns only the first 12 bytes of
6
5
  # the digest.
7
6
  class MD5_96 < MD5
8
7
  mac_length 12
9
8
  end
10
-
11
9
  end
@@ -1,7 +1,6 @@
1
1
  require 'net/ssh/transport/hmac/abstract'
2
2
 
3
3
  module Net::SSH::Transport::HMAC
4
-
5
4
  # The "none" algorithm. This has a key and mac length of 0.
6
5
  class None < Abstract
7
6
  key_length 0
@@ -11,5 +10,4 @@ module Net::SSH::Transport::HMAC
11
10
  ""
12
11
  end
13
12
  end
14
-
15
13
  end
@@ -1,7 +1,6 @@
1
1
  require 'net/ssh/transport/hmac/abstract'
2
2
 
3
3
  module Net::SSH::Transport::HMAC
4
-
5
4
  # The RIPEMD-160 HMAC algorithm. This has a mac and key length of 20, and
6
5
  # uses the RIPEMD-160 digest algorithm.
7
6
  class RIPEMD160 < Abstract
@@ -9,5 +8,4 @@ module Net::SSH::Transport::HMAC
9
8
  key_length 20
10
9
  digest_class OpenSSL::Digest::RIPEMD160
11
10
  end
12
-
13
11
  end
@@ -1,7 +1,6 @@
1
1
  require 'net/ssh/transport/hmac/abstract'
2
2
 
3
3
  module Net::SSH::Transport::HMAC
4
-
5
4
  # The SHA1 HMAC algorithm. This has a mac and key length of 20, and
6
5
  # uses the SHA1 digest algorithm.
7
6
  class SHA1 < Abstract
@@ -9,5 +8,4 @@ module Net::SSH::Transport::HMAC
9
8
  key_length 20
10
9
  digest_class OpenSSL::Digest::SHA1
11
10
  end
12
-
13
11
  end
@@ -1,11 +1,9 @@
1
1
  require 'net/ssh/transport/hmac/sha1'
2
2
 
3
3
  module Net::SSH::Transport::HMAC
4
-
5
4
  # The SHA1-96 HMAC algorithm. This returns only the first 12 bytes of
6
5
  # the digest.
7
6
  class SHA1_96 < SHA1
8
7
  mac_length 12
9
8
  end
10
-
11
9
  end
@@ -1,15 +1,11 @@
1
1
  require 'net/ssh/transport/hmac/abstract'
2
2
 
3
- if defined?(OpenSSL::Digest::SHA256) # need openssl support
4
- module Net::SSH::Transport::HMAC
5
-
6
- # The SHA-256 HMAC algorithm. This has a mac and key length of 32, and
7
- # uses the SHA-256 digest algorithm.
8
- class SHA2_256 < Abstract
9
- mac_length 32
10
- key_length 32
11
- digest_class OpenSSL::Digest::SHA256
12
- end
13
-
3
+ module Net::SSH::Transport::HMAC
4
+ # The SHA-256 HMAC algorithm. This has a mac and key length of 32, and
5
+ # uses the SHA-256 digest algorithm.
6
+ class SHA2_256 < Abstract
7
+ mac_length 32
8
+ key_length 32
9
+ digest_class OpenSSL::Digest::SHA256
14
10
  end
15
11
  end
@@ -1,13 +1,9 @@
1
1
  require 'net/ssh/transport/hmac/abstract'
2
2
 
3
3
  module Net::SSH::Transport::HMAC
4
-
5
- if defined?(SHA2_256) # need openssl support
6
- # The SHA256-96 HMAC algorithm. This returns only the first 12 bytes of
7
- # the digest.
8
- class SHA2_256_96 < SHA2_256
9
- mac_length 12
10
- end
4
+ # The SHA256-96 HMAC algorithm. This returns only the first 12 bytes of
5
+ # the digest.
6
+ class SHA2_256_96 < SHA2_256
7
+ mac_length 12
11
8
  end
12
-
13
9
  end
@@ -0,0 +1,12 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+ # The SHA-256 Encrypt-Then-Mac HMAC algorithm. This has a mac and
5
+ # key length of 32, and uses the SHA-256 digest algorithm.
6
+ class SHA2_256_Etm < Abstract
7
+ etm true
8
+ mac_length 32
9
+ key_length 32
10
+ digest_class OpenSSL::Digest::SHA256
11
+ end
12
+ end
@@ -1,14 +1,11 @@
1
1
  require 'net/ssh/transport/hmac/abstract'
2
2
 
3
3
  module Net::SSH::Transport::HMAC
4
-
5
- if defined?(OpenSSL::Digest::SHA512) # need openssl support
6
- # The SHA-512 HMAC algorithm. This has a mac and key length of 64, and
7
- # uses the SHA-512 digest algorithm.
8
- class SHA2_512 < Abstract
9
- mac_length 64
10
- key_length 64
11
- digest_class OpenSSL::Digest::SHA512
12
- end
4
+ # The SHA-512 HMAC algorithm. This has a mac and key length of 64, and
5
+ # uses the SHA-512 digest algorithm.
6
+ class SHA2_512 < Abstract
7
+ mac_length 64
8
+ key_length 64
9
+ digest_class OpenSSL::Digest::SHA512
13
10
  end
14
11
  end
@@ -1,13 +1,9 @@
1
1
  require 'net/ssh/transport/hmac/abstract'
2
2
 
3
3
  module Net::SSH::Transport::HMAC
4
-
5
- if defined?(SHA2_512) # need openssl support
6
- # The SHA2-512-96 HMAC algorithm. This returns only the first 12 bytes of
7
- # the digest.
8
- class SHA2_512_96 < SHA2_512
9
- mac_length 12
10
- end
4
+ # The SHA2-512-96 HMAC algorithm. This returns only the first 12 bytes of
5
+ # the digest.
6
+ class SHA2_512_96 < SHA2_512
7
+ mac_length 12
11
8
  end
12
-
13
9
  end
@@ -0,0 +1,12 @@
1
+ require 'net/ssh/transport/hmac/abstract'
2
+
3
+ module Net::SSH::Transport::HMAC
4
+ # The SHA-512 Encrypt-Then-Mac HMAC algorithm. This has a mac and
5
+ # key length of 64, and uses the SHA-512 digest algorithm.
6
+ class SHA2_512_Etm < Abstract
7
+ etm true
8
+ mac_length 64
9
+ key_length 64
10
+ digest_class OpenSSL::Digest::SHA512
11
+ end
12
+ end
@@ -7,6 +7,8 @@ require 'net/ssh/transport/hmac/sha2_256'
7
7
  require 'net/ssh/transport/hmac/sha2_256_96'
8
8
  require 'net/ssh/transport/hmac/sha2_512'
9
9
  require 'net/ssh/transport/hmac/sha2_512_96'
10
+ require 'net/ssh/transport/hmac/sha2_256_etm'
11
+ require 'net/ssh/transport/hmac/sha2_512_etm'
10
12
  require 'net/ssh/transport/hmac/ripemd160'
11
13
  require 'net/ssh/transport/hmac/none'
12
14
 
@@ -15,24 +17,24 @@ require 'net/ssh/transport/hmac/none'
15
17
  module Net::SSH::Transport::HMAC
16
18
  # The mapping of SSH hmac algorithms to their implementations
17
19
  MAP = {
18
- 'hmac-md5' => MD5,
19
- 'hmac-md5-96' => MD5_96,
20
- 'hmac-sha1' => SHA1,
21
- 'hmac-sha1-96' => SHA1_96,
20
+ 'hmac-md5' => MD5,
21
+ 'hmac-md5-96' => MD5_96,
22
+ 'hmac-sha1' => SHA1,
23
+ 'hmac-sha1-96' => SHA1_96,
24
+ 'hmac-sha2-256' => SHA2_256,
25
+ 'hmac-sha2-256-96' => SHA2_256_96,
26
+ 'hmac-sha2-512' => SHA2_512,
27
+ 'hmac-sha2-512-96' => SHA2_512_96,
28
+ 'hmac-sha2-256-etm@openssh.com' => SHA2_256_Etm,
29
+ 'hmac-sha2-512-etm@openssh.com' => SHA2_512_Etm,
22
30
  'hmac-ripemd160' => RIPEMD160,
23
31
  'hmac-ripemd160@openssh.com' => RIPEMD160,
24
- 'none' => None
32
+ 'none' => None
25
33
  }
26
34
 
27
- # add mapping to sha2 hmac algorithms if they're available
28
- MAP['hmac-sha2-256'] = SHA2_256 if defined?(::Net::SSH::Transport::HMAC::SHA2_256)
29
- MAP['hmac-sha2-256-96'] = SHA2_256_96 if defined?(::Net::SSH::Transport::HMAC::SHA2_256_96)
30
- MAP['hmac-sha2-512'] = SHA2_512 if defined?(::Net::SSH::Transport::HMAC::SHA2_512)
31
- MAP['hmac-sha2-512-96'] = SHA2_512_96 if defined?(::Net::SSH::Transport::HMAC::SHA2_512_96)
32
-
33
35
  # Retrieves a new hmac instance of the given SSH type (+name+). If +key+ is
34
36
  # given, the new instance will be initialized with that key.
35
- def self.get(name, key="", parameters = {})
37
+ def self.get(name, key = "", parameters = {})
36
38
  impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}"
37
39
  impl.new(Net::SSH::Transport::KeyExpander.expand_key(impl.key_length, key, parameters))
38
40
  end