Permalink
Browse files

- Add SSH::Key::Signer#add_private_key_file

- Add SSH::Key::Verifier#add_private_key_file
- Add SSH::Key::Verifier#add_public_key_file
- Add tests to cover public/private keys in files
- Fix a bug in verification
  • Loading branch information...
1 parent 920d5a8 commit e3582820ceda714f81bc56398e422bbf21d384db @jordansissel committed Nov 4, 2010
View
@@ -80,4 +80,8 @@ def signing_identities
end
return identities
end # def signing_identities
+
+ def add_private_key_file(path, passphrase=nil)
+ @keys << Net::SSH::KeyFactory.load_private_key(path, passphrase)
+ end # def add_private_key_file(path)
end; end; end # class SSH::Key::Signer
View
@@ -38,9 +38,8 @@ def initialize(account=nil)
@use_authorized_keys = true
@sshd_config_file = "/etc/ssh/sshd_config"
@authorized_keys_file = nil
- #@logger = Logger.new("/tmp/verifier.log")
@logger = Logger.new(STDERR)
- @logger.level = Logger::WARN
+ @logger.level = $DEBUG ? Logger::DEBUG : Logger::WARN
@keys = []
end # def initialize
@@ -66,7 +65,6 @@ def ensure_connected
def verify?(signature, original)
results = verify(signature, original)
results.each do |identity, verified|
- @logger.info "Trying key #{identity.to_s[0..30]}... #{verified}"
return true if verified
end
return false
@@ -84,20 +82,26 @@ def verify(signatures, original)
results = {}
if signatures.is_a? Hash
+ @logger.debug("verify 'signatures' is a Hash")
inputs = signatures.values
elsif signatures.is_a? Array
+ @logger.debug("verify 'signatures' is an Array")
inputs = signatures
elsif signatures.is_a? String
+ @logger.debug("verify 'signatures' is an String")
inputs = [signatures]
end
if inputs[0].is_a? SSH::Key::Signature
+ @logger.debug("verify 'signatures' is an array of Signatures")
inputs = inputs.collect { |i| i.signature }
end
inputs.each do |signature|
identities.each do |identity|
- results[identity] = identity.ssh_do_verify(signature, original)
+ key = [signature, identity]
+ results[key] = identity.ssh_do_verify(signature, original)
+ @logger.info "Trying key #{identity.to_s.split("\n")[1]}... #{results[key]}"
end
end
return results
@@ -207,6 +211,7 @@ def authorized_keys
end
identity = Net::SSH::KeyFactory.load_data_public_key(line)
+
# Add the '.comment' attribute to our key
identity.extend(Net::SSH::Authentication::Agent::Comment)
@@ -222,4 +227,12 @@ def authorized_keys
end
return keys
end
+
+ def add_private_key_file(path, passphrase=nil)
+ @keys << Net::SSH::KeyFactory.load_private_key(path, passphrase)
+ end # def add_private_key_file(path)
+
+ def add_public_key_file(path, passphrase=nil)
+ @keys << Net::SSH::KeyFactory.load_public_key(path)
+ end # def add_private_key_file(path)
end; end; end # class SSH::Key::Verifier
View
@@ -3,8 +3,8 @@
require "base64"
require "json"
-$:.unshift "../lib"
-$:.unshift "lib"
+
+$:.unshift "#{File.dirname(__FILE__)}/../lib"
require "ssh/key/signer"
def main(argv)
View
@@ -3,7 +3,8 @@
require "base64"
require "json"
-$:.unshift "../lib"
+
+$:.unshift "#{File.dirname(__FILE__)}/../lib"
require "ssh/key/verifier"
def main(argv)
@@ -13,6 +14,7 @@ def main(argv)
input = argv
end
verifier = SSH::Key::Verifier.new
+ verifier.use_agent = false
input.each do |line|
data = JSON.parse(line)
View
@@ -1 +1,2 @@
require 'test_agent'
+require 'test_with_files'
View
@@ -0,0 +1 @@
+The passphrase for the key here is 'testing'
@@ -1,30 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
-DEK-Info: DES-EDE3-CBC,89BA80483980E174
+DEK-Info: DES-EDE3-CBC,0CB5569EED9F08E0
-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
+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
-----END RSA PRIVATE KEY-----
@@ -1 +1 @@
-ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAzMth8xzMRlKZXB7DwwYf/JqChrV7d/s1IEoxvUH6bWIgv42DHI0pzeJeLcEdlNLPwu8wLGnx82Wlp0fwM1D+pOdFEErbMx2FHXA0dq0U69smRC1lc7OL64RG/u84vyXoFyFMZo5uyI2YlWf7cEZZVjy9ePBCDXutCuTDUrkolncLYd9FxY/SayxIwZRUZbuIRNhnX2v32ijYj8sMJLWl0jksGtOeNC7uEegrow10CHPrh2z07DZb2kLq75evsSTnLbQEsKrkMCMZLSZVp0ZehJb0pn1DEdbAWx8cG9b1NAEl/aLM/h565ExnWuP0i2ExETHh4c6BXLfxF9ybedtPDQ== jls@snack.home
+ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEA4cqwTnDIJrQvDLNFeFHNXEUpniveoaDMRJ05XFg3b55i8h0oQV/8OpU2HMuTRTrL3/24hjL6f9rzumeYbI6/eIkGw1Zb1HQ4KCJorDVcMgbpQwlenqcCYNgzL4IujrmtFnd4s4hR2jxnlScHwGeuOgdqufBKWwQoTXOWi6mOGyuWF1dH4DHLUX74GaspG+3Pgg/J3/iZAuGZyWq4dHPIYMPeonlbeJovI9JBrJ2/KDpqIzrAgVkvRCbU824wIOsoAMybZMX3iN6N13yl6J4DOe2U28qxAdkK7LJuIw/RtiDhOCyie9/ILFdDzeTHVvzJSesUNrQh8k7c2I6GdBN3jQ== jls@snack.home
View
@@ -0,0 +1,55 @@
+
+require "test/unit"
+
+$:.unshift "#{File.dirname(__FILE__)}/../lib"
+require "ssh/key/signer"
+require "ssh/key/verifier"
+
+class TestWithFiles < Test::Unit::TestCase
+ def setup
+ @signer = SSH::Key::Signer.new
+ @signer.use_agent = false
+
+ @verifier = SSH::Key::Verifier.new
+ @verifier.use_agent = false
+ @verifier.use_authorized_keys = false
+ end # def setup
+
+ def test_with_rsa_key_without_passphrase
+ @signer.add_private_key_file("keys/tester_nopassphrase_rsa")
+ idcount = @signer.signing_identities.length
+ assert_equal(1, idcount, "Expected 1 identity, found #{idcount}.")
+ end # def test_with_rsa_key_without_passphrase
+
+ def test_with_rsa_key_with_passphrase
+ @signer.add_private_key_file("keys/tester_withpassphrase_rsa", "testing")
+ idcount = @signer.signing_identities.length
+ assert_equal(1, idcount, "Expected 1 identity, found #{idcount}.")
+ end
+
+ def test_sign_and_verify_with_rsa_key_file
+ @signer.add_private_key_file("keys/tester_nopassphrase_rsa")
+ @verifier.add_public_key_file("keys/tester_nopassphrase_rsa.pub")
+
+ inputs = [ "hello", "foo bar 1 2 3 4", Marshal.dump({:test => :fizz}),
+ "", "1", " " ]
+ inputs.each do |data|
+ signatures = @signer.sign(data)
+ assert(@verifier.verify?(signatures, data),
+ "Signature verify failed against data '#{data.inspect}'")
+ end
+ end
+
+ def test_sign_and_verify_with_rsa_key_fails_on_bad_data
+ @signer.add_private_key_file("keys/tester_nopassphrase_rsa")
+ @verifier.add_public_key_file("keys/tester_nopassphrase_rsa.pub")
+
+ inputs = [ "hello", "foo bar 1 2 3 4", Marshal.dump({:test => :fizz}),
+ "", "1", " " ]
+ inputs.each do |data|
+ signatures = @signer.sign(data)
+ assert(!@verifier.verify?(signatures, data + "bad"),
+ "Signature verify expected to fail when verifying against altered data")
+ end
+ end
+end # class TestWithFiles

0 comments on commit e358282

Please sign in to comment.