helpers for generating private keys

This commit is contained in:
Ben Toews 2019-02-25 08:54:36 -07:00
Родитель 689f9f9533
Коммит 214e2cbb23
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: E9C423BE17EFEE70
11 изменённых файлов: 134 добавлений и 13 удалений

Просмотреть файл

@ -7,6 +7,22 @@ module SSHData
@algo = kwargs[:algo]
@comment = kwargs[:comment]
end
# Generate a new private key.
#
# Returns a PublicKey::Base subclass instance.
def self.generate(**kwargs)
raise "implement me"
end
# Make an SSH signature.
#
# signed_data - The String message over which to calculated the signature.
#
# Returns a binary String signature.
def sign(signed_data)
raise "implement me"
end
end
end
end

Просмотреть файл

@ -3,6 +3,18 @@
class DSA < Base
attr_reader :p, :q, :g, :x, :y, :openssl
# Generate a new private key.
#
# Returns a PublicKey::Base subclass instance.
def self.generate
from_openssl(OpenSSL::PKey::DSA.generate(1024))
end
# Import an openssl private key.
#
# key - An OpenSSL::PKey::DSA instance.
#
# Returns a DSA instance.
def self.from_openssl(key)
new(
algo: PublicKey::ALGO_DSA,

Просмотреть файл

@ -3,6 +3,25 @@ module SSHData
class ECDSA < Base
attr_reader :curve, :public_key_bytes, :private_key_bytes, :openssl
# Generate a new private key.
#
# curve - The String curve to use. One of SSHData::PublicKey::NISTP256,
# SSHData::PublicKey::NISTP384, or SSHData::PublicKey::NISTP521.
#
# Returns a PublicKey::Base subclass instance.
def self.generate(curve)
openssl_curve = PublicKey::ECDSA::OPENSSL_CURVE_NAME_FOR_CURVE[curve]
raise AlgorithmError, "unknown curve: #{curve}" if openssl_curve.nil?
openssl_key = OpenSSL::PKey::EC.new(openssl_curve).tap(&:generate_key)
from_openssl(openssl_key)
end
# Import an openssl private key.
#
# key - An OpenSSL::PKey::EC instance.
#
# Returns a DSA instance.
def self.from_openssl(key)
curve = PublicKey::ECDSA::CURVE_FOR_OPENSSL_CURVE_NAME[key.group.curve_name]
algo = "ecdsa-sha2-#{curve}"

Просмотреть файл

@ -3,6 +3,13 @@ module SSHData
class ED25519 < Base
attr_reader :pk, :sk, :ed25519_key
# Generate a new private key.
#
# Returns a PublicKey::Base subclass instance.
def self.generate
from_ed25519(Ed25519::SigningKey.generate)
end
# Create from a ::Ed25519::SigningKey instance.
#
# key - A ::Ed25519::SigningKey instance.

Просмотреть файл

@ -3,6 +3,27 @@ module SSHData
class RSA < Base
attr_reader :n, :e, :d, :iqmp, :p, :q, :openssl
# Generate a new private key.
#
# size - The Integer key size to generate.
# unsafe_allow_small_key: - Bool of whether to allow keys of less than
# 2048 bits.
#
# Returns a PublicKey::Base subclass instance.
def self.generate(size, unsafe_allow_small_key: false)
unless size >= 2048 || unsafe_allow_small_key
raise AlgorithmError, "key too small"
end
from_openssl(OpenSSL::PKey::RSA.generate(size))
end
# Import an openssl private key.
#
# key - An OpenSSL::PKey::DSA instance.
#
# Returns a DSA instance.
def self.from_openssl(key)
new(
algo: PublicKey::ALGO_RSA,

Просмотреть файл

@ -3,22 +3,26 @@ module SSHData
class ECDSA < Base
attr_reader :curve, :public_key_bytes, :openssl
NISTP256 = "nistp256"
NISTP384 = "nistp384"
NISTP521 = "nistp521"
OPENSSL_CURVE_NAME_FOR_CURVE = {
"nistp256" => "prime256v1",
"nistp384" => "secp384r1",
"nistp521" => "secp521r1",
NISTP256 => "prime256v1",
NISTP384 => "secp384r1",
NISTP521 => "secp521r1",
}
CURVE_FOR_OPENSSL_CURVE_NAME = {
"prime256v1" => "nistp256",
"secp384r1" => "nistp384",
"secp521r1" => "nistp521",
"prime256v1" => NISTP256,
"secp384r1" => NISTP384,
"secp521r1" => NISTP521,
}
DIGEST_FOR_CURVE = {
"nistp256" => OpenSSL::Digest::SHA256,
"nistp384" => OpenSSL::Digest::SHA384,
"nistp521" => OpenSSL::Digest::SHA512,
NISTP256 => OpenSSL::Digest::SHA256,
NISTP384 => OpenSSL::Digest::SHA384,
NISTP521 => OpenSSL::Digest::SHA512,
}
# Convert an SSH encoded ECDSA signature to DER encoding for verification with

Просмотреть файл

@ -1,10 +1,10 @@
require_relative "./spec_helper"
describe SSHData::Certificate do
let(:rsa_ca) { SSHData::PrivateKey::RSA.from_openssl(OpenSSL::PKey::RSA.generate(2048)) }
let(:dsa_ca) { SSHData::PrivateKey::DSA.from_openssl(OpenSSL::PKey::DSA.generate(1024)) }
let(:ecdsa_ca) { SSHData::PrivateKey::ECDSA.from_openssl(OpenSSL::PKey::EC.new("prime256v1").tap(&:generate_key)) }
let(:ed25519_ca) { SSHData::PrivateKey::ED25519.from_ed25519(Ed25519::SigningKey.generate) }
let(:rsa_ca) { SSHData::PrivateKey::RSA.generate(2048) }
let(:dsa_ca) { SSHData::PrivateKey::DSA.generate }
let(:ecdsa_ca) { SSHData::PrivateKey::ECDSA.generate("nistp256") }
let(:ed25519_ca) { SSHData::PrivateKey::ED25519.generate }
it "supports the deprecated Certificate.parse method" do
expect {

Просмотреть файл

@ -10,6 +10,12 @@ describe SSHData::PrivateKey::DSA do
subject { described_class.from_openssl(private_key) }
it "can be generated" do
expect {
described_class.generate
}.not_to raise_error
end
it "can sign messages" do
expect(subject.public_key.verify(message, subject.sign(message))).to eq(true)
end

Просмотреть файл

@ -3,6 +3,12 @@ require_relative "../spec_helper"
describe SSHData::PrivateKey::ECDSA do
let(:openssh_key) { SSHData::PrivateKey.parse(fixture("ecdsa_leaf_for_rsa_ca")) }
it "can raises AlgorithmError for unknown curves" do
expect {
described_class.generate("foo")
}.to raise_error(SSHData::AlgorithmError)
end
it "can parse openssh-generate keys" do
keys = openssh_key
expect(keys).to be_an(Array)
@ -21,6 +27,12 @@ describe SSHData::PrivateKey::ECDSA do
subject { described_class.from_openssl(private_key) }
it "can be generated" do
expect {
described_class.generate(ssh_curve)
}.not_to raise_error
end
it "can sign messages" do
expect(subject.public_key.verify(message, subject.sign(message))).to eq(true)
end

Просмотреть файл

@ -17,6 +17,12 @@ describe SSHData::PrivateKey::ED25519 do
)
end
it "can be generated" do
expect {
described_class.generate
}.not_to raise_error
end
it "can sign messages" do
expect(subject.public_key.verify(message, subject.sign(message))).to eq(true)
end

Просмотреть файл

@ -10,6 +10,24 @@ describe SSHData::PrivateKey::RSA do
subject { described_class.from_openssl(private_key) }
it "can be generated" do
expect {
described_class.generate(2048)
}.not_to raise_error
end
it "raises AlgorithmError on small key sizes" do
expect {
described_class.generate(1024)
}.to raise_error(SSHData::AlgorithmError)
end
it "can generate small keys if unsafe_allow_small_key is passed" do
expect {
described_class.generate(1024, unsafe_allow_small_key: true)
}.not_to raise_error
end
it "can sign messages" do
expect(subject.public_key.verify(message, subject.sign(message))).to eq(true)
end