Class: Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader
- Inherits:
-
Object
- Object
- Net::SSH::Authentication::ED25519::OpenSSHPrivateKeyLoader
- Defined in:
- lib/net/ssh/authentication/ed25519.rb
Defined Under Namespace
Classes: DecryptError
Constant Summary collapse
- CipherFactory =
Net::SSH::Transport::CipherFactory
- MBEGIN =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
- MEND =
"-----END OPENSSH PRIVATE KEY-----"
- MAGIC =
"openssh-key-v1"
Class Method Summary collapse
Class Method Details
.read(datafull, password) ⇒ Object
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/net/ssh/authentication/ed25519.rb', line 41 def self.read(datafull, password) datafull = datafull.strip 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) datab64 = datafull[MBEGIN.size...-MEND.size] data = datab64.unpack1("m") 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) raise DecryptError.new("BCyryptPbkdf failed", encrypted_key: true) unless key 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 DecryptError.new("Decrypt failed on private key", encrypted_key: kdfname == 'bcrypt') if (check1 != check2) type_name = decoded.read_string case type_name when "ssh-ed25519" PrivKey.new(decoded) else decoded.read_private_keyblob(type_name) end end |