core: Vagrant::Util::Keypair for generating keypairs

This commit is contained in:
Mitchell Hashimoto 2014-10-24 09:33:44 -07:00
parent d6c55d4834
commit f4dec575ed
2 changed files with 80 additions and 0 deletions

View File

@ -0,0 +1,46 @@
require "base64"
require "openssl"
module Vagrant
module Util
class Keypair
# Creates an SSH keypair and returns it.
#
# @param [String] password Password for the key, or nil for no password.
# @return [Array<String, String, String>] PEM-encoded public and private key,
# respectively. The final element is the OpenSSH encoded public
# key.
def self.create(password=nil)
rsa_key = OpenSSL::PKey::RSA.new(2048)
public_key = rsa_key.public_key
private_key = rsa_key.to_pem
if password
cipher = OpenSSL::Cipher::Cipher.new('des3')
private_key = rsa_key.to_pem(cipher, password)
end
# Generate the binary necessary for the OpenSSH public key.
binary = [7].pack("N")
binary += "ssh-rsa"
["e", "n"].each do |m|
val = public_key.send(m)
data = val.to_s(2)
first_byte = data[0,1].unpack("c").first
if val < 0
data[0] = [0x80 & first_byte].pack("c")
elsif first_byte < 0
data = 0.chr + data
end
binary += [data.length].pack("N") + data
end
openssh_key = "ssh-rsa #{Base64.encode64(binary).gsub("\n", "")} vagrant"
public_key = public_key.to_pem
return [public_key, private_key, openssh_key]
end
end
end
end

View File

@ -0,0 +1,34 @@
require "openssl"
require File.expand_path("../../../base", __FILE__)
require "vagrant/util/keypair"
describe Vagrant::Util::Keypair do
describe ".create" do
it "generates a usable keypair with no password" do
# I don't know how to validate the final return value yet...
pubkey, privkey, _ = described_class.create
pubkey = OpenSSL::PKey::RSA.new(pubkey)
privkey = OpenSSL::PKey::RSA.new(privkey)
encrypted = pubkey.public_encrypt("foo")
decrypted = privkey.private_decrypt(encrypted)
expect(decrypted).to eq("foo")
end
it "generates a keypair that requires a password" do
pubkey, privkey, _ = described_class.create("password")
pubkey = OpenSSL::PKey::RSA.new(pubkey)
privkey = OpenSSL::PKey::RSA.new(privkey, "password")
encrypted = pubkey.public_encrypt("foo")
decrypted = privkey.private_decrypt(encrypted)
expect(decrypted).to eq("foo")
end
end
end