From 2c4869c294a887692b8c8a35c9d0b69df8ffc4bd Mon Sep 17 00:00:00 2001 From: mycognosist Date: Mon, 19 Sep 2022 16:38:04 +0100 Subject: [PATCH 01/18] add encoders for blob, bool and box --- lib/ssb_bfe/encoder.ex | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/ssb_bfe/encoder.ex b/lib/ssb_bfe/encoder.ex index 1dca7cd..d5406d3 100644 --- a/lib/ssb_bfe/encoder.ex +++ b/lib/ssb_bfe/encoder.ex @@ -1,5 +1,22 @@ +# might be good to use a multiclause function for the `encode` function +# - use the `where` conditional guard with e.g. `is_number` + defmodule SsbBfe.Encoder do - def encode_bool(blob_id) do - # Enum.sum(list) / Kernel.length(list) + def encode_blob(blob_id) do + blob_tf_tag = SsbBfe.Types.get_blob_type(blob_id) + base64_data = String.slice(blob_id, 1, 44) + {:ok, decoded_base64_data} = Base.decode64(base64_data) + blob_tf_tag <> decoded_base64_data + end + + def encode_bool(true), do: <<6, 1, 1>> + + def encode_bool(false), do: <<6, 1, 0>> + + def encode_box(box_str) do + box_tf_tag = SsbBfe.Types.get_box_type(box_str) + [base64_data, _] = String.split(box_str, ".") + {:ok, decoded_base64_data} = Base.decode64(base64_data) + box_tf_tag <> decoded_base64_data end end From 8535fa1fa279114926cb36c4b15608514e3fcded Mon Sep 17 00:00:00 2001 From: mycognosist Date: Mon, 19 Sep 2022 16:39:11 +0100 Subject: [PATCH 02/18] add basic tests for types plus blob, bool and box encoding --- test/ssb_bfe_encoder_test.exs | 27 +++++++++++++++++++++++++++ test/ssb_bfe_types_test.exs | 15 +++++++++++++++ 2 files changed, 42 insertions(+) create mode 100644 test/ssb_bfe_encoder_test.exs create mode 100644 test/ssb_bfe_types_test.exs diff --git a/test/ssb_bfe_encoder_test.exs b/test/ssb_bfe_encoder_test.exs new file mode 100644 index 0000000..46df33b --- /dev/null +++ b/test/ssb_bfe_encoder_test.exs @@ -0,0 +1,27 @@ +defmodule SsbBfeEncoderTest do + use ExUnit.Case + + @blob_id "&S7+CwHM6dZ9si5Vn4ftpk/l/ldbRMqzzJos+spZbWf4=.sha256" + @box1_msg "siZEm1zFx1icq0SrEynGDpNRmJCXMxTB3iEteXFn+IhJH8WhMbT8tp9qOIaFkIYcdOyerSon6RK0l4RE1ZdDh/3lcGZSdP0Ljq59qsdqlf2ngwbIbV9AWdPRrPsoVZBV6RhI+YcVTloWWP5aauu1hZKjcm62ezLBTQ3EmFPYtDuwsOFkx9/7FP97ljhj67CwvlGzuiWp6FNICHbt5kOCxs9H0k6Tr8JJVdaJtJ2pqkX4p0ECMuEuYxCYbh3FpncCqlNZJXb0dj3iSsfsMNWTJLDqfkqJKH1jBVfxDL6+xAXBDS+E4F2hD4y9gRDZEej99uVBQWlbxr5eCRV+VbfBGYxwoAYtqux6rg3jBabImKKinBwHShEP5F/+wlb9IxQn4swyOgyv+UKx/jbx+91Ayso5bnNPZMpwRRX5p5DbpK1BnryeVJhktMgFqgni1g0lHyU8sQ2QzwZgXGw7dfYoamkqK4D24NOLnUoHuVuhd7Q5SxZWSAO6wpDa4nrODePoJdl328pbMwCoQlUNeHINmKxh/o/oCNbgXitn4oN3kSVEg/umdgwwI94gmZUjiYwP1v7HA7dI.box" + @box2_msg "WQyfhDDHQ1gH34uppHbj8SldRu8hD2764gQ6TAhaVp6R01EMBnJQj5ewD5F+UT5NwvV91uU8q5XCjuvcP4ihCJ0RtX8HjKyN+tDKP5gKB3UZo/eO/rP5CcPGoIG7pcLBsd3DQbZLfTnb/iqECEji9gclNcGENTS2u6aATwbQ4uQ7RzIAKKT2NfC2qk86p/gXC2owDFAazuPlQTT8DMNvO8G52gb48a75CGKsDAevrC//Bz38VFxwUiTKzRWaxCbTK9knj39u3qoCP9VLyyRqITgNwvlGLP7ndchTyBiO0TPNkb9PAOenw5WBjyWhA61hpG+VkKpkaysBVGjXYv8OpV1HGbs87TI79uT7JrNV4wEZiwqGknwmCi5B2gbd7tav8yDXsK5yQgDncHQjZotsBFX2adP7Jli9WmvV3xX5lL3kBNKV0ZiE/DZUgB2m1OXvCjNI4fuZhnpZpEQi9coO+icrirKiH/UA8TS9HI72cIbkEJVxOTnKnsgr3Qc/5HhtRS17a54ymVmBsnpP+KqqCqKLN50TInb7qoUlvQ2nw07xX3Ig9usLb8Ik8U8XMb6SLqACxlZN/qW4EJzxVetoIk84AU1yLInK6v9dzfsewRYBXW8+lYbyxVNuIIK4pKYsx2WbjuJyZHgjgbCdGf/kjqP5rDs4zwqj2lmkO70PoEUrcSi46J2hkqtcrd1yl+F3/BDwFlxAXH+x4+LhmT7g+BSgzRUbWvCyeB+HJaoao6g4K/Fs8HxnbVB1zW761OQJaQnV86ZThkvUjXh2SEBlBd+D94eUCqIJkjI7RLt+D/0gxg/D7u1Zq14UxRijZryB51An7GdXtEc2xhU+Bh/aPmKmMZ9D/ArdglSlnVUD8OIBVVw5jtooGlhxbOFHM4N5SoAO/yWPcbcuQz7t4SPij358rY574DLBGZEPCrS6KPpnrlqlnZK4f6/+9zv3hfzNTXVvJtxZL/rvmNvbgh7LpMnSqjnsXqm86a3GXeVWD83TdCnL1oPqEi/8RItTrjy01DmVhUoV6t12STP4mHb8RjR+/ks+7lowfV3HQ13n6if0g0/u+Bzv6XXOX6iePPOHA3lFv2MSPKf9JZ0uQiqajR03YkNE8YnSTYu0Io1cGPZ/lWBp2tyWtwFmGtqw/9+O165tJhrdU2EXJ4T/XP136WpLD2+vtYsx3Xr5lfeD12/g+I/6jwduqTuHpst2tqvcSWoZ4DAWcpcKJ1mUbJU3/mLAYGwWb3XuqMOgJOLoztAwd5xFzUZD1MnR/iyYoZ2weYTSOz3OKR3cJyCjxBhIGaX5xpAc61K1dXNfERBJr9TS0mL2578dd5AauE6Ksn6YlGxNJIVC3VpdAtRbVHNX1g==.box2" + + test "encode_blob_works" do + encoded_blob = SsbBfe.Encoder.encode_blob(@blob_id) + assert encoded_blob == <<2, 0, 75, 191, 130, 192, 115, 58, 117, 159, 108, 139, 149, 103, 225, 251, 105, 147, 249, 127, 149, 214, 209, 50, 172, 243, 38, 139, 62, 178, 150, 91, 89, 254>> + end + + test "encode_bool_works" do + assert SsbBfe.Encoder.encode_bool(true) == <<6, 1, 1>> + assert SsbBfe.Encoder.encode_bool(false) == <<6, 1, 0>> + end + + test "encode_box1_works" do + encoded_box1 = SsbBfe.Encoder.encode_box(@box1_msg) + assert String.starts_with?(encoded_box1, <<5, 0>>) + end + + test "encode_box2_works" do + encoded_box2 = SsbBfe.Encoder.encode_box(@box2_msg) + assert String.starts_with?(encoded_box2, <<5, 1>>) + end +end diff --git a/test/ssb_bfe_types_test.exs b/test/ssb_bfe_types_test.exs new file mode 100644 index 0000000..1ff227e --- /dev/null +++ b/test/ssb_bfe_types_test.exs @@ -0,0 +1,15 @@ +defmodule SsbBfeTypesTest do + use ExUnit.Case + + test "get_blob_type_matches_classic" do + blob_id = "&S7+CwHM6dZ9si5Vn4ftpk/l/ldbRMqzzJos+spZbWf4=.sha256" + blob_type = SsbBfe.Types.get_blob_type(blob_id) + assert blob_type == <<2, 0>> + end + + test "get_blob_type_matches_unknown" do + blob_id = "&what.is_this" + blob_type = SsbBfe.Types.get_blob_type(blob_id) + assert blob_type == nil + end +end From 056d34104f62196061870e0b9c5b7f2d505e118a Mon Sep 17 00:00:00 2001 From: mycognosist Date: Mon, 19 Sep 2022 16:39:48 +0100 Subject: [PATCH 03/18] update manifest --- mix.exs | 1 + 1 file changed, 1 insertion(+) diff --git a/mix.exs b/mix.exs index bdcf03d..382a9d0 100644 --- a/mix.exs +++ b/mix.exs @@ -23,6 +23,7 @@ defmodule SsbBfe.MixProject do [ # {:dep_from_hexpm, "~> 0.3.0"}, # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"} + {:poison, "~> 5.0"} ] end end From 9c75595755ccb0e5e016bebe577ba9847e78bf18 Mon Sep 17 00:00:00 2001 From: glyph Date: Mon, 19 Sep 2022 17:58:58 +0100 Subject: [PATCH 04/18] add encoders for classic feed and message types --- lib/ssb_bfe/encoder.ex | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/lib/ssb_bfe/encoder.ex b/lib/ssb_bfe/encoder.ex index d5406d3..31f3910 100644 --- a/lib/ssb_bfe/encoder.ex +++ b/lib/ssb_bfe/encoder.ex @@ -2,10 +2,14 @@ # - use the `where` conditional guard with e.g. `is_number` defmodule SsbBfe.Encoder do + defp extract_base64_data(str) do + base64_data = String.slice(str, 1, 44) + Base.decode64(base64_data) + end + def encode_blob(blob_id) do blob_tf_tag = SsbBfe.Types.get_blob_type(blob_id) - base64_data = String.slice(blob_id, 1, 44) - {:ok, decoded_base64_data} = Base.decode64(base64_data) + {:ok, decoded_base64_data} = extract_base64_data(blob_id) blob_tf_tag <> decoded_base64_data end @@ -19,4 +23,16 @@ defmodule SsbBfe.Encoder do {:ok, decoded_base64_data} = Base.decode64(base64_data) box_tf_tag <> decoded_base64_data end + + def encode_feed(feed_id) do + feed_tf_tag = SsbBfe.Types.get_feed_type(feed_id) + {:ok, decoded_base64_data} = extract_base64_data(feed_id) + feed_tf_tag <> decoded_base64_data + end + + def encode_msg(msg_id) do + msg_tf_tag = SsbBfe.Types.get_msg_type(msg_id) + {:ok, decoded_base64_data} = extract_base64_data(msg_id) + msg_tf_tag <> decoded_base64_data + end end From 53a3369d62ca3e5efb41f16ed2a880192941dea5 Mon Sep 17 00:00:00 2001 From: glyph Date: Mon, 19 Sep 2022 17:59:42 +0100 Subject: [PATCH 05/18] add tests for classic feed and message encoding --- test/ssb_bfe_encoder_test.exs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/test/ssb_bfe_encoder_test.exs b/test/ssb_bfe_encoder_test.exs index 46df33b..acdd692 100644 --- a/test/ssb_bfe_encoder_test.exs +++ b/test/ssb_bfe_encoder_test.exs @@ -4,6 +4,8 @@ defmodule SsbBfeEncoderTest do @blob_id "&S7+CwHM6dZ9si5Vn4ftpk/l/ldbRMqzzJos+spZbWf4=.sha256" @box1_msg "siZEm1zFx1icq0SrEynGDpNRmJCXMxTB3iEteXFn+IhJH8WhMbT8tp9qOIaFkIYcdOyerSon6RK0l4RE1ZdDh/3lcGZSdP0Ljq59qsdqlf2ngwbIbV9AWdPRrPsoVZBV6RhI+YcVTloWWP5aauu1hZKjcm62ezLBTQ3EmFPYtDuwsOFkx9/7FP97ljhj67CwvlGzuiWp6FNICHbt5kOCxs9H0k6Tr8JJVdaJtJ2pqkX4p0ECMuEuYxCYbh3FpncCqlNZJXb0dj3iSsfsMNWTJLDqfkqJKH1jBVfxDL6+xAXBDS+E4F2hD4y9gRDZEej99uVBQWlbxr5eCRV+VbfBGYxwoAYtqux6rg3jBabImKKinBwHShEP5F/+wlb9IxQn4swyOgyv+UKx/jbx+91Ayso5bnNPZMpwRRX5p5DbpK1BnryeVJhktMgFqgni1g0lHyU8sQ2QzwZgXGw7dfYoamkqK4D24NOLnUoHuVuhd7Q5SxZWSAO6wpDa4nrODePoJdl328pbMwCoQlUNeHINmKxh/o/oCNbgXitn4oN3kSVEg/umdgwwI94gmZUjiYwP1v7HA7dI.box" @box2_msg "WQyfhDDHQ1gH34uppHbj8SldRu8hD2764gQ6TAhaVp6R01EMBnJQj5ewD5F+UT5NwvV91uU8q5XCjuvcP4ihCJ0RtX8HjKyN+tDKP5gKB3UZo/eO/rP5CcPGoIG7pcLBsd3DQbZLfTnb/iqECEji9gclNcGENTS2u6aATwbQ4uQ7RzIAKKT2NfC2qk86p/gXC2owDFAazuPlQTT8DMNvO8G52gb48a75CGKsDAevrC//Bz38VFxwUiTKzRWaxCbTK9knj39u3qoCP9VLyyRqITgNwvlGLP7ndchTyBiO0TPNkb9PAOenw5WBjyWhA61hpG+VkKpkaysBVGjXYv8OpV1HGbs87TI79uT7JrNV4wEZiwqGknwmCi5B2gbd7tav8yDXsK5yQgDncHQjZotsBFX2adP7Jli9WmvV3xX5lL3kBNKV0ZiE/DZUgB2m1OXvCjNI4fuZhnpZpEQi9coO+icrirKiH/UA8TS9HI72cIbkEJVxOTnKnsgr3Qc/5HhtRS17a54ymVmBsnpP+KqqCqKLN50TInb7qoUlvQ2nw07xX3Ig9usLb8Ik8U8XMb6SLqACxlZN/qW4EJzxVetoIk84AU1yLInK6v9dzfsewRYBXW8+lYbyxVNuIIK4pKYsx2WbjuJyZHgjgbCdGf/kjqP5rDs4zwqj2lmkO70PoEUrcSi46J2hkqtcrd1yl+F3/BDwFlxAXH+x4+LhmT7g+BSgzRUbWvCyeB+HJaoao6g4K/Fs8HxnbVB1zW761OQJaQnV86ZThkvUjXh2SEBlBd+D94eUCqIJkjI7RLt+D/0gxg/D7u1Zq14UxRijZryB51An7GdXtEc2xhU+Bh/aPmKmMZ9D/ArdglSlnVUD8OIBVVw5jtooGlhxbOFHM4N5SoAO/yWPcbcuQz7t4SPij358rY574DLBGZEPCrS6KPpnrlqlnZK4f6/+9zv3hfzNTXVvJtxZL/rvmNvbgh7LpMnSqjnsXqm86a3GXeVWD83TdCnL1oPqEi/8RItTrjy01DmVhUoV6t12STP4mHb8RjR+/ks+7lowfV3HQ13n6if0g0/u+Bzv6XXOX6iePPOHA3lFv2MSPKf9JZ0uQiqajR03YkNE8YnSTYu0Io1cGPZ/lWBp2tyWtwFmGtqw/9+O165tJhrdU2EXJ4T/XP136WpLD2+vtYsx3Xr5lfeD12/g+I/6jwduqTuHpst2tqvcSWoZ4DAWcpcKJ1mUbJU3/mLAYGwWb3XuqMOgJOLoztAwd5xFzUZD1MnR/iyYoZ2weYTSOz3OKR3cJyCjxBhIGaX5xpAc61K1dXNfERBJr9TS0mL2578dd5AauE6Ksn6YlGxNJIVC3VpdAtRbVHNX1g==.box2" + @classic_feed "@d/zDvFswFbQaYJc03i47C9CgDev+/A8QQSfG5l/SEfw=.ed25519" + @classic_msg "%R8heq/tQoxEIPkWf0Kxn1nCm/CsxG2CDpUYnAvdbXY8=.sha256" test "encode_blob_works" do encoded_blob = SsbBfe.Encoder.encode_blob(@blob_id) @@ -24,4 +26,15 @@ defmodule SsbBfeEncoderTest do encoded_box2 = SsbBfe.Encoder.encode_box(@box2_msg) assert String.starts_with?(encoded_box2, <<5, 1>>) end + + test "encode_classic_feed_works" do + encoded_classic_feed = SsbBfe.Encoder.encode_feed(@classic_feed) + assert String.starts_with?(encoded_classic_feed, <<0, 0>>) + end + + test "encode_classic_msg_works" do + encoded_classic_msg = SsbBfe.Encoder.encode_msg(@classic_msg) + assert encoded_classic_msg == <<1, 0, 71, 200, 94, 171, 251, 80, 163, 17, 8, 62, 69, 159, 208, 172, 103, 214, 112, 166, 252, 43, 49, 27, 96, 131, 165, 70, 39, 2, 247, 91, 93, 143>> + end + end From 40a108f5e5c4f8b6ed1565c71a836896400002fc Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 20 Sep 2022 11:24:31 +0100 Subject: [PATCH 06/18] formatting --- lib/ssb_bfe/types.ex | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/ssb_bfe/types.ex b/lib/ssb_bfe/types.ex index 1e1022c..f3eb12c 100644 --- a/lib/ssb_bfe/types.ex +++ b/lib/ssb_bfe/types.ex @@ -8,7 +8,7 @@ defmodule SsbBfe.Types do <<2, 0>> end end - + @doc ~S""" Take a box as a string and return the encoded bytes representing the box type-format. Return `nil` if the ID does not end with `.box` or `.box2`. @@ -17,8 +17,10 @@ defmodule SsbBfe.Types do cond do String.ends_with?(boxed_str, ".box") -> <<5, 0>> + String.ends_with?(boxed_str, ".box2") -> <<5, 1>> + true -> nil end @@ -43,8 +45,10 @@ defmodule SsbBfe.Types do cond do String.ends_with?(msg_id, ".sha256") -> <<1, 0>> + String.ends_with?(msg_id, ".cloaked") -> <<1, 2>> + true -> nil end From 8ce0502782a4188085ea47a700edeb40b97d85c0 Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 20 Sep 2022 11:25:27 +0100 Subject: [PATCH 07/18] add sig encoder and improve base64 extractor --- lib/ssb_bfe/encoder.ex | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/ssb_bfe/encoder.ex b/lib/ssb_bfe/encoder.ex index 31f3910..7d38e44 100644 --- a/lib/ssb_bfe/encoder.ex +++ b/lib/ssb_bfe/encoder.ex @@ -2,8 +2,15 @@ # - use the `where` conditional guard with e.g. `is_number` defmodule SsbBfe.Encoder do + # Extract the base64 substring from a sigil-link and decode it. defp extract_base64_data(str) do - base64_data = String.slice(str, 1, 44) + base64_data = String.slice(str, 1..44) + Base.decode64(base64_data) + end + + # Provide a pattern with which to split a string and base64 decode the first part. + defp extract_base64_data(str, pattern) do + [base64_data | _] = String.split(str, pattern) Base.decode64(base64_data) end @@ -19,8 +26,7 @@ defmodule SsbBfe.Encoder do def encode_box(box_str) do box_tf_tag = SsbBfe.Types.get_box_type(box_str) - [base64_data, _] = String.split(box_str, ".") - {:ok, decoded_base64_data} = Base.decode64(base64_data) + {:ok, decoded_base64_data} = extract_base64_data(box_str, ".") box_tf_tag <> decoded_base64_data end @@ -35,4 +41,9 @@ defmodule SsbBfe.Encoder do {:ok, decoded_base64_data} = extract_base64_data(msg_id) msg_tf_tag <> decoded_base64_data end + + def encode_sig(sig) do + {:ok, decoded_base64_data} = extract_base64_data(sig, ".sig.ed25519") + <<4, 0>> <> decoded_base64_data + end end From dc4009978fb77ff4df02beda9122621b6ff73c6b Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 20 Sep 2022 11:26:00 +0100 Subject: [PATCH 08/18] add test for sig decoding --- test/ssb_bfe_encoder_test.exs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/ssb_bfe_encoder_test.exs b/test/ssb_bfe_encoder_test.exs index acdd692..992d9f8 100644 --- a/test/ssb_bfe_encoder_test.exs +++ b/test/ssb_bfe_encoder_test.exs @@ -6,12 +6,14 @@ defmodule SsbBfeEncoderTest do @box2_msg "WQyfhDDHQ1gH34uppHbj8SldRu8hD2764gQ6TAhaVp6R01EMBnJQj5ewD5F+UT5NwvV91uU8q5XCjuvcP4ihCJ0RtX8HjKyN+tDKP5gKB3UZo/eO/rP5CcPGoIG7pcLBsd3DQbZLfTnb/iqECEji9gclNcGENTS2u6aATwbQ4uQ7RzIAKKT2NfC2qk86p/gXC2owDFAazuPlQTT8DMNvO8G52gb48a75CGKsDAevrC//Bz38VFxwUiTKzRWaxCbTK9knj39u3qoCP9VLyyRqITgNwvlGLP7ndchTyBiO0TPNkb9PAOenw5WBjyWhA61hpG+VkKpkaysBVGjXYv8OpV1HGbs87TI79uT7JrNV4wEZiwqGknwmCi5B2gbd7tav8yDXsK5yQgDncHQjZotsBFX2adP7Jli9WmvV3xX5lL3kBNKV0ZiE/DZUgB2m1OXvCjNI4fuZhnpZpEQi9coO+icrirKiH/UA8TS9HI72cIbkEJVxOTnKnsgr3Qc/5HhtRS17a54ymVmBsnpP+KqqCqKLN50TInb7qoUlvQ2nw07xX3Ig9usLb8Ik8U8XMb6SLqACxlZN/qW4EJzxVetoIk84AU1yLInK6v9dzfsewRYBXW8+lYbyxVNuIIK4pKYsx2WbjuJyZHgjgbCdGf/kjqP5rDs4zwqj2lmkO70PoEUrcSi46J2hkqtcrd1yl+F3/BDwFlxAXH+x4+LhmT7g+BSgzRUbWvCyeB+HJaoao6g4K/Fs8HxnbVB1zW761OQJaQnV86ZThkvUjXh2SEBlBd+D94eUCqIJkjI7RLt+D/0gxg/D7u1Zq14UxRijZryB51An7GdXtEc2xhU+Bh/aPmKmMZ9D/ArdglSlnVUD8OIBVVw5jtooGlhxbOFHM4N5SoAO/yWPcbcuQz7t4SPij358rY574DLBGZEPCrS6KPpnrlqlnZK4f6/+9zv3hfzNTXVvJtxZL/rvmNvbgh7LpMnSqjnsXqm86a3GXeVWD83TdCnL1oPqEi/8RItTrjy01DmVhUoV6t12STP4mHb8RjR+/ks+7lowfV3HQ13n6if0g0/u+Bzv6XXOX6iePPOHA3lFv2MSPKf9JZ0uQiqajR03YkNE8YnSTYu0Io1cGPZ/lWBp2tyWtwFmGtqw/9+O165tJhrdU2EXJ4T/XP136WpLD2+vtYsx3Xr5lfeD12/g+I/6jwduqTuHpst2tqvcSWoZ4DAWcpcKJ1mUbJU3/mLAYGwWb3XuqMOgJOLoztAwd5xFzUZD1MnR/iyYoZ2weYTSOz3OKR3cJyCjxBhIGaX5xpAc61K1dXNfERBJr9TS0mL2578dd5AauE6Ksn6YlGxNJIVC3VpdAtRbVHNX1g==.box2" @classic_feed "@d/zDvFswFbQaYJc03i47C9CgDev+/A8QQSfG5l/SEfw=.ed25519" @classic_msg "%R8heq/tQoxEIPkWf0Kxn1nCm/CsxG2CDpUYnAvdbXY8=.sha256" + @sig "nkY4Wsn9feosxvX7bpLK7OxjdSrw6gSL8sun1n2TMLXKySYK9L5itVQnV2nQUctFsrUOa2istD2vDk1B0uAMBQ==.sig.ed25519" test "encode_blob_works" do encoded_blob = SsbBfe.Encoder.encode_blob(@blob_id) + assert encoded_blob == <<2, 0, 75, 191, 130, 192, 115, 58, 117, 159, 108, 139, 149, 103, 225, 251, 105, 147, 249, 127, 149, 214, 209, 50, 172, 243, 38, 139, 62, 178, 150, 91, 89, 254>> end - + test "encode_bool_works" do assert SsbBfe.Encoder.encode_bool(true) == <<6, 1, 1>> assert SsbBfe.Encoder.encode_bool(false) == <<6, 1, 0>> @@ -21,7 +23,7 @@ defmodule SsbBfeEncoderTest do encoded_box1 = SsbBfe.Encoder.encode_box(@box1_msg) assert String.starts_with?(encoded_box1, <<5, 0>>) end - + test "encode_box2_works" do encoded_box2 = SsbBfe.Encoder.encode_box(@box2_msg) assert String.starts_with?(encoded_box2, <<5, 1>>) @@ -34,7 +36,12 @@ defmodule SsbBfeEncoderTest do test "encode_classic_msg_works" do encoded_classic_msg = SsbBfe.Encoder.encode_msg(@classic_msg) + assert encoded_classic_msg == <<1, 0, 71, 200, 94, 171, 251, 80, 163, 17, 8, 62, 69, 159, 208, 172, 103, 214, 112, 166, 252, 43, 49, 27, 96, 131, 165, 70, 39, 2, 247, 91, 93, 143>> end + test "encode_sig_works" do + encoded_sig = SsbBfe.Encoder.encode_sig(@sig) + assert encoded_sig == <<4, 0, 158, 70, 56, 90, 201, 253, 125, 234, 44, 198, 245, 251, 110, 146, 202, 236, 236, 99, 117, 42, 240, 234, 4, 139, 242, 203, 167, 214, 125, 147, 48, 181, 202, 201, 38, 10, 244, 190, 98, 181, 84, 39, 87, 105, 208, 81, 203, 69, 178, 181, 14, 107, 104, 172, 180, 61, 175, 14, 77, 65, 210, 224, 12, 5>> + end end From 58d87d9c6a2a96f1f8b6cc00253d386476cc1f47 Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 20 Sep 2022 11:37:24 +0100 Subject: [PATCH 09/18] add str encoder --- lib/ssb_bfe/encoder.ex | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/ssb_bfe/encoder.ex b/lib/ssb_bfe/encoder.ex index 7d38e44..da5ca7b 100644 --- a/lib/ssb_bfe/encoder.ex +++ b/lib/ssb_bfe/encoder.ex @@ -46,4 +46,8 @@ defmodule SsbBfe.Encoder do {:ok, decoded_base64_data} = extract_base64_data(sig, ".sig.ed25519") <<4, 0>> <> decoded_base64_data end -end + + def encode_str(str), do: <<6, 0>> <> str + + # def encode_uri(uri) +end From 99b6a046b48fa5977ed6bde2ad4fafb5c45b21e5 Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 20 Sep 2022 11:38:01 +0100 Subject: [PATCH 10/18] add test for str encoding --- test/ssb_bfe_encoder_test.exs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/test/ssb_bfe_encoder_test.exs b/test/ssb_bfe_encoder_test.exs index 992d9f8..9d84794 100644 --- a/test/ssb_bfe_encoder_test.exs +++ b/test/ssb_bfe_encoder_test.exs @@ -7,6 +7,7 @@ defmodule SsbBfeEncoderTest do @classic_feed "@d/zDvFswFbQaYJc03i47C9CgDev+/A8QQSfG5l/SEfw=.ed25519" @classic_msg "%R8heq/tQoxEIPkWf0Kxn1nCm/CsxG2CDpUYnAvdbXY8=.sha256" @sig "nkY4Wsn9feosxvX7bpLK7OxjdSrw6gSL8sun1n2TMLXKySYK9L5itVQnV2nQUctFsrUOa2istD2vDk1B0uAMBQ==.sig.ed25519" + @str "golden ripples in the meshwork" test "encode_blob_works" do encoded_blob = SsbBfe.Encoder.encode_blob(@blob_id) @@ -44,4 +45,9 @@ defmodule SsbBfeEncoderTest do encoded_sig = SsbBfe.Encoder.encode_sig(@sig) assert encoded_sig == <<4, 0, 158, 70, 56, 90, 201, 253, 125, 234, 44, 198, 245, 251, 110, 146, 202, 236, 236, 99, 117, 42, 240, 234, 4, 139, 242, 203, 167, 214, 125, 147, 48, 181, 202, 201, 38, 10, 244, 190, 98, 181, 84, 39, 87, 105, 208, 81, 203, 69, 178, 181, 14, 107, 104, 172, 180, 61, 175, 14, 77, 65, 210, 224, 12, 5>> end + + test "encode_str_works" do + encoded_str = SsbBfe.Encoder.encode_str(@str) + assert encoded_str == <<6, 0, 103, 111, 108, 100, 101, 110, 32, 114, 105, 112, 112, 108, 101, 115, 32, 105, 110, 32, 116, 104, 101, 32, 109, 101, 115, 104, 119, 111, 114, 107>> + end end From e4b9dc7b5418e26bf22239a3d30e445075f615d2 Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 20 Sep 2022 19:33:58 +0100 Subject: [PATCH 11/18] add string encoding --- lib/ssb_bfe.ex | 22 ++++++++++++++++++++++ lib/ssb_bfe/encoder.ex | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/ssb_bfe.ex b/lib/ssb_bfe.ex index 608e9ad..1933c63 100644 --- a/lib/ssb_bfe.ex +++ b/lib/ssb_bfe.ex @@ -15,4 +15,26 @@ defmodule SsbBfe do def hello do :world end + + def encode(value) when is_bitstring(value) do + cond do + String.starts_with?(value, "@") -> + SsbBfe.Encoder.encode_feed(value) + + String.starts_with?(value, "%") -> + SsbBfe.Encoder.encode_msg(value) + + String.starts_with?(value, "&") -> + SsbBfe.Encoder.encode_blob(value) + + String.ends_with?(value, ".sig.ed25519") -> + SsbBfe.Encoder.encode_sig(value) + + String.ends_with?(value, [".box", ".box2"]) -> + SsbBfe.Encoder.encode_box(value) + + true -> + SsbBfe.Encoder.encode_str(value) + end + end end diff --git a/lib/ssb_bfe/encoder.ex b/lib/ssb_bfe/encoder.ex index da5ca7b..39174c0 100644 --- a/lib/ssb_bfe/encoder.ex +++ b/lib/ssb_bfe/encoder.ex @@ -1,5 +1,5 @@ # might be good to use a multiclause function for the `encode` function -# - use the `where` conditional guard with e.g. `is_number` +# - use the `when` conditional guard with e.g. `is_number` defmodule SsbBfe.Encoder do # Extract the base64 substring from a sigil-link and decode it. From 3732f34ded0e5c58fa6ae26efb0b0a2cc3c78a9f Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 20 Sep 2022 19:34:41 +0100 Subject: [PATCH 12/18] add lockfile to ignore list --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 8f6a4a6..54df957 100644 --- a/.gitignore +++ b/.gitignore @@ -24,3 +24,6 @@ ssb_bfe-*.tar # Temporary files, for example, from tests. /tmp/ + +# Ignore the lockfile +mix.lock From 22c820ca7330846177a4f6f5287a1050dec191c7 Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 20 Sep 2022 19:35:52 +0100 Subject: [PATCH 13/18] remove low-level tests and add api tests for string encoding --- test/ssb_bfe_encoder_test.exs | 53 ----------------------------------- test/ssb_bfe_test.exs | 48 +++++++++++++++++++++++++++++-- test/ssb_bfe_types_test.exs | 15 ---------- 3 files changed, 46 insertions(+), 70 deletions(-) delete mode 100644 test/ssb_bfe_encoder_test.exs delete mode 100644 test/ssb_bfe_types_test.exs diff --git a/test/ssb_bfe_encoder_test.exs b/test/ssb_bfe_encoder_test.exs deleted file mode 100644 index 9d84794..0000000 --- a/test/ssb_bfe_encoder_test.exs +++ /dev/null @@ -1,53 +0,0 @@ -defmodule SsbBfeEncoderTest do - use ExUnit.Case - - @blob_id "&S7+CwHM6dZ9si5Vn4ftpk/l/ldbRMqzzJos+spZbWf4=.sha256" - @box1_msg "siZEm1zFx1icq0SrEynGDpNRmJCXMxTB3iEteXFn+IhJH8WhMbT8tp9qOIaFkIYcdOyerSon6RK0l4RE1ZdDh/3lcGZSdP0Ljq59qsdqlf2ngwbIbV9AWdPRrPsoVZBV6RhI+YcVTloWWP5aauu1hZKjcm62ezLBTQ3EmFPYtDuwsOFkx9/7FP97ljhj67CwvlGzuiWp6FNICHbt5kOCxs9H0k6Tr8JJVdaJtJ2pqkX4p0ECMuEuYxCYbh3FpncCqlNZJXb0dj3iSsfsMNWTJLDqfkqJKH1jBVfxDL6+xAXBDS+E4F2hD4y9gRDZEej99uVBQWlbxr5eCRV+VbfBGYxwoAYtqux6rg3jBabImKKinBwHShEP5F/+wlb9IxQn4swyOgyv+UKx/jbx+91Ayso5bnNPZMpwRRX5p5DbpK1BnryeVJhktMgFqgni1g0lHyU8sQ2QzwZgXGw7dfYoamkqK4D24NOLnUoHuVuhd7Q5SxZWSAO6wpDa4nrODePoJdl328pbMwCoQlUNeHINmKxh/o/oCNbgXitn4oN3kSVEg/umdgwwI94gmZUjiYwP1v7HA7dI.box" - @box2_msg "WQyfhDDHQ1gH34uppHbj8SldRu8hD2764gQ6TAhaVp6R01EMBnJQj5ewD5F+UT5NwvV91uU8q5XCjuvcP4ihCJ0RtX8HjKyN+tDKP5gKB3UZo/eO/rP5CcPGoIG7pcLBsd3DQbZLfTnb/iqECEji9gclNcGENTS2u6aATwbQ4uQ7RzIAKKT2NfC2qk86p/gXC2owDFAazuPlQTT8DMNvO8G52gb48a75CGKsDAevrC//Bz38VFxwUiTKzRWaxCbTK9knj39u3qoCP9VLyyRqITgNwvlGLP7ndchTyBiO0TPNkb9PAOenw5WBjyWhA61hpG+VkKpkaysBVGjXYv8OpV1HGbs87TI79uT7JrNV4wEZiwqGknwmCi5B2gbd7tav8yDXsK5yQgDncHQjZotsBFX2adP7Jli9WmvV3xX5lL3kBNKV0ZiE/DZUgB2m1OXvCjNI4fuZhnpZpEQi9coO+icrirKiH/UA8TS9HI72cIbkEJVxOTnKnsgr3Qc/5HhtRS17a54ymVmBsnpP+KqqCqKLN50TInb7qoUlvQ2nw07xX3Ig9usLb8Ik8U8XMb6SLqACxlZN/qW4EJzxVetoIk84AU1yLInK6v9dzfsewRYBXW8+lYbyxVNuIIK4pKYsx2WbjuJyZHgjgbCdGf/kjqP5rDs4zwqj2lmkO70PoEUrcSi46J2hkqtcrd1yl+F3/BDwFlxAXH+x4+LhmT7g+BSgzRUbWvCyeB+HJaoao6g4K/Fs8HxnbVB1zW761OQJaQnV86ZThkvUjXh2SEBlBd+D94eUCqIJkjI7RLt+D/0gxg/D7u1Zq14UxRijZryB51An7GdXtEc2xhU+Bh/aPmKmMZ9D/ArdglSlnVUD8OIBVVw5jtooGlhxbOFHM4N5SoAO/yWPcbcuQz7t4SPij358rY574DLBGZEPCrS6KPpnrlqlnZK4f6/+9zv3hfzNTXVvJtxZL/rvmNvbgh7LpMnSqjnsXqm86a3GXeVWD83TdCnL1oPqEi/8RItTrjy01DmVhUoV6t12STP4mHb8RjR+/ks+7lowfV3HQ13n6if0g0/u+Bzv6XXOX6iePPOHA3lFv2MSPKf9JZ0uQiqajR03YkNE8YnSTYu0Io1cGPZ/lWBp2tyWtwFmGtqw/9+O165tJhrdU2EXJ4T/XP136WpLD2+vtYsx3Xr5lfeD12/g+I/6jwduqTuHpst2tqvcSWoZ4DAWcpcKJ1mUbJU3/mLAYGwWb3XuqMOgJOLoztAwd5xFzUZD1MnR/iyYoZ2weYTSOz3OKR3cJyCjxBhIGaX5xpAc61K1dXNfERBJr9TS0mL2578dd5AauE6Ksn6YlGxNJIVC3VpdAtRbVHNX1g==.box2" - @classic_feed "@d/zDvFswFbQaYJc03i47C9CgDev+/A8QQSfG5l/SEfw=.ed25519" - @classic_msg "%R8heq/tQoxEIPkWf0Kxn1nCm/CsxG2CDpUYnAvdbXY8=.sha256" - @sig "nkY4Wsn9feosxvX7bpLK7OxjdSrw6gSL8sun1n2TMLXKySYK9L5itVQnV2nQUctFsrUOa2istD2vDk1B0uAMBQ==.sig.ed25519" - @str "golden ripples in the meshwork" - - test "encode_blob_works" do - encoded_blob = SsbBfe.Encoder.encode_blob(@blob_id) - - assert encoded_blob == <<2, 0, 75, 191, 130, 192, 115, 58, 117, 159, 108, 139, 149, 103, 225, 251, 105, 147, 249, 127, 149, 214, 209, 50, 172, 243, 38, 139, 62, 178, 150, 91, 89, 254>> - end - - test "encode_bool_works" do - assert SsbBfe.Encoder.encode_bool(true) == <<6, 1, 1>> - assert SsbBfe.Encoder.encode_bool(false) == <<6, 1, 0>> - end - - test "encode_box1_works" do - encoded_box1 = SsbBfe.Encoder.encode_box(@box1_msg) - assert String.starts_with?(encoded_box1, <<5, 0>>) - end - - test "encode_box2_works" do - encoded_box2 = SsbBfe.Encoder.encode_box(@box2_msg) - assert String.starts_with?(encoded_box2, <<5, 1>>) - end - - test "encode_classic_feed_works" do - encoded_classic_feed = SsbBfe.Encoder.encode_feed(@classic_feed) - assert String.starts_with?(encoded_classic_feed, <<0, 0>>) - end - - test "encode_classic_msg_works" do - encoded_classic_msg = SsbBfe.Encoder.encode_msg(@classic_msg) - - assert encoded_classic_msg == <<1, 0, 71, 200, 94, 171, 251, 80, 163, 17, 8, 62, 69, 159, 208, 172, 103, 214, 112, 166, 252, 43, 49, 27, 96, 131, 165, 70, 39, 2, 247, 91, 93, 143>> - end - - test "encode_sig_works" do - encoded_sig = SsbBfe.Encoder.encode_sig(@sig) - assert encoded_sig == <<4, 0, 158, 70, 56, 90, 201, 253, 125, 234, 44, 198, 245, 251, 110, 146, 202, 236, 236, 99, 117, 42, 240, 234, 4, 139, 242, 203, 167, 214, 125, 147, 48, 181, 202, 201, 38, 10, 244, 190, 98, 181, 84, 39, 87, 105, 208, 81, 203, 69, 178, 181, 14, 107, 104, 172, 180, 61, 175, 14, 77, 65, 210, 224, 12, 5>> - end - - test "encode_str_works" do - encoded_str = SsbBfe.Encoder.encode_str(@str) - assert encoded_str == <<6, 0, 103, 111, 108, 100, 101, 110, 32, 114, 105, 112, 112, 108, 101, 115, 32, 105, 110, 32, 116, 104, 101, 32, 109, 101, 115, 104, 119, 111, 114, 107>> - end -end diff --git a/test/ssb_bfe_test.exs b/test/ssb_bfe_test.exs index 0df39be..37165c4 100644 --- a/test/ssb_bfe_test.exs +++ b/test/ssb_bfe_test.exs @@ -2,7 +2,51 @@ defmodule SsbBfeTest do use ExUnit.Case doctest SsbBfe - test "greets the world" do - assert SsbBfe.hello() == :world + setup do + [ + blob: "&S7+CwHM6dZ9si5Vn4ftpk/l/ldbRMqzzJos+spZbWf4=.sha256", + box1: "bG92ZSBjb2xsYXBzZXMgc3BhY2V0aW1l.box", + box2: "bG92ZSBjb2xsYXBzZXMgc3BhY2V0aW1l.box2", + feed_classic: "@d/zDvFswFbQaYJc03i47C9CgDev+/A8QQSfG5l/SEfw=.ed25519", + msg_classic: "%R8heq/tQoxEIPkWf0Kxn1nCm/CsxG2CDpUYnAvdbXY8=.sha256", + sig: "nkY4Wsn9feosxvX7bpLK7OxjdSrw6gSL8sun1n2TMLXKySYK9L5itVQnV2nQUctFsrUOa2istD2vDk1B0uAMBQ==.sig.ed25519", + str: "golden ripples in the meshwork", + ] + end + + test "classic feed is encoded correctly", context do + encoded_feed = SsbBfe.encode(context.feed_classic) + + assert encoded_feed == <<0, 0, 119, 252, 195, 188, 91, 48, 21, 180, 26, 96, 151, 52, 222, 46, 59, 11, 208, 160, 13, 235, 254, 252, 15, 16, 65, 39, 198, 230, 95, 210, 17, 252>> + end + + test "classic msg is encoded correctly", context do + encoded_msg = SsbBfe.encode(context.msg_classic) + + assert encoded_msg == <<1, 0, 71, 200, 94, 171, 251, 80, 163, 17, 8, 62, 69, 159, 208, 172, 103, 214, 112, 166, 252, 43, 49, 27, 96, 131, 165, 70, 39, 2, 247, 91, 93, 143>> + end + + test "blob is encoded correctly", context do + encoded_blob = SsbBfe.encode(context.blob) + + assert encoded_blob == <<2, 0, 75, 191, 130, 192, 115, 58, 117, 159, 108, 139, 149, 103, 225, 251, 105, 147, 249, 127, 149, 214, 209, 50, 172, 243, 38, 139, 62, 178, 150, 91, 89, 254>> + end + + test "signature is encoded correctly", context do + encoded_sig = SsbBfe.encode(context.sig) + + assert encoded_sig == <<4, 0, 158, 70, 56, 90, 201, 253, 125, 234, 44, 198, 245, 251, 110, 146, 202, 236, 236, 99, 117, 42, 240, 234, 4, 139, 242, 203, 167, 214, 125, 147, 48, 181, 202, 201, 38, 10, 244, 190, 98, 181, 84, 39, 87, 105, 208, 81, 203, 69, 178, 181, 14, 107, 104, 172, 180, 61, 175, 14, 77, 65, 210, 224, 12, 5>> + end + + test "box is encoded correctly", context do + encoded_box = SsbBfe.encode(context.box1) + + assert encoded_box == <<5, 0, 108, 111, 118, 101, 32, 99, 111, 108, 108, 97, 112, 115, 101, 115, 32, 115, 112, 97, 99, 101, 116, 105, 109, 101>> + end + + test "box2 is encoded correctly", context do + encoded_box2 = SsbBfe.encode(context.box2) + + assert encoded_box2 == <<5, 1, 108, 111, 118, 101, 32, 99, 111, 108, 108, 97, 112, 115, 101, 115, 32, 115, 112, 97, 99, 101, 116, 105, 109, 101>> end end diff --git a/test/ssb_bfe_types_test.exs b/test/ssb_bfe_types_test.exs deleted file mode 100644 index 1ff227e..0000000 --- a/test/ssb_bfe_types_test.exs +++ /dev/null @@ -1,15 +0,0 @@ -defmodule SsbBfeTypesTest do - use ExUnit.Case - - test "get_blob_type_matches_classic" do - blob_id = "&S7+CwHM6dZ9si5Vn4ftpk/l/ldbRMqzzJos+spZbWf4=.sha256" - blob_type = SsbBfe.Types.get_blob_type(blob_id) - assert blob_type == <<2, 0>> - end - - test "get_blob_type_matches_unknown" do - blob_id = "&what.is_this" - blob_type = SsbBfe.Types.get_blob_type(blob_id) - assert blob_type == nil - end -end From 1da93e32602313d2d7e4b8b55a761a0ea43297a9 Mon Sep 17 00:00:00 2001 From: glyph Date: Tue, 20 Sep 2022 19:48:21 +0100 Subject: [PATCH 14/18] add happy path test for plain string --- test/ssb_bfe_test.exs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/ssb_bfe_test.exs b/test/ssb_bfe_test.exs index 37165c4..684c29f 100644 --- a/test/ssb_bfe_test.exs +++ b/test/ssb_bfe_test.exs @@ -13,7 +13,9 @@ defmodule SsbBfeTest do str: "golden ripples in the meshwork", ] end - + + # HAPPY PATH ENCODING TESTS + test "classic feed is encoded correctly", context do encoded_feed = SsbBfe.encode(context.feed_classic) @@ -49,4 +51,10 @@ defmodule SsbBfeTest do assert encoded_box2 == <<5, 1, 108, 111, 118, 101, 32, 99, 111, 108, 108, 97, 112, 115, 101, 115, 32, 115, 112, 97, 99, 101, 116, 105, 109, 101>> end + + test "plain string is encoded correctly", context do + encoded_str = SsbBfe.encode(context.str) + + assert encoded_str == <<6, 0, 103, 111, 108, 100, 101, 110, 32, 114, 105, 112, 112, 108, 101, 115, 32, 105, 110, 32, 116, 104, 101, 32, 109, 101, 115, 104, 119, 111, 114, 107>> + end end From f72b8f153f05cd65deeff0669258efa5bd40269e Mon Sep 17 00:00:00 2001 From: glyph Date: Wed, 21 Sep 2022 12:10:30 +0100 Subject: [PATCH 15/18] add tests for encoding boolean, nil, list, map and tuple --- test/ssb_bfe_test.exs | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/test/ssb_bfe_test.exs b/test/ssb_bfe_test.exs index 684c29f..21e0ca7 100644 --- a/test/ssb_bfe_test.exs +++ b/test/ssb_bfe_test.exs @@ -57,4 +57,36 @@ defmodule SsbBfeTest do assert encoded_str == <<6, 0, 103, 111, 108, 100, 101, 110, 32, 114, 105, 112, 112, 108, 101, 115, 32, 105, 110, 32, 116, 104, 101, 32, 109, 101, 115, 104, 119, 111, 114, 107>> end + + test "boolean is encoded correctly" do + encoded_bool_true = SsbBfe.encode(true) + encoded_bool_false = SsbBfe.encode(false) + + assert encoded_bool_true == <<6, 1, 1>> + assert encoded_bool_false == <<6, 1, 0>> + end + + test "nil is encoded correctly" do + encoded_nil = SsbBfe.encode(nil) + + assert encoded_nil == <<6, 2>> + end + + test "list is encoded correctly" do + encoded_list = SsbBfe.encode([true, nil, "ganoderma"]) + + assert encoded_list == [<<6, 1, 1>>, <<6, 2>>, <<6, 0, 103, 97, 110, 111, 100, 101, 114, 109, 97>>] + end + + test "map is encoded correctly", context do + encoded_map = SsbBfe.encode(%{"bool" => false, "feed" => context.feed_classic}) + + assert encoded_map == %{"bool" => <<6, 1, 0>>, "feed" => <<0, 0, 119, 252, 195, 188, 91, 48, 21, 180, 26, 96, 151, 52, 222, 46, 59, 11, 208, 160, 13, 235, 254, 252, 15, 16, 65, 39, 198, 230, 95, 210, 17, 252>>} + end + + test "tuple is encoded correctly", context do + encoded_tuple = SsbBfe.encode({7, context.msg_classic}) + + assert encoded_tuple == [7, <<1, 0, 71, 200, 94, 171, 251, 80, 163, 17, 8, 62, 69, 159, 208, 172, 103, 214, 112, 166, 252, 43, 49, 27, 96, 131, 165, 70, 39, 2, 247, 91, 93, 143>>] + end end From e31466b128a3cbffc9a982a2a42d3865b2a85908 Mon Sep 17 00:00:00 2001 From: glyph Date: Wed, 21 Sep 2022 12:11:20 +0100 Subject: [PATCH 16/18] add encoder for nil values --- lib/ssb_bfe/encoder.ex | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/ssb_bfe/encoder.ex b/lib/ssb_bfe/encoder.ex index 39174c0..159b4ac 100644 --- a/lib/ssb_bfe/encoder.ex +++ b/lib/ssb_bfe/encoder.ex @@ -42,6 +42,8 @@ defmodule SsbBfe.Encoder do msg_tf_tag <> decoded_base64_data end + def encode_nil(), do: <<6, 2>> + def encode_sig(sig) do {:ok, decoded_base64_data} = extract_base64_data(sig, ".sig.ed25519") <<4, 0>> <> decoded_base64_data From bac29888bd80e35e38921ca67ffe1d008d10f1d6 Mon Sep 17 00:00:00 2001 From: glyph Date: Wed, 21 Sep 2022 12:12:14 +0100 Subject: [PATCH 17/18] add encoding of boolean, nil, list, map and tuple --- lib/ssb_bfe.ex | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/lib/ssb_bfe.ex b/lib/ssb_bfe.ex index 1933c63..ff8ea35 100644 --- a/lib/ssb_bfe.ex +++ b/lib/ssb_bfe.ex @@ -16,6 +16,24 @@ defmodule SsbBfe do :world end + def encode(value) when is_list(value) do + Enum.map(value, fn x -> encode(x) end) + end + + def encode(value) when is_map(value) do + Enum.reduce( + value, + %{}, + fn {k, v}, acc -> + Map.put(acc, k, SsbBfe.encode(v)) + end + ) + end + + def encode(value) when is_tuple(value) do + Enum.map(Tuple.to_list(value), fn x -> encode(x) end) + end + def encode(value) when is_bitstring(value) do cond do String.starts_with?(value, "@") -> @@ -37,4 +55,10 @@ defmodule SsbBfe do SsbBfe.Encoder.encode_str(value) end end + + def encode(value) when is_boolean(value), do: SsbBfe.Encoder.encode_bool(value) + + def encode(value) when is_number(value), do: value + + def encode(value) when is_nil(value), do: SsbBfe.Encoder.encode_nil() end From b2f7328f7812ed340cdfe605856cab97c5149a8f Mon Sep 17 00:00:00 2001 From: glyph Date: Wed, 21 Sep 2022 12:35:18 +0100 Subject: [PATCH 18/18] add license and docs about encoding support --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.md b/README.md index af659e1..fe2d45b 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,41 @@ Binary Field Encodings (BFE) for Secure Scuttlebutt (SSB). +See the [SSB Binary Field Encodings Specification](https://github.com/ssbc/ssb-bfe-spec) for details. + +## Encoding + +```elixir +SsbBfe.encode(value) +``` + +### Elixir Types + +Encoding of the following Elixir types is supported: + + - List + - Map + - Tuple + - String + - Boolean + - Nil + - Integer + - Float + +Note: encoding of structs is not supported. You may wish to convert your struct to amap and encode it that way. + +### Scuttlebutt Types + +Encoding of the following Scuttlebutt types is supported: + + - Feed (classic) + - Message (classic) + - Blob + - Signature + - Private message (box, box2) + +Note: encoding of URIs is not currently supported, nor are other formats such as Gabby Grove and Bendy Butt. + ## Installation If [available in Hex](https://hex.pm/docs/publish), the package can be installed @@ -15,7 +50,12 @@ def deps do end ``` +## Documentation + Documentation can be generated with [ExDoc](https://github.com/elixir-lang/ex_doc) and published on [HexDocs](https://hexdocs.pm). Once published, the docs can be found at . +## License + +LGPL-3.0.