Current section
Files
Jump to
Current section
Files
lib/crypto/public_key.ex
defmodule Tezex.Crypto.PublicKey do
@moduledoc """
Holds public key data.
Parameters:
- `:point` [`t:Tezex.Crypto.Point.t/0`]: public key point data;
- `:curve` [`t:Tezex.Crypto.Curve.t/0`]: public key curve information.
"""
defstruct [:point, :curve]
alias Tezex.Crypto.Curve
alias Tezex.Crypto.KnownCurves
alias Tezex.Crypto.Math
alias Tezex.Crypto.Point
alias Tezex.Crypto.Utils
@type t :: %__MODULE__{
point: Point.t(),
curve: Curve.t()
}
@doc false
def to_string(public_key, encoded \\ false) do
curve_length = Curve.get_length(public_key.curve)
x_string =
Utils.string_from_number(
public_key.point.x,
curve_length
)
y_string =
Utils.string_from_number(
public_key.point.y,
curve_length
)
if encoded do
"\x00\x04" <> x_string <> y_string
else
x_string <> y_string
end
end
@doc false
def from_string(string, curve \\ :secp256k1, validate_point \\ true) do
{:ok, from_string!(string, curve, validate_point)}
rescue
e in RuntimeError -> {:error, e}
end
@doc false
def from_string!(string, curve \\ :secp256k1, validate_point \\ true) do
curve = KnownCurves.get_curve_by_name(curve)
base_length = Curve.get_length(curve)
xs = binary_part(string, 0, base_length)
ys = binary_part(string, base_length, byte_size(string) - base_length)
point = %Point{
x: Utils.number_from_string(xs),
y: Utils.number_from_string(ys)
}
publicKey = %__MODULE__{point: point, curve: curve}
cond do
validate_point == false ->
publicKey
Point.is_at_infinity?(point) ->
raise "Public Key point is at infinity"
Curve.contains?(curve, point) == false ->
raise "Point (#{point.x},#{point.y}) is not valid for curve #{curve.name}"
Point.is_at_infinity?(Math.multiply(point, curve."N", curve."N", curve."A", curve."P")) ==
false ->
raise "Point (#{point.x},#{point.y}) * #{curve.name}.N is not at infinity"
true ->
publicKey
end
end
end