diff --git a/lib/ssh_data/private_key/ed25519.rb b/lib/ssh_data/private_key/ed25519.rb index 395a4b0..d668aa9 100644 --- a/lib/ssh_data/private_key/ed25519.rb +++ b/lib/ssh_data/private_key/ed25519.rb @@ -7,6 +7,7 @@ module SSHData # # Returns a PublicKey::Base subclass instance. def self.generate + PublicKey::ED25519.ed25519_gem_required! from_ed25519(Ed25519::SigningKey.generate) end @@ -56,6 +57,7 @@ module SSHData # # Returns a binary String signature. def sign(signed_data, algo: nil) + PublicKey::ED25519.ed25519_gem_required! algo ||= self.algo raise AlgorithmError unless algo == self.algo raw_sig = ed25519_key.sign(signed_data) diff --git a/lib/ssh_data/public_key/ed25519.rb b/lib/ssh_data/public_key/ed25519.rb index 34fa870..c2796c7 100644 --- a/lib/ssh_data/public_key/ed25519.rb +++ b/lib/ssh_data/public_key/ed25519.rb @@ -9,6 +9,13 @@ module SSHData Object.const_defined?(:Ed25519) end + # Assert that the ed25519 gem has been loaded. + # + # Returns nothing, raises AlgorithmError. + def self.ed25519_gem_required! + raise AlgorithmError, "the ed25519 gem is not loaded" unless enabled? + end + def initialize(algo:, pk:) unless algo == ALGO_ED25519 raise DecodeError, "bad algorithm: #{algo.inspect}" @@ -30,9 +37,7 @@ module SSHData # # Returns boolean. def verify(signed_data, signature) - unless self.class.enabled? - raise VerifyError, "the ed25519 gem isn't loadedd" - end + self.class.ed25519_gem_required! sig_algo, raw_sig, _ = Encoding.decode_signature(signature) if sig_algo != ALGO_ED25519 diff --git a/spec/private_key/ed25519_spec.rb b/spec/private_key/ed25519_spec.rb index 70cca1a..1432902 100644 --- a/spec/private_key/ed25519_spec.rb +++ b/spec/private_key/ed25519_spec.rb @@ -78,4 +78,27 @@ describe SSHData::PrivateKey::ED25519 do expect(keys.size).to eq(1) expect(keys.first).to be_an(SSHData::PrivateKey::ED25519) end + + it "fails cleanly if the ed25519 gem hasn't been loaded" do + backup = Object.send(:remove_const, :Ed25519) + key = openssh_key.first + + begin + expect { + expect(key.sk).not_to be_nil + expect(key.pk).not_to be_nil + expect(key.public_key).not_to be_nil + }.not_to raise_error + + expect { + described_class.generate + }.to raise_error(SSHData::AlgorithmError) + + expect { + key.sign(message) + }.to raise_error(SSHData::AlgorithmError) + ensure + Object.const_set(:Ed25519, backup) + end + end end diff --git a/spec/public_key/ed25519_spec.rb b/spec/public_key/ed25519_spec.rb index e17e0f7..9c537c9 100644 --- a/spec/public_key/ed25519_spec.rb +++ b/spec/public_key/ed25519_spec.rb @@ -67,15 +67,15 @@ describe SSHData::PublicKey::ED25519 do it "fails cleanly if the ed25519 gem hasn't been loaded" do expect(described_class.enabled?).to be(true) - backup = Object.send(:remove_const, :Ed25519) - expect(described_class.enabled?).to be(false) + backup = Object.send(:remove_const, :Ed25519) + expect(described_class.enabled?).to be(false) begin expect { SSHData::Certificate.parse_openssh(fixture("rsa_leaf_for_ed25519_ca-cert.pub"), unsafe_no_verify: false ) - }.to raise_error(SSHData::VerifyError) + }.to raise_error(SSHData::AlgorithmError) ensure Object.const_set(:Ed25519, backup) end