core: Vagrant::Util::Keypair for generating keypairs
This commit is contained in:
parent
d6c55d4834
commit
f4dec575ed
|
@ -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
|
|
@ -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
|
Loading…
Reference in New Issue