summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorDelano Mandelbaum <delano.mandelbaum@gmail.com>2012-01-11 03:37:55 -0800
committerDelano Mandelbaum <delano.mandelbaum@gmail.com>2012-01-11 03:37:55 -0800
commit17cea0164e3c18f4fd6fa0c25f967ded8064939e (patch)
tree6a724bb4ead5e84862f3c7f622d14717217c751b /lib
parente0c9efa487121023b226eee5264c185965d10d90 (diff)
parentb390295736ce509b86651d003a6d06e6b2247d32 (diff)
downloadnet-ssh-17cea0164e3c18f4fd6fa0c25f967ded8064939e.tar.gz
Merge pull request #30 from nappa/sha2mac
hmac-sha2 and diffie-hellman-group-exchange-sha256 support
Diffstat (limited to 'lib')
-rw-r--r--lib/net/ssh/transport/algorithms.rb18
-rw-r--r--lib/net/ssh/transport/cipher_factory.rb24
-rw-r--r--lib/net/ssh/transport/hmac.rb17
-rw-r--r--lib/net/ssh/transport/hmac/sha2_256.rb15
-rw-r--r--lib/net/ssh/transport/hmac/sha2_256_96.rb13
-rw-r--r--lib/net/ssh/transport/hmac/sha2_512.rb14
-rw-r--r--lib/net/ssh/transport/hmac/sha2_512_96.rb13
-rw-r--r--lib/net/ssh/transport/kex.rb8
-rw-r--r--lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb7
-rw-r--r--lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb15
-rw-r--r--lib/net/ssh/transport/key_expander.rb26
11 files changed, 134 insertions, 36 deletions
diff --git a/lib/net/ssh/transport/algorithms.rb b/lib/net/ssh/transport/algorithms.rb
index 9c7f8d0..1c0c8ce 100644
--- a/lib/net/ssh/transport/algorithms.rb
+++ b/lib/net/ssh/transport/algorithms.rb
@@ -24,11 +24,14 @@ module Net; module SSH; module Transport
ALGORITHMS = {
:host_key => %w(ssh-rsa ssh-dss),
:kex => %w(diffie-hellman-group-exchange-sha1
- diffie-hellman-group1-sha1),
+ diffie-hellman-group1-sha1
+ diffie-hellman-group-exchange-sha256),
:encryption => %w(aes128-cbc 3des-cbc blowfish-cbc cast128-cbc
aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se
idea-cbc none arcfour128 arcfour256),
- :hmac => %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96 none),
+ :hmac => %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96
+ hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96
+ hmac-sha2-512-96 none),
:compression => %w(none zlib@openssh.com zlib),
:language => %w()
}
@@ -345,14 +348,13 @@ module Net; module SSH; module Transport
mac_key_client = key["E"]
mac_key_server = key["F"]
- parameters = { :iv => iv_client, :key => key_client, :shared => secret,
- :hash => hash, :digester => digester }
+ parameters = { :shared => secret, :hash => hash, :digester => digester }
- cipher_client = CipherFactory.get(encryption_client, parameters.merge(:encrypt => true))
+ cipher_client = CipherFactory.get(encryption_client, parameters.merge(:iv => iv_client, :key => key_client, :encrypt => true))
cipher_server = CipherFactory.get(encryption_server, parameters.merge(:iv => iv_server, :key => key_server, :decrypt => true))
- mac_client = HMAC.get(hmac_client, mac_key_client)
- mac_server = HMAC.get(hmac_server, mac_key_server)
+ mac_client = HMAC.get(hmac_client, mac_key_client, parameters)
+ mac_server = HMAC.get(hmac_server, mac_key_server, parameters)
session.configure_client :cipher => cipher_client, :hmac => mac_client,
:compression => normalize_compression_name(compression_client),
@@ -381,4 +383,4 @@ module Net; module SSH; module Transport
end
end
end
-end; end; end \ No newline at end of file
+end; end; end
diff --git a/lib/net/ssh/transport/cipher_factory.rb b/lib/net/ssh/transport/cipher_factory.rb
index ae57f2c..4a07aa2 100644
--- a/lib/net/ssh/transport/cipher_factory.rb
+++ b/lib/net/ssh/transport/cipher_factory.rb
@@ -1,4 +1,5 @@
require 'openssl'
+require 'net/ssh/transport/key_expander'
require 'net/ssh/transport/identity_cipher'
module Net; module SSH; module Transport
@@ -50,10 +51,10 @@ module Net; module SSH; module Transport
cipher.send(options[:encrypt] ? :encrypt : :decrypt)
cipher.padding = 0
- cipher.iv = make_key(cipher.iv_len, options[:iv], options) if ossl_name != "rc4"
+ cipher.iv = Net::SSH::Transport::KeyExpander.expand_key(cipher.iv_len, options[:iv], options) if ossl_name != "rc4"
key_len = KEY_LEN_OVERRIDE[name] || cipher.key_len
cipher.key_len = key_len
- cipher.key = make_key(key_len, options[:key], options)
+ cipher.key = Net::SSH::Transport::KeyExpander.expand_key(key_len, options[:key], options)
cipher.update(" " * 1536) if ossl_name == "rc4"
return cipher
@@ -73,25 +74,6 @@ module Net; module SSH; module Transport
return [key_len, ossl_name=="rc4" ? 8 : cipher.block_size]
end
-
- private
-
- # Generate a key value in accordance with the SSH2 specification.
- def self.make_key(bytes, start, options={})
- k = start[0, bytes]
-
- digester = options[:digester] or raise 'No digester supplied'
- shared = options[:shared] or raise 'No shared secret supplied'
- hash = options[:hash] or raise 'No hash supplied'
-
- while k.length < bytes
- step = digester.digest(shared + hash + k)
- bytes_needed = bytes - k.length
- k << step[0, bytes_needed]
- end
-
- return k
- end
end
end; end; end
diff --git a/lib/net/ssh/transport/hmac.rb b/lib/net/ssh/transport/hmac.rb
index 262db73..8452046 100644
--- a/lib/net/ssh/transport/hmac.rb
+++ b/lib/net/ssh/transport/hmac.rb
@@ -1,7 +1,12 @@
+require 'net/ssh/transport/key_expander'
require 'net/ssh/transport/hmac/md5'
require 'net/ssh/transport/hmac/md5_96'
require 'net/ssh/transport/hmac/sha1'
require 'net/ssh/transport/hmac/sha1_96'
+require 'net/ssh/transport/hmac/sha2_256'
+require 'net/ssh/transport/hmac/sha2_256_96'
+require 'net/ssh/transport/hmac/sha2_512'
+require 'net/ssh/transport/hmac/sha2_512_96'
require 'net/ssh/transport/hmac/none'
# Implements a simple factory interface for fetching hmac implementations, or
@@ -16,11 +21,17 @@ module Net::SSH::Transport::HMAC
'none' => None
}
+ # add mapping to sha2 hmac algorithms if they're available
+ MAP['hmac-sha2-256'] = SHA2_256 if defined?(::Net::SSH::Transport::HMAC::SHA2_256)
+ MAP['hmac-sha2-256-96'] = SHA2_256_96 if defined?(::Net::SSH::Transport::HMAC::SHA2_256_96)
+ MAP['hmac-sha2-512'] = SHA2_512 if defined?(::Net::SSH::Transport::HMAC::SHA2_512)
+ MAP['hmac-sha2-512-96'] = SHA2_512_96 if defined?(::Net::SSH::Transport::HMAC::SHA2_512_96)
+
# Retrieves a new hmac instance of the given SSH type (+name+). If +key+ is
# given, the new instance will be initialized with that key.
- def self.get(name, key="")
+ def self.get(name, key="", parameters = {})
impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}"
- impl.new(key)
+ impl.new(Net::SSH::Transport::KeyExpander.expand_key(impl.key_length, key, parameters))
end
# Retrieves the key length for the hmac of the given SSH type (+name+).
@@ -28,4 +39,4 @@ module Net::SSH::Transport::HMAC
impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}"
impl.key_length
end
-end \ No newline at end of file
+end
diff --git a/lib/net/ssh/transport/hmac/sha2_256.rb b/lib/net/ssh/transport/hmac/sha2_256.rb
new file mode 100644
index 0000000..8191a90
--- /dev/null
+++ b/lib/net/ssh/transport/hmac/sha2_256.rb
@@ -0,0 +1,15 @@
+require 'net/ssh/transport/hmac/abstract'
+
+if defined?(OpenSSL::Digest::SHA256) # need openssl support
+ module Net::SSH::Transport::HMAC
+
+ # The SHA-256 HMAC algorithm. This has a mac and key length of 32, and
+ # uses the SHA-256 digest algorithm.
+ class SHA2_256 < Abstract
+ mac_length 32
+ key_length 32
+ digest_class OpenSSL::Digest::SHA256
+ end
+
+ end
+end
diff --git a/lib/net/ssh/transport/hmac/sha2_256_96.rb b/lib/net/ssh/transport/hmac/sha2_256_96.rb
new file mode 100644
index 0000000..15e36ff
--- /dev/null
+++ b/lib/net/ssh/transport/hmac/sha2_256_96.rb
@@ -0,0 +1,13 @@
+require 'net/ssh/transport/hmac/abstract'
+
+module Net::SSH::Transport::HMAC
+
+ if defined?(SHA2_256) # need openssl support
+ # The SHA256-96 HMAC algorithm. This returns only the first 12 bytes of
+ # the digest.
+ class SHA2_256_96 < SHA2_256
+ mac_length 12
+ end
+ end
+
+end
diff --git a/lib/net/ssh/transport/hmac/sha2_512.rb b/lib/net/ssh/transport/hmac/sha2_512.rb
new file mode 100644
index 0000000..e68df19
--- /dev/null
+++ b/lib/net/ssh/transport/hmac/sha2_512.rb
@@ -0,0 +1,14 @@
+require 'net/ssh/transport/hmac/abstract'
+
+module Net::SSH::Transport::HMAC
+
+ if defined?(OpenSSL::Digest::SHA512) # need openssl support
+ # The SHA-512 HMAC algorithm. This has a mac and key length of 64, and
+ # uses the SHA-512 digest algorithm.
+ class SHA2_512 < Abstract
+ mac_length 64
+ key_length 64
+ digest_class OpenSSL::Digest::SHA512
+ end
+ end
+end
diff --git a/lib/net/ssh/transport/hmac/sha2_512_96.rb b/lib/net/ssh/transport/hmac/sha2_512_96.rb
new file mode 100644
index 0000000..5cc7aed
--- /dev/null
+++ b/lib/net/ssh/transport/hmac/sha2_512_96.rb
@@ -0,0 +1,13 @@
+require 'net/ssh/transport/hmac/abstract'
+
+module Net::SSH::Transport::HMAC
+
+ if defined?(SHA2_512) # need openssl support
+ # The SHA2-512-96 HMAC algorithm. This returns only the first 12 bytes of
+ # the digest.
+ class SHA2_512_96 < SHA2_512
+ mac_length 12
+ end
+ end
+
+end
diff --git a/lib/net/ssh/transport/kex.rb b/lib/net/ssh/transport/kex.rb
index 29123c3..79a46a1 100644
--- a/lib/net/ssh/transport/kex.rb
+++ b/lib/net/ssh/transport/kex.rb
@@ -1,5 +1,6 @@
require 'net/ssh/transport/kex/diffie_hellman_group1_sha1'
require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
+require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha256'
module Net::SSH::Transport
module Kex
@@ -7,7 +8,10 @@ module Net::SSH::Transport
# to their corresponding implementors.
MAP = {
'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1,
- 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1
+ 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1,
}
+ if defined?(DiffieHellmanGroupExchangeSHA256)
+ MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256
+ end
end
-end \ No newline at end of file
+end
diff --git a/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb b/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb
index da47ec2..8fb69e8 100644
--- a/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb
+++ b/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb
@@ -19,7 +19,10 @@ module Net::SSH::Transport::Kex
# Compute the number of bits needed for the given number of bytes.
def compute_need_bits
- need_bits = data[:need_bytes] * 8
+
+ # for Compatibility: OpenSSH requires (need_bits * 2 + 1) length of parameter
+ need_bits = data[:need_bytes] * 8 * 2 + 1
+
if need_bits < MINIMUM_BITS
need_bits = MINIMUM_BITS
elsif need_bits > MAXIMUM_BITS
@@ -74,4 +77,4 @@ module Net::SSH::Transport::Kex
end
end
-end \ No newline at end of file
+end
diff --git a/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb b/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb
new file mode 100644
index 0000000..656254c
--- /dev/null
+++ b/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb
@@ -0,0 +1,15 @@
+require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1'
+
+module Net::SSH::Transport::Kex
+ if defined?(OpenSSL::Digest::SHA256)
+ # A key-exchange service implementing the
+ # "diffie-hellman-group-exchange-sha256" key-exchange algorithm.
+ class DiffieHellmanGroupExchangeSHA256 < DiffieHellmanGroupExchangeSHA1
+ def initialize(*args)
+ super(*args)
+
+ @digester = OpenSSL::Digest::SHA256
+ end
+ end
+ end
+end
diff --git a/lib/net/ssh/transport/key_expander.rb b/lib/net/ssh/transport/key_expander.rb
new file mode 100644
index 0000000..86e608d
--- /dev/null
+++ b/lib/net/ssh/transport/key_expander.rb
@@ -0,0 +1,26 @@
+module Net; module SSH; module Transport
+ module KeyExpander
+
+ # Generate a key value in accordance with the SSH2 specification.
+ # (RFC4253 7.2. "Output from Key Exchange")
+ def self.expand_key(bytes, start, options={})
+ if bytes == 0
+ return ""
+ end
+
+ k = start[0, bytes]
+
+ digester = options[:digester] or raise 'No digester supplied'
+ shared = options[:shared] or raise 'No shared secret supplied'
+ hash = options[:hash] or raise 'No hash supplied'
+
+ while k.length < bytes
+ step = digester.digest(shared + hash + k)
+ bytes_needed = bytes - k.length
+ k << step[0, bytes_needed]
+ end
+
+ return k
+ end
+end
+end; end; end