send public key with every message

this is more efficient and solves key distribution concerns
This commit is contained in:
Alain Zscheile 2022-11-26 23:41:53 +01:00
parent d8f2dc3e66
commit c48367ff09
9 changed files with 34 additions and 84 deletions

View file

@ -3,6 +3,7 @@ DEFINITIONS EXPLICIT TAGS ::= BEGIN
Signature ::= SEQUENCE {
algorithm OBJECT IDENTIFIER,
key OCTET STRING,
value OCTET STRING
}
Severity ::= ENUMERATED {
@ -38,9 +39,6 @@ XferInner ::= SEQUENCE {
}
XferBlob ::= SEQUENCE {
-- source system name --
source RDNSequence,
-- message max remaining hops
ttl INTEGER (0..255),

View file

@ -14,8 +14,6 @@ defmodule Floof.Application do
markers = Application.fetch_env!(:floof, :markers)
attrs = Application.fetch_env!(:floof, :attrs)
set_markers = Application.fetch_env!(:floof, :set_markers)
pubkey_mgr = Application.fetch_env!(:floof, :pubkey_mgr)
pubkey_config = Application.fetch_env!(:floof, :pubkey_config)
spool_dir = Application.fetch_env!(:floof, :spool_dir)
sessions_file = Application.fetch_env!(:floof, :sessions_file)
@ -30,9 +28,7 @@ defmodule Floof.Application do
Floof.Distributor.fconfig(
markers: markers,
attrs: attrs,
set_markers: set_markers,
pubkey_mgr: pubkey_mgr,
pubkey_config: pubkey_config
set_markers: set_markers
)},
{Floof.SessionManager, {:sessions, [file: to_charlist(sessions_file)]}}
] ++

View file

