Stevedore.Digest (Stevedore v0.2.0)

Copy Markdown View Source

A content digest: an algorithm:hex pair identifying bytes by their hash.

Digests are the unit of content addressing throughout OCI — manifests, configs, and layers are all referenced by digest, and the digest is always computed over the raw bytes as they appear on the wire (never over a re-serialized form).

Spec: OCI image-spec, descriptor "Digests".

Summary

Functions

Computes the digest of data with algorithm (default :sha256).

Parses an "algorithm:hex" string into a digest.

Renders a short, display-only form — the algorithm with the hex truncated to 12 characters.

Returns the "algorithm/hex" path segment used by the OCI blob layout (blobs/<algo>/<hex>).

Renders a digest as its canonical "algorithm:hex" string.

Verifies that data hashes to digest.

Types

algorithm()

@type algorithm() :: :sha256 | :sha512

t()

@type t() :: %Stevedore.Digest{algorithm: algorithm(), hex: String.t()}

Functions

compute(data, algorithm \\ :sha256)

@spec compute(iodata(), algorithm()) :: t()

Computes the digest of data with algorithm (default :sha256).

Examples

iex> Stevedore.Digest.compute("") |> to_string()
"sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"

iex> Stevedore.Digest.compute("hello", :sha256).hex
"2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824"

parse(string)

@spec parse(String.t()) :: {:ok, t()} | {:error, {:bad_input, term()}}

Parses an "algorithm:hex" string into a digest.

Rejects unknown algorithms, wrong hex length, and non-lowercase-hex — never converts the algorithm with String.to_atom/1 (it is matched against a fixed allowlist).

Examples

iex> {:ok, d} = Stevedore.Digest.parse("sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855")
iex> {d.algorithm, byte_size(d.hex)}
{:sha256, 64}

iex> Stevedore.Digest.parse("sha256:nothex")
{:error, {:bad_input, "invalid digest \"sha256:nothex\""}}

short(digest)

@spec short(t()) :: String.t()

Renders a short, display-only form — the algorithm with the hex truncated to 12 characters.

For logs and Inspect, not as an identifier: it is not collision-free. Use to_string/1 when you need the full, stable digest.

Examples

iex> Stevedore.Digest.short(Stevedore.Digest.compute(""))
"sha256:e3b0c44298fc…"

to_path(digest)

@spec to_path(t()) :: String.t()

Returns the "algorithm/hex" path segment used by the OCI blob layout (blobs/<algo>/<hex>).

Examples

iex> Stevedore.Digest.compute("") |> Stevedore.Digest.to_path()
"sha256/e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"

to_string(digest)

@spec to_string(t()) :: String.t()

Renders a digest as its canonical "algorithm:hex" string.

Also available via Kernel.to_string/1 through String.Chars.

Examples

iex> Stevedore.Digest.to_string(%Stevedore.Digest{algorithm: :sha256, hex: "abc"})
"sha256:abc"

verify(data, digest)

@spec verify(iodata(), t()) :: :ok | {:error, :digest_mismatch}

Verifies that data hashes to digest.

Examples

iex> Stevedore.Digest.verify("hello", Stevedore.Digest.compute("hello"))
:ok

iex> Stevedore.Digest.verify("tampered", Stevedore.Digest.compute("hello"))
{:error, :digest_mismatch}