summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Maher <tmaher@pw0n.me>2017-05-03 16:21:41 -0700
committerMiklos Fazekas <mfazekas@szemafor.com>2018-03-21 15:30:50 +0100
commit8f545802bbf05931dfcb46434a54c1fdfdfb7fb4 (patch)
tree8d091966789caef15f39deaa1d9e4bff17bab768
parent9463579e6e875d255ce93a0a1cc893b927672a13 (diff)
downloadnet-ssh-8f545802bbf05931dfcb46434a54c1fdfdfb7fb4.tar.gz
add sha256 key fingerprinting
-rw-r--r--lib/net/ssh/authentication/ed25519.rb75
-rw-r--r--lib/net/ssh/authentication/pub_key_fingerprint.rb41
-rw-r--r--lib/net/ssh/transport/openssl.rb5
-rw-r--r--lib/net/ssh/version.rb29
-rw-r--r--test/authentication/test_ed25519.rb44
-rw-r--r--test/test_key_factory.rb90
6 files changed, 217 insertions, 67 deletions
diff --git a/lib/net/ssh/authentication/ed25519.rb b/lib/net/ssh/authentication/ed25519.rb
index bcb7fd1..2f98fa1 100644
--- a/lib/net/ssh/authentication/ed25519.rb
+++ b/lib/net/ssh/authentication/ed25519.rb
@@ -6,67 +6,66 @@ require 'ed25519'
require 'base64'
require 'net/ssh/transport/cipher_factory'
+require 'net/ssh/authentication/pub_key_fingerprint'
require 'bcrypt_pbkdf' unless RUBY_PLATFORM == "java"
-module Net
- module SSH
+module Net
+ module SSH
module Authentication
module ED25519
class SigningKeyFromFile < SimpleDelegator
def initialize(pk,sk)
key = ::Ed25519::SigningKey.from_keypair(sk)
raise ArgumentError, "pk does not match sk" unless pk == key.verify_key.to_bytes
-
+
super(key)
end
end
-
+
class PubKey
+ include Net::SSH::Authentication::PubKeyFingerprint
+
attr_reader :verify_key
-
+
def initialize(data)
@verify_key = ::Ed25519::VerifyKey.new(data)
end
-
+
def self.read_keyblob(buffer)
PubKey.new(buffer.read_string)
end
-
+
def to_blob
Net::SSH::Buffer.from(:mstring,"ssh-ed25519",:string,@verify_key.to_bytes).to_s
end
-
+
def ssh_type
"ssh-ed25519"
end
-
+
def ssh_signature_type
ssh_type
end
-
+
def ssh_do_verify(sig,data)
@verify_key.verify(sig,data)
end
-
+
def to_pem
# TODO this is not pem
ssh_type + Base64.encode64(@verify_key.to_bytes)
end
-
- def fingerprint
- @fingerprint ||= OpenSSL::Digest::MD5.hexdigest(to_blob).scan(/../).join(":")
- end
end
-
+
class PrivKey
CipherFactory = Net::SSH::Transport::CipherFactory
-
+
MBEGIN = "-----BEGIN OPENSSH PRIVATE KEY-----\n"
MEND = "-----END OPENSSH PRIVATE KEY-----\n"
MAGIC = "openssh-key-v1"
-
+
attr_reader :sign_key
-
+
def initialize(datafull,password)
raise ArgumentError.new("Expected #{MBEGIN} at start of private key") unless datafull.start_with?(MBEGIN)
raise ArgumentError.new("Expected #{MEND} at end of private key") unless datafull.end_with?(MEND)
@@ -74,75 +73,75 @@ module Net
data = Base64.decode64(datab64)
raise ArgumentError.new("Expected #{MAGIC} at start of decoded private key") unless data.start_with?(MAGIC)
buffer = Net::SSH::Buffer.new(data[MAGIC.size + 1..-1])
-
+
ciphername = buffer.read_string
raise ArgumentError.new("#{ciphername} in private key is not supported") unless
CipherFactory.supported?(ciphername)
-
+
kdfname = buffer.read_string
raise ArgumentError.new("Expected #{kdfname} to be or none or bcrypt") unless %w[none bcrypt].include?(kdfname)
-
+
kdfopts = Net::SSH::Buffer.new(buffer.read_string)
num_keys = buffer.read_long
raise ArgumentError.new("Only 1 key is supported in ssh keys #{num_keys} was in private key") unless num_keys == 1
_pubkey = buffer.read_string
-
+
len = buffer.read_long
-
+
keylen, blocksize, ivlen = CipherFactory.get_lengths(ciphername, iv_len: true)
raise ArgumentError.new("Private key len:#{len} is not a multiple of #{blocksize}") if
((len < blocksize) || ((blocksize > 0) && (len % blocksize) != 0))
-
+
if kdfname == 'bcrypt'
salt = kdfopts.read_string
rounds = kdfopts.read_long
-
+
raise "BCryptPbkdf is not implemented for jruby" if RUBY_PLATFORM == "java"
key = BCryptPbkdf::key(password, salt, keylen + ivlen, rounds)
else
key = '\x00' * (keylen + ivlen)
end
-
+
cipher = CipherFactory.get(ciphername, key: key[0...keylen], iv:key[keylen...keylen + ivlen], decrypt: true)
-
+
decoded = cipher.update(buffer.remainder_as_buffer.to_s)
decoded << cipher.final
-
+
decoded = Net::SSH::Buffer.new(decoded)
check1 = decoded.read_long
check2 = decoded.read_long
-
+
raise ArgumentError, "Decrypt failed on private key" if (check1 != check2)
-
+
_type_name = decoded.read_string
pk = decoded.read_string
sk = decoded.read_string
_comment = decoded.read_string
-
+
@pk = pk
@sign_key = SigningKeyFromFile.new(pk,sk)
end
-
+
def to_blob
public_key.to_blob
end
-
+
def ssh_type
"ssh-ed25519"
end
-
+
def ssh_signature_type
ssh_type
end
-
+
def public_key
PubKey.new(@pk)
end
-
+
def ssh_do_sign(data)
@sign_key.sign(data)
end
-
+
def self.read(data,password)
self.new(data,password)
end
diff --git a/lib/net/ssh/authentication/pub_key_fingerprint.rb b/lib/net/ssh/authentication/pub_key_fingerprint.rb
new file mode 100644
index 0000000..e06aeef
--- /dev/null
+++ b/lib/net/ssh/authentication/pub_key_fingerprint.rb
@@ -0,0 +1,41 @@
+
+require 'openssl'
+
+module Net
+ module SSH
+ module Authentication
+ # Public key fingerprinting utility module - internal not part of API.
+ # This is included in pubkey classes and called from there. All RSA, DSA, and ECC keys
+ # are supported.
+ #
+ # require 'net/ssh'
+ # my_pubkey_text = File.read('/path/to/id_ed25519.pub')
+ # #=> "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDB2NBh4GJPPUN1kXPMu8b633Xcv55WoKC3OkBjFAbzJ alice@example.com"
+ # my_pubkey = Net::SSH::KeyFactory.load_data_public_key(my_pubkey_text)
+ # #=> #<Net::SSH::Authentication::ED25519::PubKey:0x00007fc8e91819b0
+ # my_pubkey.fingerprint
+ # #=> "2f:7f:97:21:76:a4:0f:38:c4:fe:d8:b4:6a:39:72:30"
+ # my_pubkey.fingerprint('SHA256')
+ # #=> "SHA256:u6mXnY8P1b0FODGp8mckqOB33u8+jvkSCtJbD5Q9klg"
+ module PubKeyFingerprint # :nodoc:
+ # Return the key's fingerprint. Algorithm may be either +MD5+ (default),
+ # or +SHA256+. For +SHA256+, fingerprints are in the same format
+ # returned by OpenSSH's <tt>`ssh-add -l -E SHA256`</tt>, i.e.,
+ # trailing base64 padding '=' characters are stripped and the
+ # literal string +SHA256:+ is prepended.
+ def fingerprint(algorithm='MD5')
+ @fingerprint ||= {}
+ @fingerprint[algorithm] ||=
+ case algorithm.to_s.upcase
+ when 'MD5'
+ OpenSSL::Digest.hexdigest(algorithm, to_blob).scan(/../).join(":")
+ when 'SHA256'
+ "SHA256:#{Base64.encode64(OpenSSL::Digest.digest(algorithm, to_blob)).chomp.gsub(/=+\z/, '')}"
+ else
+ raise OpenSSL::Digest::DigestError, "unsupported ssh key digest #{algorithm}"
+ end
+ end
+ end
+ end
+ end
+end
diff --git a/lib/net/ssh/transport/openssl.rb b/lib/net/ssh/transport/openssl.rb
index 9135ae0..15715f4 100644
--- a/lib/net/ssh/transport/openssl.rb
+++ b/lib/net/ssh/transport/openssl.rb
@@ -1,4 +1,5 @@
require 'openssl'
+require 'net/ssh/authentication/pub_key_fingerprint'
module OpenSSL
@@ -25,9 +26,7 @@ module OpenSSL
module PKey
class PKey
- def fingerprint
- @fingerprint ||= OpenSSL::Digest::MD5.hexdigest(to_blob).scan(/../).join(":")
- end
+ include Net::SSH::Authentication::PubKeyFingerprint
end
# This class is originally defined in the OpenSSL module. As needed, methods
diff --git a/lib/net/ssh/version.rb b/lib/net/ssh/version.rb
index fcd5db8..c1a6cca 100644
--- a/lib/net/ssh/version.rb
+++ b/lib/net/ssh/version.rb
@@ -1,4 +1,4 @@
-module Net
+module Net
module SSH
# A class for describing the current version of a library. The version
# consists of three parts: the +major+ number, the +minor+ number, and the
@@ -14,54 +14,55 @@ module Net
# end
class Version
include Comparable
-
+
# A convenience method for instantiating a new Version instance with the
# given +major+, +minor+, and +tiny+ components.
def self.[](major, minor, tiny, pre = nil)
new(major, minor, tiny, pre)
end
-
+
attr_reader :major, :minor, :tiny
-
+
# Create a new Version object with the given components.
def initialize(major, minor, tiny, pre = nil)
@major, @minor, @tiny, @pre = major, minor, tiny, pre
end
-
+
# Compare this version to the given +version+ object.
def <=>(version)
to_i <=> version.to_i
end
-
+
# Converts this version object to a string, where each of the three
# version components are joined by the '.' character. E.g., 2.0.0.
def to_s
@to_s ||= [@major, @minor, @tiny, @pre].compact.join(".")
end
-
+
# Converts this version to a canonical integer that may be compared
# against other version objects.
def to_i
@to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
end
-
+
# The major component of this version of the Net::SSH library
MAJOR = 5
-
+
# The minor component of this version of the Net::SSH library
MINOR = 0
-
+
# The tiny component of this version of the Net::SSH library
TINY = 0
-
+
# The prerelease component of this version of the Net::SSH library
# nil allowed
PRE = "beta1"
-
+
# The current version of the Net::SSH library as a Version instance
CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact)
-
+
# The current version of the Net::SSH library as a String
STRING = CURRENT.to_s
end
-end; end
+ end
+end
diff --git a/test/authentication/test_ed25519.rb b/test/authentication/test_ed25519.rb
index 620942b..6c0bca5 100644
--- a/test/authentication/test_ed25519.rb
+++ b/test/authentication/test_ed25519.rb
@@ -5,27 +5,29 @@ unless ENV['NET_SSH_NO_ED25519']
require 'base64'
module Authentication
-
+
class TestED25519 < NetSSHTest
def setup
raise "No ED25519 set NET_SSH_NO_ED25519 to ignore this test" unless Net::SSH::Authentication::ED25519Loader::LOADED
end
-
+
def test_no_pwd_key
pub = Net::SSH::Buffer.new(Base64.decode64(public_key_no_pwd.split(' ')[1]))
_type = pub.read_string
pub_data = pub.read_string
priv = private_key_no_pwd
-
+
pub_key = Net::SSH::Authentication::ED25519::PubKey.new(pub_data)
priv_key = Net::SSH::Authentication::ED25519::PrivKey.new(priv,nil)
-
+
shared_secret = "Hello"
signed = priv_key.ssh_do_sign(shared_secret)
self.assert_equal(true,pub_key.ssh_do_verify(signed,shared_secret))
self.assert_equal(priv_key.public_key.fingerprint, pub_key.fingerprint)
+ self.assert_equal(pub_key.fingerprint, key_fingerprint_md5_no_pwd)
+ self.assert_equal(pub_key.fingerprint('sha256'), key_fingerprint_sha256_no_pwd)
end
-
+
def test_pwd_key
if defined?(JRUBY_VERSION)
puts "Skipping password protected ED25519 for JRuby"
@@ -35,16 +37,18 @@ unless ENV['NET_SSH_NO_ED25519']
_type = pub.read_string
pub_data = pub.read_string
priv = private_key_pwd
-
+
pub_key = Net::SSH::Authentication::ED25519::PubKey.new(pub_data)
priv_key = Net::SSH::Authentication::ED25519::PrivKey.new(priv,'pwd')
-
+
shared_secret = "Hello"
signed = priv_key.ssh_do_sign(shared_secret)
self.assert_equal(true,pub_key.ssh_do_verify(signed,shared_secret))
self.assert_equal(priv_key.public_key.fingerprint, pub_key.fingerprint)
+ self.assert_equal(pub_key.fingerprint, key_fingerprint_md5_pwd)
+ self.assert_equal(pub_key.fingerprint('sha256'), key_fingerprint_sha256_pwd)
end
-
+
def private_key_pwd
@pwd_key = <<-EOF
-----BEGIN OPENSSH PRIVATE KEY-----
@@ -57,11 +61,19 @@ oPcTikV1iWH5Xc+GxRFRRGTN/6HvBf0AKDB1kMXlDhGnBnHGeNH1pk44xG
-----END OPENSSH PRIVATE KEY-----
EOF
end
-
+
def public_key_pwd
'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICaHkFaGXqYhUVFcaZ10TPUbkIvmaFXwYRoOS5qE8Mci vagrant@vagrant-ubuntu-trusty-64'
end
-
+
+ def key_fingerprint_md5_pwd
+ 'c8:89:92:60:12:1b:01:5e:ca:58:55:68:7e:5e:1a:f1'
+ end
+
+ def key_fingerprint_sha256_pwd
+ 'SHA256:Uz5Qk/fB+f8Bu7FTxNcDh7+atpB29Q3tBBJX/gnUfGw'
+ end
+
def private_key_no_pwd
@anonymous_key = <<-EOF
-----BEGIN OPENSSH PRIVATE KEY-----
@@ -74,12 +86,20 @@ IDBAU=
-----END OPENSSH PRIVATE KEY-----
EOF
end
-
+
def public_key_no_pwd
'ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDB2NBh4GJPPUN1kXPMu8b633Xcv55WoKC3OkBjFAbzJ vagrant@vagrant-ubuntu-trusty-64'
end
+
+ def key_fingerprint_md5_no_pwd
+ '2f:7f:97:21:76:a4:0f:38:c4:fe:d8:b4:6a:39:72:30'
+ end
+
+ def key_fingerprint_sha256_no_pwd
+ 'SHA256:u6mXnY8P1b0FODGp8mckqOB33u8+jvkSCtJbD5Q9klg'
+ end
end
-
+
end
end
diff --git a/test/test_key_factory.rb b/test/test_key_factory.rb
index 9e0d85e..0780868 100644
--- a/test/test_key_factory.rb
+++ b/test/test_key_factory.rb
@@ -11,11 +11,31 @@ class TestKeyFactory < NetSSHTest
assert_equal rsa_key.to_der, Net::SSH::KeyFactory.load_private_key(@key_file).to_der
end
+ def test_load_unencrypted_private_RSA_key_should_have_fp_md5
+ File.expects(:read).with(@key_file).returns(rsa_key.export)
+ assert_equal rsa_key_fingerprint_md5, Net::SSH::KeyFactory.load_private_key(@key_file).fingerprint
+ end
+
+ def test_load_unencrypted_private_RSA_key_should_have_fp_sha256
+ File.expects(:read).with(@key_file).returns(rsa_key.export)
+ assert_equal rsa_key_fingerprint_sha256, Net::SSH::KeyFactory.load_private_key(@key_file).fingerprint('sha256')
+ end
+
def test_load_unencrypted_private_DSA_key_should_return_key
File.expects(:read).with(@key_file).returns(dsa_key.export)
assert_equal dsa_key.to_der, Net::SSH::KeyFactory.load_private_key(@key_file).to_der
end
+ def test_load_unencrypted_private_DSA_key_should_have_fp_md5
+ File.expects(:read).with(@key_file).returns(dsa_key.export)
+ assert_equal dsa_key_fingerprint_md5, Net::SSH::KeyFactory.load_private_key(@key_file).fingerprint
+ end
+
+ def test_load_unencrypted_private_DSA_key_should_have_fp_sha256
+ File.expects(:read).with(@key_file).returns(dsa_key.export)
+ assert_equal dsa_key_fingerprint_sha256, Net::SSH::KeyFactory.load_private_key(@key_file).fingerprint('sha256')
+ end
+
def test_load_encrypted_private_RSA_key_should_prompt_for_password_and_return_key
prompt = MockPrompt.new
File.expects(:read).with(@key_file).returns(encrypted(rsa_key, "password"))
@@ -100,6 +120,36 @@ class TestKeyFactory < NetSSHTest
assert_equal ecdsa_sha2_nistp521_key.to_der, Net::SSH::KeyFactory.load_private_key("/key-file").to_der
end
+ def test_load_unencrypted_private_ecdsa_sha2_nistp256_key_should_have_fp_md5
+ File.expects(:read).with(@key_file).returns(ecdsa_sha2_nistp256_key.to_pem)
+ assert_equal ecdsa_sha2_nistp256_key_fingerprint_md5, Net::SSH::KeyFactory.load_private_key("/key-file").fingerprint
+ end
+
+ def test_load_unencrypted_private_ecdsa_sha2_nistp256_key_should_have_fp_sha256
+ File.expects(:read).with(@key_file).returns(ecdsa_sha2_nistp256_key.to_pem)
+ assert_equal ecdsa_sha2_nistp256_key_fingerprint_sha256, Net::SSH::KeyFactory.load_private_key("/key-file").fingerprint('sha256')
+ end
+
+ def test_load_unencrypted_private_ecdsa_sha2_nistp384_key_should_have_fp_md5
+ File.expects(:read).with(@key_file).returns(ecdsa_sha2_nistp384_key.to_pem)
+ assert_equal ecdsa_sha2_nistp384_key_fingerprint_md5, Net::SSH::KeyFactory.load_private_key("/key-file").fingerprint
+ end
+
+ def test_load_unencrypted_private_ecdsa_sha2_nistp384_key_should_have_fp_sha256
+ File.expects(:read).with(@key_file).returns(ecdsa_sha2_nistp384_key.to_pem)
+ assert_equal ecdsa_sha2_nistp384_key_fingerprint_sha256, Net::SSH::KeyFactory.load_private_key("/key-file").fingerprint('sha256')
+ end
+
+ def test_load_unencrypted_private_ecdsa_sha2_nistp521_key_should_have_fp_md5
+ File.expects(:read).with(@key_file).returns(ecdsa_sha2_nistp521_key.to_pem)
+ assert_equal ecdsa_sha2_nistp521_key_fingerprint_md5, Net::SSH::KeyFactory.load_private_key("/key-file").fingerprint
+ end
+
+ def test_load_unencrypted_private_ecdsa_sha2_nistp521_key_should_have_fp_sha256
+ File.expects(:read).with(@key_file).returns(ecdsa_sha2_nistp521_key.to_pem)
+ assert_equal ecdsa_sha2_nistp521_key_fingerprint_sha256, Net::SSH::KeyFactory.load_private_key("/key-file").fingerprint('sha256')
+ end
+
def test_load_public_ecdsa_sha2_nistp256_key_should_return_key
File.expects(:read).with(@key_file).returns(public(ecdsa_sha2_nistp256_key))
assert_equal ecdsa_sha2_nistp256_key.to_blob, Net::SSH::KeyFactory.load_public_key("/key-file").to_blob
@@ -127,6 +177,14 @@ class TestKeyFactory < NetSSHTest
private
+ def rsa_key_fingerprint_md5
+ '32:00:44:78:bf:91:02:c1:00:25:0f:f9:0a:f9:aa:c7'
+ end
+
+ def rsa_key_fingerprint_sha256
+ 'SHA256:1XFnG2UY/fBunFk1vviHPVV5ruqbL6ZBfGVVOf9mRMk'
+ end
+
def rsa_key
# 512 bits
@rsa_key ||= OpenSSL::PKey::RSA.new("0\202\001;\002\001\000\002A\000\235\236\374N\e@2E\321\3757\003\354c\276N\f\003\3479Ko\005\317\0027\a\255=\345!\306\220\340\211;\027u\331\260\362\2063x\332\301y4\353\v%\032\214v\312\304\212\271GJ\353\2701\031\002\003\001\000\001\002@\022Y\306*\031\306\031\224Cde\231QV3{\306\256U\2477\377\017\000\020\323\363R\332\027\351\034\224OU\020\227H|pUS\n\263+%\304\341\321\273/\271\e\004L\250\273\020&,\t\304By\002!\000\311c\246%a\002\305\277\262R\266\244\250\025V_\351]\264\016\265\341\355\305\223\347Z$8\205#\023\002!\000\310\\\367|\243I\363\350\020\307\246\302\365\ed\212L\273\2158M\223w\a\367 C\t\224A4\243\002!\000\262]+}\327\231\331\002\2331^\312\036\204'g\363\f&\271\020\245\365-\024}\306\374e\202\2459\002 }\231\341\276\3551\277\307{5\\\361\233\353G\024wS\237\fk}\004\302&\205\277\340rb\211\327\002!\000\223\307\025I:\215_\260\370\252\3757\256Y&X\364\354\342\215\350\203E8\227|\f\237M\375D|")
@@ -137,18 +195,50 @@ class TestKeyFactory < NetSSHTest
@dsa_key ||= OpenSSL::PKey::DSA.new("0\201\367\002\001\000\002A\000\203\316/\037u\272&J\265\003l3\315d\324h\372{\t8\252#\331_\026\006\035\270\266\255\343\353Z\302\276\335\336\306\220\375\202L\244\244J\206>\346\b\315\211\302L\246x\247u\a\376\366\345\302\016#\002\025\000\244\274\302\221Og\275/\302+\356\346\360\024\373wI\2573\361\002@\027\215\270r*\f\213\350C\245\021:\350 \006\\\376\345\022`\210b\262\3643\023XLKS\320\370\002\276\347A\nU\204\276\324\256`=\026\240\330\306J\316V\213\024\e\030\215\355\006\037q\337\356ln\002@\017\257\034\f\260\333'S\271#\237\230E\321\312\027\021\226\331\251Vj\220\305\316\036\v\266+\000\230\270\177B\003?t\a\305]e\344\261\334\023\253\323\251\223M\2175)a(\004\"lI8\312\303\307\a\002\024_\aznW\345\343\203V\326\246ua\203\376\201o\350\302\002")
end
+ def dsa_key_fingerprint_md5
+ '8c:3a:e7:ea:34:cd:75:7a:fd:c9:b8:48:ce:4a:2f:97'
+ end
+
+ def dsa_key_fingerprint_sha256
+ 'SHA256:9+7rXHxjuAmxm3UjuZ3T1qTF/UZUrmZQMJC8kNMr7J8'
+ end
+
if defined?(OpenSSL::PKey::EC)
def ecdsa_sha2_nistp256_key
@ecdsa_sha2_nistp256_key ||= OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINv6pPVLlkqvT1v5MJlWgaSWGwqupISG4U79bUXQDNCaoAoGCCqGSM49\nAwEHoUQDQgAElqubvi/GkSme+bwtncU1NiE0dWQ0EO07VufUQg8lUJ5+Fi6f96qa\n95T1zwOMQhY1h8PP9rQIZr4S48vN/ZnQLw==\n-----END EC PRIVATE KEY-----\n")
end
+ def ecdsa_sha2_nistp256_key_fingerprint_md5
+ 'ed:9e:cd:74:41:a4:37:ae:99:9e:9a:c3:de:04:c9:e1'
+ end
+
+ def ecdsa_sha2_nistp256_key_fingerprint_sha256
+ 'SHA256:yGdFZAf5Mbg5+EPA802cn4lo+uoBEj3RBK4DLG9WK1Y'
+ end
+
def ecdsa_sha2_nistp384_key
@ecdsa_sha2_nistp384_key ||= OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDBxwkmydCn4mP4KMhlMpeBvIroQolWKVNoRPXpG7brFgK+Yiikqw8wd\nIZW5OlL4y3mgBwYFK4EEACKhZANiAARkoIR1oABi+aQJbKcmvzeYSKURQOyXM0HU\nR4T68v4hd/lJE4fFQRczj3wAaECe9u3CWI/oDlow4Vr0vab82ZGjIoblxblKQWYl\nyzENgzl226waGg1bLBo8Auilyf1B5yI=\n-----END EC PRIVATE KEY-----\n")
end
+ def ecdsa_sha2_nistp384_key_fingerprint_md5
+ '87:5a:c0:a0:23:55:22:05:ca:16:4d:cc:0c:e5:e7:74'
+ end
+
+ def ecdsa_sha2_nistp384_key_fingerprint_sha256
+ 'SHA256:l8ZS7aKnquF8VUXAbHj9wPEEenUjyKIiuUSgOWbWqUw'
+ end
+
def ecdsa_sha2_nistp521_key
@ecdsa_sha2_nistp521_key ||= OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMIHbAgEBBEHQ2i7kjEGQHQB4pUQW9a2eCLWR2S5Go8U3CDyfbRCrYEp/pTSgI8uu\nMXyR3bf3SjqFQgZ6MZk5lkyrissJuwmvZKAHBgUrgQQAI6GBiQOBhgAEAN14FACK\nbs/KTqw4rxijeozGTVJTh1hNzBl2XaIhM4Fv8o3fE/pvogymyFu53GCng6gC4dmx\n/hycF41iIM29xVKPAeBnRNl6MdFBjuthOmE8eCRezgk1Bak8aBDUrzNT8OQssscw\npvQK4nc6ga/wTDaQGy5kV8tCOHNs2wKH+p2LpWTJ\n-----END EC PRIVATE KEY-----\n")
end
+
+ def ecdsa_sha2_nistp521_key_fingerprint_md5
+ '6d:5f:10:80:18:4a:69:f3:e3:70:a3:87:90:81:9a:11'
+ end
+
+ def ecdsa_sha2_nistp521_key_fingerprint_sha256
+ 'SHA256:gxtS/gn7iVn6rGgH3EZCInzxN2/hiONcaRSyBJ/Nr4U'
+ end
end
def anonymous_private_key