@ -12,9 +12,7 @@ defmodule Floof.Distributor do
Record.defrecord(:fconfig,
markers: [],
attrs: [],
set_markers: [],
pubkey_mgr: Floof.Distributor.PubkeyMgr.FileDB,
pubkey_config: %{:keydb => ""}
set_markers: []
)
Record.defrecord(:dstate, fconf: {}, trgs: MapSet.new())
@ -71,10 +69,10 @@ defmodule Floof.Distributor do
# spawn a separate process to avoid blocking the queue
# we only block the queue above for the check + seen marker
spawn_link(fn ->
{:XferBlob, source, ttl, old_markers, signature, data} = dcd
{:XferBlob, ttl, old_markers, signature, data} = dcd
set_markers = fconfig(fconf, :set_markers)
new_markers = Enum.uniq(set_markers ++ old_markers)
dcd2 = {:XferBlob, source, ttl - 1, new_markers, signature, data}
dcd2 = {:XferBlob, ttl - 1, new_markers, signature, data}
for trg <- trgs do
send(trg, {:fwdxfer, {dcdhash, dcd2}})
@ -93,40 +91,30 @@ defmodule Floof.Distributor do
end
defp check_incoming(fconf, dcdhash, dcd) do
{:XferBlob, source, ttl, _, {:Signature, sigalgo, sigval}, xfinner} = dcd
{:XferBlob, ttl, _, {:Signature, sigalgo, pubkey, sigval}, xfinner} = dcd
case sigalgo do
{1, 3, 6, 1, 4, 1, 11591, 15, 1} ->
# Ed25519
case get_pubkey(fconf, source) do
{:ok, :ed25519, pubkey} ->
cond do
Floof.DistributorSeen.have_we(dcdhash) ->
# we can ignore this packet, its content was already processed
false
not :enacl.sign_verify_detached(sigval, xfinner, pubkey) ->
Logger.error("packet signature invalid for #{inspect(xfinner)}")
false
ttl == 0 ->
Logger.warn("packet in processing expired (out of hops): #{inspect(xfinner)}")
false
not check_filters(fconf, dcd) ->
Logger.debug("packet discarded according to filters: #{inspect(xfinner)}")
false
true ->
true
end
_ ->
Logger.warn(
"unable to verify packet signature due to unknown signer: #{inspect(source)}"
)
cond do
Floof.DistributorSeen.have_we(dcdhash) ->
# we can ignore this packet, its content was already processed
false
not :enacl.sign_verify_detached(sigval, xfinner, pubkey) ->
Logger.error("packet signature invalid for #{inspect(xfinner)}")
false
ttl == 0 ->
Logger.warn("packet in processing expired (out of hops): #{inspect(xfinner)}")
false
not check_filters(fconf, dcd) ->
Logger.debug("packet discarded according to filters: #{inspect(xfinner)}")
false
true ->
true
end
_ ->
@ -138,7 +126,7 @@ defmodule Floof.Distributor do
end
end
defp check_filters(fconf, {:XferBlob, _, _, markers, _, xfinner}) do
defp check_filters(fconf, {:XferBlob, _, markers, _, xfinner}) do
try do
{:ok, {:XferInner, _, attrs, _, _}} = :FloofProtocol.decode(:XferInner, xfinner)
@ -171,8 +159,4 @@ defmodule Floof.Distributor do
defp check_filters_markers2([], _) do
true
end
defp get_pubkey(fconf, source) do
fconfig(fconf, :pubkey_mgr).get_pubkey(fconfig(fconf, :pubkey_config), source)
end
end

View file

@ -4,17 +4,18 @@ defmodule Floof.Message do
"""
def emit(xf) do
{:XferBlob, _, _, _, _, xfinner} = xf
{:XferBlob, _, _, _, xfinner} = xf
mhash = :crypto.hash(:blake2b, xfinner)
GenServer.cast(Floof.Distributor, {:xfer, {self(), mhash, xf}})
mhash
end
def sign(xf, secret_key) do
{:XferBlob, source, ttl, markers, _, xfinner} = xf
{:XferBlob, ttl, markers, _, xfinner} = xf
public_key = :enacl.crypto_sign_ed25519_sk_to_pk(secret_key)
signature = :enacl.sign_detached(xfinner, secret_key)
signature2 = {:Signature, {1, 3, 6, 1, 4, 1, 11591, 15, 1}, signature}
{:XferBlob, source, ttl, markers, signature2, xfinner}
signature2 = {:Signature, {1, 3, 6, 1, 4, 1, 11591, 15, 1}, public_key, signature}
{:XferBlob, ttl, markers, signature2, xfinner}
end
def pack_inner(topic, attrs, severity, data) do
@ -26,7 +27,7 @@ defmodule Floof.Message do
data
end
def build_outer(source, ttl, markers, secret_key, xfinner) do
{:XferBlob, source, ttl, markers, nil, xfinner} |> sign(secret_key)
def build_outer(ttl, markers, secret_key, xfinner) do
{:XferBlob, ttl, markers, nil, xfinner} |> sign(secret_key)
end
end

View file

@ -1,24 +0,0 @@
defmodule Floof.PubkeyMgr do
@callback get_pubkey(any(), [{:RelativeDistinguishedName, any(), any()}]) ::
{:ok, :ed25519, binary()} | :error
end
defmodule Floof.PubkeyMgr.FileDB do
@behaviour Floof.PubkeyMgr
def get_pubkey(config, source) do
keydb = config.keydb
if keydb == "" do
:error
else
{:ok, encname} = :FloofProtocol.encode(:RDNSequence, source)
keypath = keydb <> "/" <> Base.url_encode64(encname)
case File.read(keypath) do
{:ok, data} -> {:ok, :ed25519, data}
{:error, _} -> :error
end
end
end
end

View file

@ -34,10 +34,7 @@ defmodule Floof.MixProject do
# these are the markers of form {:RelativeDistinguishedName, oid-as-list(), value()}
# which get added to all processed messages
set_markers: [],
pubkey_mgr: Floof.PubkeyMgr.FileDB,
# file locations
# the keydb is only read, and is used to check message signatures
pubkey_config: %{:keydb => "mock_keydb"},
# the spool dir saves messages in-transit, and is used to prevent RAM OOM
spool_dir: "mock_spool",
# the sessions file is used for persistence of session data across restarts

View file

@ -1 +0,0 @@
÷"a?ÿ0ïëôÞò]²±“Î}<7D>MZÝ—úM

View file

@ -8,11 +8,10 @@ defmodule FloofTest do
# {:ok, pkname} = :FloofProtocol.encode(:RDNSequence, [{:RelativeDistinguishedName, {0, 9, 2342, 19200300, 100, 1, 25}, "test"}])
# :ok = File.write("mock_keydb/" <> Base.url_encode64(pkname), kp.public)
{:ok, secret_key} = File.read("mock_keydb/test01.secret")
source = [{:RelativeDistinguishedName, {0, 9, 2342, 19_200_300, 100, 1, 25}, "test"}]
{:ok, secret_key} = File.read("test/test01.secret")
msg_topic = [{:RelativeDistinguishedName, {2, 5, 4, 41}, "test topic"}]
msg_inner = Floof.Message.pack_inner(msg_topic, [], :info, <<0, 0>>)
msg_outer = Floof.Message.build_outer(source, 10, [], secret_key, msg_inner)
msg_outer = Floof.Message.build_outer(10, [], secret_key, msg_inner)
{:ok, msg_encd} = :FloofProtocol.encode(:ProtoMessage, {:xfer, msg_outer})
Floof.Distributor.register(self())