lib/mix/tasks/metamorphic_crypto.gen.key.ex

defmodule Mix.Tasks.MetamorphicCrypto.Gen.Key do
  @shortdoc "Generate a random 32-byte encryption key"

  @moduledoc """
  Generates a random 32-byte encryption key for use with MetamorphicCrypto.

      $ mix metamorphic_crypto.gen.key

  The output is a base64-encoded key suitable for:

  - `config :metamorphic_crypto, :secret_key` (Ecto encrypted fields)
  - `config :metamorphic_crypto, :hmac_key` (blind indexes)
  - Any `MetamorphicCrypto.SecretBox` operation

  ## Options

  - `--count` or `-n` — number of keys to generate (default: 1)

  ## Example

      $ mix metamorphic_crypto.gen.key
      Generated key:
      xK7m2Fq9+PnNz3v...

      Add to your config/runtime.exs:
          config :metamorphic_crypto, :secret_key, System.fetch_env!("METAMORPHIC_CRYPTO_KEY")

  """

  use Mix.Task

  @impl true
  def run(args) do
    {opts, _, _} = OptionParser.parse(args, aliases: [n: :count], strict: [count: :integer])
    count = Keyword.get(opts, :count, 1)

    # Start the NIF application so we can call generate_key
    Mix.Task.run("app.start")

    keys = for _ <- 1..count, do: MetamorphicCrypto.Keys.generate_key()

    case keys do
      [key] ->
        Mix.shell().info("""

        Generated key:
            #{key}

        Add to your environment:
            export METAMORPHIC_CRYPTO_KEY="#{key}"

        Then in config/runtime.exs:
            config :metamorphic_crypto, :secret_key, System.fetch_env!("METAMORPHIC_CRYPTO_KEY")
        """)

      keys ->
        Mix.shell().info("\nGenerated #{count} keys:\n")

        Enum.each(keys, fn key ->
          Mix.shell().info("    #{key}")
        end)

        Mix.shell().info("")
    end
  end
end