defmodule Cryppo.EncryptedDataWithDerivedKey do
@moduledoc """
A struct for a derived key and data encrypted with this derived key
"""
import Cryppo.Base64
import Cryppo.Strategies, only: [find_key_derivation_strategy: 1]
alias Cryppo.{DerivedKey, EncryptedData, EncryptedDataWithDerivedKey, Serialization}
@typedoc """
Struct `Cryppo.EncryptedData`
A `Cryppo.EncryptedData` struct contains
* `encrypted_data`: a `Cryppo.EncryptedData` struct
* `derived_key`: a `Cryppo.DerivedKey` struct
"""
@type t :: %__MODULE__{
encrypted_data: EncryptedData.t(),
derived_key: DerivedKey.t()
}
@enforce_keys [:encrypted_data, :derived_key]
defstruct [:encrypted_data, :derived_key]
@doc false
@spec load(String.t(), String.t(), String.t(), String.t(), String.t()) ::
{:ok, t()}
| {:error,
:invalid_base64
| :invalid_derivation_artefacts
| :invalid_bson
| String.t()}
| {:unsupported_encryption_strategy, binary}
| {:unsupported_key_derivation_strategy, binary}
def load(
strategy_name,
encrypted_data_base64,
encryption_artefacts_base64,
key_derivation_strategy,
derivation_artefacts_base64
) do
with {:ok, key_derivation_mod} <-
find_key_derivation_strategy(key_derivation_strategy),
{:ok, derivation_artefacts} <- decode_base64(derivation_artefacts_base64),
{:ok, salt, iterations, length} <- DerivedKey.load_artefacts(derivation_artefacts),
{:ok, encrypted_data} <-
EncryptedData.load(strategy_name, encrypted_data_base64, encryption_artefacts_base64) do
hash = apply(key_derivation_mod, :hash_function, [])
derived_key = %DerivedKey{
encryption_key: nil,
key_derivation_strategy: key_derivation_mod,
salt: salt,
iter: iterations,
length: length,
hash: hash
}
key = %__MODULE__{encrypted_data: encrypted_data, derived_key: derived_key}
{:ok, key}
end
end
defimpl Serialization do
@spec serialize(EncryptedDataWithDerivedKey.t()) :: binary
def serialize(%EncryptedDataWithDerivedKey{
derived_key: %DerivedKey{} = derived_key,
encrypted_data: %EncryptedData{} = encrypted_data
}) do
[encrypted_data, derived_key] |> Enum.map_join(".", &Serialization.serialize/1)
end
end
end