Hi everyone,
I’m trying to start an SSH daemon in Elixir using :ssh.daemon/2,3
, and I want to dynamically generate an SSH host key instead of relying on a pre-existing key file.
I initially tried to do in elixir
defmodule MyWeb.SFTPServer do
def start do
port = 8989
sftp_dir = Path.join(System.tmp_dir!(), "sftp_dir")
File.mkdir(sftp_dir)
opts = [
{:key_cb, {KeyCallback, []}},
{:system_dir, to_charlist("/tmp")},
{:user_passwords, [{~c"user", ~c"password"}]},
{:subsystems, [:ssh_sftpd.subsystem_spec([{:root, to_charlist(sftp_dir)}])]}
]
:ssh.daemon(port, opts)
end
end
defmodule KeyCallback do
@moduledoc false
@behaviour :ssh_server_key_api
@impl :ssh_server_key_api
def host_key(:rsa, _damon_options) do
{private_key, _} = generate_key()
IO.inspect(private_key)
{:ok, private_key}
end
@impl :ssh_server_key_api
def is_auth_key(_publicKey, _user, _daemon_options) do
true
end
defp generate_key do
# http://erlang.org/doc/apps/public_key/public_key_records.html#rsa
{:RSAPrivateKey, _version, modulus, public_exponent, _private_exponent, _prime1, _prime2,
_exponent1, _exponent2, _coefficient,
_other_primeInfos} = rsa_private_key = :public_key.generate_key({:rsa, 2048, 65537})
rsa_public_key = {:RSAPublicKey, modulus, public_exponent}
rsa_private_key_pem_entry = :public_key.pem_entry_encode(:RSAPrivateKey, rsa_private_key)
rsa_public_key_pem_entry = :public_key.pem_entry_encode(:RSAPublicKey, rsa_public_key)
pem_out_public = :public_key.pem_encode([rsa_public_key_pem_entry])
pem_out_private = :public_key.pem_encode([rsa_private_key_pem_entry])
{pem_out_private, pem_out_public}
end
end
However, I am unsure how to pass the generated key to :ssh.daemon/2,3
as an option.
- Am I generating the key correctly for use with
:ssh.daemon/2,3
? - How can I pass the generated key to
:ssh.daemon/2,3
so that it does not require a file-based key?
I appreciate any guidance on this!