This repository has been archived by the owner on Oct 30, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
organized keymaterials + entry function for keypair generation
- Loading branch information
Showing
14 changed files
with
245 additions
and
84 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
defmodule ExUcan.Core.Capability do | ||
Check warning on line 1 in lib/ex_ucan/core/capability/data.ex GitHub Actions / Build and test (1.15.7, 26.0.2)
|
||
# TODO: All the docs needed | ||
@type t :: %__MODULE__{ | ||
resource: String.t(), | ||
ability: String.t(), | ||
caveat: list(map()) | ||
} | ||
defstruct [:resource, :ability, :caveat] | ||
|
||
@spec new(String.t(), String.t(), list()) :: __MODULE__.t() | ||
def new(resource, ability, caveat) do | ||
%__MODULE__{ | ||
resource: resource, | ||
ability: ability, | ||
caveat: caveat | ||
} | ||
end | ||
end | ||
|
||
defmodule ExUcan.Core.Capabilities do | ||
@moduledoc """ | ||
Capabilities always deals with capabilites as map of maps | ||
map<String: map<String: list()>> | ||
""" | ||
alias ExUcan.Core.Capability | ||
# TODO: All the docs needed | ||
|
||
# def validate(capabilities) when is_map(capabilities) do | ||
# capabilities | ||
# |> Enum.reduce_while(%{}, fn {resource, ability}, caps -> | ||
# # ability should be map | ||
# # iter through ability | ||
|
||
# end) | ||
# end | ||
|
||
def validate(_), do: {:error, "Capabilities must be an object."} | ||
|
||
@spec map_to_sequence(map()) :: list(Capability.t()) | ||
def map_to_sequence(capabilities) do | ||
capabilities | ||
|> Enum.reduce([], fn {resource, ability}, caps -> | ||
[{ability, caveat}] = Map.to_list(ability) | ||
caps ++ [Capability.new(resource, ability, caveat)] | ||
end) | ||
end | ||
|
||
@spec sequence_to_map(list(Capability.t())) :: map() | ||
def sequence_to_map(capabilites) do | ||
capabilites | ||
|> Enum.reduce(%{}, fn %Capability{} = cap, caps -> | ||
Map.put(caps, cap.resource, %{cap.ability => cap.caveat}) | ||
end) | ||
end | ||
end |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
4 changes: 2 additions & 2 deletions
4
lib/ex_ucan/plugins/ed25519/crypto.ex → lib/ex_ucan/keymaterial/ed25519/crypto.ex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
defmodule ExUcan.Keymaterial.Ed25519.Keypair do | ||
@moduledoc """ | ||
Encapsulates Ed25519 Keypair generation and implements `Keymaterial` protocol | ||
""" | ||
|
||
alias ExUcan.Keymaterial | ||
alias ExUcan.Keymaterial.Ed25519.Crypto | ||
|
||
@typedoc """ | ||
A Keypair struct holds the generate keypairs and its metadata | ||
jwt_alg - JWT algorith used, ex: edDSA, HMAC etc.. | ||
secret_key - Private key bytes | ||
public_key - Public key bytes | ||
""" | ||
@type t :: %__MODULE__{ | ||
jwt_alg: String.t(), | ||
secret_key: binary(), | ||
public_key: binary() | ||
} | ||
|
||
defstruct [:jwt_alg, :secret_key, :public_key] | ||
|
||
@doc """ | ||
Creates a keypair with EdDSA algorithm | ||
This keypair can be later used for create UCAN tokens | ||
""" | ||
@spec create() :: __MODULE__.t() | ||
def create() do | ||
{pub, priv} = :crypto.generate_key(:eddsa, :ed25519) | ||
|
||
%__MODULE__{ | ||
jwt_alg: "EdDSA", | ||
secret_key: priv, | ||
public_key: pub | ||
} | ||
end | ||
|
||
defimpl Keymaterial do | ||
def get_jwt_algorithm_name(keypair) do | ||
keypair.jwt_alg | ||
end | ||
|
||
def get_did(keypair) do | ||
Crypto.publickey_to_did(keypair.public_key) | ||
end | ||
|
||
def sign(keypair, payload) do | ||
:public_key.sign( | ||
payload, | ||
:ignored, | ||
{:ed_pri, :ed25519, keypair.public_key, keypair.secret_key}, | ||
[] | ||
) | ||
end | ||
|
||
def verify(keypair, payload, signature) do | ||
:public_key.verify(payload, :ignored, signature, {:ed_pub, :ed25519, keypair.public_key}) | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
defprotocol ExUcan.Keymaterial do | ||
@moduledoc """ | ||
Keymaterial protocol used by Keypair generation modules like `ExUcan.Keymaterial.Ed25519.Keypair` | ||
This protocol requires four functions to be implemented, `get_jwt_algorithm_name/1`, | ||
`get_did/1`, `sign/2` and `verify/3` | ||
""" | ||
alias ExUcan.Core.Structs.UcanPayload | ||
|
||
@doc """ | ||
Returns the Jwt algorithm used by the Keypair to create Ucan | ||
""" | ||
@spec get_jwt_algorithm_name(any()) :: String.t() | ||
def get_jwt_algorithm_name(type) | ||
|
||
@doc """ | ||
Retursn the did (Decentralized Identifiers) generated using the keypair | ||
""" | ||
@spec get_did(any()) :: String.t() | ||
def get_did(type) | ||
|
||
@doc """ | ||
Creates signature on the given payload with the keypair | ||
""" | ||
@spec sign(any(), binary()) :: binary() | ||
def sign(type, payload) | ||
|
||
@doc """ | ||
Verifies the signature with the keypair | ||
""" | ||
@spec verify(any(), binary(), binary()) :: boolean() | ||
def verify(type, payload, signature) | ||
end |
2 changes: 1 addition & 1 deletion
2
lib/ex_ucan/plugins/utils.ex → lib/ex_ucan/keymaterial/utils.ex
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
defmodule CapabilityTest do | ||
alias ExUcan.Core.Capabilities | ||
alias ExUcan.Core.Capability | ||
use ExUnit.Case | ||
|
||
@tag :caps | ||
test "can_cast_between_map_and_sequence" do | ||
cap_foo = Capability.new("example//foo", "ability/foo", %{}) | ||
assert cap_foo.caveat == %{} | ||
cap_bar = Capability.new("example://bar", "ability/bar", %{"beep" => 1}) | ||
|
||
cap_sequence = [cap_foo, cap_bar] | ||
|
||
cap_maps = Capabilities.sequence_to_map(cap_sequence) | ||
assert Capabilities.map_to_sequence(cap_maps) == cap_sequence | ||
end | ||
|
||
test "it_rejects_non_compliant_json" do | ||
failure_cases = [ | ||
{ | ||
[], | ||
"resources must be map" | ||
}, | ||
{ | ||
%{"resource:foo" => []}, | ||
"abilities must be map" | ||
}, | ||
{ | ||
%{"resource:foo" => {}}, | ||
"resource must have at least one ability" | ||
}, | ||
{ | ||
%{"resource:foo" => %{"ability/read" => %{}}}, | ||
"caveats must be a list" | ||
}, | ||
{ | ||
%{"resource:foo" => %{"ability/read" => [1]}}, | ||
"caveat must be object" | ||
} | ||
] | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,8 +1,11 @@ | ||
defmodule ExUcanTest do | ||
alias ExUcan.Keymaterial.Ed25519.Keypair | ||
use ExUnit.Case | ||
doctest ExUcan | ||
|
||
test "greets the world" do | ||
assert ExUcan.hello() == :world | ||
test "create_default_keypair" do | ||
assert %Keypair{jwt_alg: "EdDSA"} = keypair = Keypair.create() | ||
assert is_binary(keypair.public_key) | ||
assert is_binary(keypair.secret_key) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
defmodule Keymaterial.KeypairTest do | ||
alias ExUcan.Keymaterial.Ed25519.Keypair | ||
alias ExUcan.Keymaterial | ||
use ExUnit.Case | ||
|
||
test "creating edDSA keypair" do | ||
assert %Keypair{jwt_alg: "EdDSA"} = keypair = Keypair.create() | ||
assert is_binary(keypair.public_key) | ||
assert is_binary(keypair.secret_key) | ||
end | ||
|
||
test "testing success keymaterial implementation" do | ||
assert %Keypair{jwt_alg: "EdDSA"} = keypair = Keypair.create() | ||
assert Keymaterial.get_jwt_algorithm_name(keypair) == "EdDSA" | ||
assert "did:key:z" <> _ = Keymaterial.get_did(keypair) | ||
signature = Keymaterial.sign(keypair, "Hello world") | ||
assert is_binary(signature) | ||
assert Keymaterial.verify(keypair, "Hello world", signature) | ||
end | ||
|
||
test "testing failed cases, keymaterial implementations" do | ||
assert %Keypair{jwt_alg: "EdDSA"} = keypair = Keypair.create() | ||
assert Keymaterial.get_jwt_algorithm_name(keypair) == "EdDSA" | ||
assert "did:key:z" <> _ = Keymaterial.get_did(keypair) | ||
signature = Keymaterial.sign(keypair, "Hello world") | ||
assert is_binary(signature) | ||
refute Keymaterial.verify(keypair, "Hell world", signature) | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1,2 @@ | ||
ExUnit.start() | ||
ExUnit.configure(exclude: [:skip]) |