defmodule GitGud.Packages.Signing.Local do
@moduledoc """
The default signing backend: the private key lives in Postgres,
AES-GCM-encrypted through `GitGud.Secrets`, and is decrypted in the
app to sign.
This is what every registry format did before the behaviour existed,
and it stays the default — an existing deployment changes nothing and
needs nothing new running.
It delegates key custody to `GitGud.Packages.signing_key/2`, so apt's
OpenPGP certificate and the RSA keys every other format uses are
reached the same way they always were. Only `sign/4` is new, and it
only knows RSA: apt does its own signing through the sequoia NIF
because OpenPGP is a packet format, not a raw signature.
"""
@behaviour GitGud.Packages.Signing
alias GitGud.Packages
@impl true
def ensure_key(scope, format) do
# Only the public half leaves: `signing_key/2` also hands back the
# private key.
with {:ok, key} <- Packages.signing_key(scope, format) do
{:ok, Map.take(key, [:public_pem])}
end
end
@impl true
def public_key(scope, format) do
case Packages.get_signing_key(scope, format) do
nil -> {:error, :no_key}
key -> {:ok, key.public_key}
end
end
@impl true
def sign(scope, format, data, opts) when is_binary(data) do
digest = Keyword.get(opts, :digest, :sha256)
scheme = Keyword.get(opts, :scheme, :pkcs1v15)
with {:ok, %{private_pem: pem}} <- Packages.signing_key(scope, format),
{:ok, key} <- decode_private(pem) do
erlang_digest = GitGud.Packages.Signing.erlang_digest(digest)
{:ok, :public_key.sign(data, erlang_digest, key, sign_options(scheme))}
end
rescue
# `:public_key.sign/4` raises on a key it can't use — a caller
# asking an OpenPGP certificate to produce a PKCS#1 signature, for
# instance. An error tuple is the useful shape here.
e -> {:error, {:sign_failed, Exception.message(e)}}
end
defp sign_options(:pss),
do: [rsa_padding: :rsa_pkcs1_pss_padding, rsa_pss_saltlen: -1]
defp sign_options(_pkcs1v15), do: []
defp decode_private(pem) do
case :public_key.pem_decode(pem) do
[entry | _] -> {:ok, :public_key.pem_entry_decode(entry)}
[] -> {:error, :not_a_pem_key}
end
rescue
_ -> {:error, :not_a_pem_key}
end
end
neiam
/gitgud
Git Gud
public · Issues · Pulls · Labels · Forks · Compare · Actions success · Badges · Packages
⭐
1
Log in to mark this repository.
2.3 KiB · text
History
b868907