Class: Net::SSH::Authentication::ED25519::PrivKey

Inherits:
Object
  • Object
show all
Defined in:
lib/net/ssh/authentication/ed25519.rb

Constant Summary collapse

CipherFactory =
Net::SSH::Transport::CipherFactory
MBEGIN =
"-----BEGIN OPENSSH PRIVATE KEY-----\n"
MEND =
"-----END OPENSSH PRIVATE KEY-----\n"
MAGIC =
"openssh-key-v1"

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(datafull, password) ⇒ PrivKey

Returns a new instance of PrivKey.

Raises:

  • (ArgumentError)


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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/net/ssh/authentication/ed25519.rb', line 64

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)
  datab64 = datafull[MBEGIN.size ... -MEND.size]
  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

Class Method Details

.read(data, password) ⇒ Object



128
129
130
# File 'lib/net/ssh/authentication/ed25519.rb', line 128

def self.read(data,password)
  self.new(data,password)
end

.read_keyblob(buffer) ⇒ Object



132
133
134
# File 'lib/net/ssh/authentication/ed25519.rb', line 132

def self.read_keyblob(buffer)
  ED25519::PubKey.read_keyblob(buffer)
end

Instance Method Details

#public_keyObject



120
121
122
# File 'lib/net/ssh/authentication/ed25519.rb', line 120

def public_key
  PubKey.new(@pk)
end

#ssh_do_sign(data) ⇒ Object



124
125
126
# File 'lib/net/ssh/authentication/ed25519.rb', line 124

def ssh_do_sign(data)
  @sign_key.sign(data)
end