Ankusa.BlobStore.Checksum (ankusa v0.7.0)

Copy Markdown View Source

The integrity headers the HTTP object stores take on a PUT, and the check of the digest they send back on a GET.

AdapterOn PUTVerified on GET
S3x-amz-checksum-sha256 (and Content-MD5 on each multipart part)x-amz-checksum-sha256, requested with x-amz-checksum-mode: ENABLED
GCSx-goog-hash: md5=…x-goog-hash
AzureContent-MD5 and x-ms-blob-content-md5Content-MD5
OCIContent-MD5 (and x-content-sha256, which the signature covers)opc-content-md5

The store validates the digest it was sent, so bytes damaged on the way up are refused with a 4xx; a digest the store sends back is compared with the bytes received, so bytes damaged on the way down are {:error, :integrity}. A response without the header (the store never kept one, a composite multipart digest, an emulator) is not checked: absence is not corruption.

Summary

Functions

Check a GET response's body against the digest header names the store puts on it (the first of names that is present); :sha256 or :md5. {:ok, body} or {:error, :integrity}.

The first value of response header name, or nil.

The md5 a x-goog-hash header (crc32c=…,md5=…, possibly several headers) carries.

Base64 MD5 of data.

Base64 SHA-256 of data.

:ok unless expected (the base64 digest a response header carried) is not the algorithm (:sha256 or :md5) digest of body. A nil or empty expected is :ok.

Functions

check_response(headers, body, algorithm, names)

@spec check_response(
  %{required(String.t()) => [String.t()]},
  binary(),
  :sha256 | :md5,
  [String.t()]
) ::
  {:ok, binary()} | {:error, :integrity}

Check a GET response's body against the digest header names the store puts on it (the first of names that is present); :sha256 or :md5. {:ok, body} or {:error, :integrity}.

first(headers, name)

@spec first(%{required(String.t()) => [String.t()]}, String.t()) :: String.t() | nil

The first value of response header name, or nil.

goog_md5(headers)

@spec goog_md5(%{required(String.t()) => [String.t()]}) :: String.t() | nil

The md5 a x-goog-hash header (crc32c=…,md5=…, possibly several headers) carries.

md5_base64(data)

@spec md5_base64(iodata()) :: String.t()

Base64 MD5 of data.

sha256_base64(data)

@spec sha256_base64(iodata()) :: String.t()

Base64 SHA-256 of data.

verify(algorithm, body, expected)

@spec verify(:sha256 | :md5, iodata(), String.t() | nil) :: :ok | {:error, :integrity}

:ok unless expected (the base64 digest a response header carried) is not the algorithm (:sha256 or :md5) digest of body. A nil or empty expected is :ok.