Packages

A standalone Elixir implementation of the Libp2p networking stack

Current section

Files

Jump to
libp2p_elixir lib libp2p crypto public_key_pb.ex
Raw

lib/libp2p/crypto/public_key_pb.ex

defmodule Libp2p.Crypto.PublicKeyPB do
@moduledoc """
Minimal encoding for the libp2p-crypto `PublicKey` protobuf message.
Schema (legacy libp2p):
- field 1: `Type` (varint enum)
- field 2: `Data` (bytes)
"""
alias Libp2p.Protobuf
alias Libp2p.Varint
@type key_type :: :rsa | :ed25519 | :secp256k1 | :ecdsa
@spec encode_public_key(key_type(), binary()) :: binary()
def encode_public_key(type, data) when is_binary(data) do
type_num =
case type do
:rsa -> 0
:ed25519 -> 1
:secp256k1 -> 2
:ecdsa -> 3
end
# tag = (field_number << 3) | wire_type
# wire types: 0 varint, 2 length-delimited
tag_type = Varint.encode_u64((1 <<< 3) ||| 0)
tag_data = Varint.encode_u64((2 <<< 3) ||| 2)
tag_type <>
Varint.encode_u64(type_num) <>
tag_data <>
Varint.encode_u64(byte_size(data)) <>
data
end
@spec decode_public_key(binary()) :: {key_type(), binary()}
def decode_public_key(bin) when is_binary(bin) do
fields = Protobuf.decode_fields(bin)
type_num =
case Enum.find(fields, fn {n, _w, _v} -> n == 1 end) do
{1, 0, v} when is_integer(v) -> v
_ -> raise ArgumentError, "missing PublicKey.Type"
end
data =
case Enum.find(fields, fn {n, _w, _v} -> n == 2 end) do
{2, 2, v} when is_binary(v) -> v
_ -> raise ArgumentError, "missing PublicKey.Data"
end
type =
case type_num do
0 -> :rsa
1 -> :ed25519
2 -> :secp256k1
3 -> :ecdsa
other -> raise ArgumentError, "unknown PublicKey.Type enum #{other}"
end
{type, data}
end
defp bor(a, b), do: :erlang.bor(a, b)
defp bsl(a, b), do: :erlang.bsl(a, b)
# allow use of <<< and ||| without pulling Bitwise everywhere
defp a <<< b, do: bsl(a, b)
defp a ||| b, do: bor(a, b)
end