Skip to content

Commit

Permalink
Add function Ownership.validate_format
Browse files Browse the repository at this point in the history
  • Loading branch information
Neylix committed Sep 14, 2023
1 parent 2ff1b8b commit 62e13f3
Show file tree
Hide file tree
Showing 6 changed files with 781 additions and 928 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -192,28 +192,25 @@ defmodule Archethic.Contracts.Interpreter.Legacy.TransactionStatements do
decoded_pub = UtilsInterpreter.get_public_key(pub, :add_ownership)
decoded_key = UtilsInterpreter.maybe_decode_hex(key)

if byte_size(decoded_key) != 80,
do: raise(Library.Error, message: "Encrypted key is not valid")

{decoded_pub, UtilsInterpreter.maybe_decode_hex(key)}
{decoded_pub, decoded_key}
end)
|> Enum.into(%{})

secret = UtilsInterpreter.maybe_decode_hex(secret)

if byte_size(secret) != 32,
do: raise(Library.Error, message: "Secret is not valid")
ownership = %Ownership{secret: secret, authorized_keys: authorized_keys}

ownership = %Ownership{
secret: secret,
authorized_keys: authorized_keys
}
case Ownership.validate_format(ownership) do
:ok ->
update_in(
tx,
[Access.key(:data, %{}), Access.key(:ownerships, [])],
&(&1 ++ [ownership])
)

update_in(
tx,
[Access.key(:data, %{}), Access.key(:ownerships, [])],
&(&1 ++ [ownership])
)
{:error, reason} ->
raise Library.Error, message: Atom.to_string(reason) |> String.replace("_", " ")
end
end

@doc """
Expand Down
42 changes: 9 additions & 33 deletions lib/archethic/mining/pending_transaction_validation.ex
Original file line number Diff line number Diff line change
Expand Up @@ -173,39 +173,15 @@ defmodule Archethic.Mining.PendingTransactionValidation do
defp validate_ownerships(%Transaction{data: %TransactionData{ownerships: []}}), do: :ok

defp validate_ownerships(%Transaction{data: %TransactionData{ownerships: ownerships}}) do
Enum.reduce_while(ownerships, :ok, fn
%Ownership{secret: secret, authorized_keys: authorized_keys}, :ok ->
cond do
secret == "" ->
{:halt, {:error, "Ownership: secret is empty"}}

authorized_keys == %{} ->
{:halt, {:error, "Ownership: authorized keys are empty"}}

true ->
verify_authorized_keys(authorized_keys)
end
end)
end

@spec verify_authorized_keys(authorized_keys :: map()) ::
{:cont, :ok} | {:halt, {:error, any()}}
defp verify_authorized_keys(authorized_keys) do
# authorized_keys: %{(public_key :: Crypto.key()) => encrypted_key }

Enum.reduce_while(authorized_keys, {:cont, :ok}, fn
{"", _}, _ ->
e = {:halt, {:error, "Ownership: public key is empty"}}
{:halt, e}

{_, ""}, _ ->
e = {:halt, {:error, "Ownership: encrypted key is empty"}}
{:halt, e}

{public_key, _}, acc ->
if Crypto.valid_public_key?(public_key),
do: {:cont, acc},
else: {:halt, {:halt, {:error, "Ownership: invalid public key"}}}
Enum.reduce_while(ownerships, :ok, fn ownership, :ok ->
case Ownership.validate_format(ownership) do
:ok ->
{:cont, :ok}

{:error, reason} ->
formated_reason = "Ownership: #{Atom.to_string(reason) |> String.replace("_", " ")}"
{:halt, {:error, formated_reason}}
end
end)
end

Expand Down
78 changes: 78 additions & 0 deletions lib/archethic/transaction_chain/transaction/data/ownership.ex
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,82 @@ defmodule Archethic.TransactionChain.TransactionData.Ownership do
when is_binary(public_key) do
Map.get(auth_keys, public_key)
end

@doc """
Verify if the data format in the ownerships is valid (public key and encrypted key)
## Examples
iex> secret = random_secret()
...> {pub, _} = Crypto.derive_keypair(:crypto.strong_rand_bytes(32), 0, :ed25519)
...> authorized_keys = %{pub => random_encrypted_key(pub)}
...> %Ownership{secret: secret, authorized_keys: authorized_keys}
...> |> Ownership.validate_format()
:ok
iex> secret = random_secret()
...> {pub, _} = Crypto.derive_keypair(:crypto.strong_rand_bytes(32), 0, :secp256k1)
...> authorized_keys = %{pub => random_encrypted_key(pub)}
...> %Ownership{secret: secret, authorized_keys: authorized_keys}
...> |> Ownership.validate_format()
:ok
iex> secret = ""
...> {pub, _} = Crypto.derive_keypair(:crypto.strong_rand_bytes(32), 0, :ed25519)
...> authorized_keys = %{pub => :crypto.strong_rand_bytes(80)}
...> %Ownership{secret: secret, authorized_keys: authorized_keys}
...> |> Ownership.validate_format()
{:error, :empty_secret}
iex> secret = random_secret()
...> authorized_keys = %{}
...> %Ownership{secret: secret, authorized_keys: authorized_keys}
...> |> Ownership.validate_format()
{:error, :empty_authorized_keys}
iex> secret = random_secret()
...> {pub, _} = Crypto.derive_keypair(:crypto.strong_rand_bytes(32), 0, :ed25519)
...> authorized_keys = %{pub => :crypto.strong_rand_bytes(55)}
...> %Ownership{secret: secret, authorized_keys: authorized_keys}
...> |> Ownership.validate_format()
{:error, :invalid_encrypted_key}
iex> secret = random_secret()
...> authorized_keys = %{:crypto.strong_rand_bytes(20) => :crypto.strong_rand_bytes(80)}
...> %Ownership{secret: secret, authorized_keys: authorized_keys}
...> |> Ownership.validate_format()
{:error, :invalid_public_key}
"""
@spec validate_format(ownership :: t()) ::
:ok
| {:error,
:empty_secret | :empty_authorized_keys | :invalid_public_key | :invalid_encrypted_key}
def validate_format(%__MODULE__{secret: ""}), do: {:error, :empty_secret}

def validate_format(%__MODULE__{authorized_keys: authorized_keys})
when map_size(authorized_keys) == 0,
do: {:error, :empty_authorized_keys}

def validate_format(%__MODULE__{authorized_keys: authorized_keys}) do
Enum.reduce_while(authorized_keys, :ok, fn {public_key, encrypted_key}, _acc ->
with :ok <- validate_public_key(public_key),
:ok <- validate_encrypted_key(public_key, encrypted_key) do
{:cont, :ok}
else
error -> {:halt, error}
end
end)
end

defp validate_public_key(public_key) do
if Crypto.valid_public_key?(public_key) do
:ok
else
{:error, :invalid_public_key}
end
end

defp validate_encrypted_key(<<0::8, _rest::binary>>, <<_encrypted_key::binary-80>>), do: :ok
defp validate_encrypted_key(_public_key, <<_encrypted_key::binary-113>>), do: :ok
defp validate_encrypted_key(_, _), do: {:error, :invalid_encrypted_key}
end
Loading

0 comments on commit 62e13f3

Please sign in to comment.