{"id":32163934,"url":"https://github.com/venndr/erebus","last_synced_at":"2026-02-20T00:31:47.738Z","repository":{"id":44548419,"uuid":"364937626","full_name":"venndr/erebus","owner":"venndr","description":"Erebus is an implementation of the envelope encryption paradigm.","archived":false,"fork":false,"pushed_at":"2025-10-03T09:59:12.000Z","size":99,"stargazers_count":23,"open_issues_count":3,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-10-24T01:57:59.677Z","etag":null,"topics":["dek","ecto","elixir","elixir-lang","encryption","google-kms","publickey-cryptosystem"],"latest_commit_sha":null,"homepage":"","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"isc","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/venndr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2021-05-06T14:26:14.000Z","updated_at":"2025-10-03T09:59:16.000Z","dependencies_parsed_at":"2025-10-03T11:29:25.878Z","dependency_job_id":null,"html_url":"https://github.com/venndr/erebus","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/venndr/erebus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/venndr%2Ferebus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/venndr%2Ferebus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/venndr%2Ferebus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/venndr%2Ferebus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/venndr","download_url":"https://codeload.github.com/venndr/erebus/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/venndr%2Ferebus/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29637408,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-19T22:32:43.237Z","status":"ssl_error","status_checked_at":"2026-02-19T22:32:38.330Z","response_time":117,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.6:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dek","ecto","elixir","elixir-lang","encryption","google-kms","publickey-cryptosystem"],"created_at":"2025-10-21T14:41:00.691Z","updated_at":"2026-02-20T00:31:47.730Z","avatar_url":"https://github.com/venndr.png","language":"Elixir","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Erebus\n\n[![Elixir CI](https://github.com/venndr/erebus/actions/workflows/elixir.yml/badge.svg)](https://github.com/venndr/erebus/actions/workflows/elixir.yml)\n\nErebus is an implementation of the envelope encryption paradigm. It uses a separate key (called DEK, short for data encryption key) for each encrypted struct. The key is regenerated on each save, making key encryption barely necessary.  During each encryption, the DEK is encrypted using the KEK (key encryption key).\n\nThe DEK is a symmetric key (Erebus uses AES-256 with Galois mode (AES-GCM) with AEAD), which guarantees both the security and the integrity of the data. The KEK is an asymmetric key – Erebus uses the public key for encryption (for performance reasons when using external key storage) and the private key for decryption. The specific implementation depends on the backend.\n\nCurrently, there are three supported backend implementations:\n\n- `Erebus.KMS.Google` - Google KMS key storage. Means that your private key never leaves Google infrastructure,\n  which is the most secure option\n- `Erebus.KMS.Local` - private/public key pair stored on your hard drive. Please note that it makes them prone to leakage\n- `Erebus.KMS.Dummy` - base64 as encryption for DEK. Never use it in production\n\nPlease note that you need to provide config for the operations and explicitly invoke them, providing the config on every call.\n\n## Installation\n\nErebus can be installed by adding `erebus` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:erebus, \"~\u003e 0.2.0-rc.3\"}\n  ]\nend\n```\n\n## Usage\n\nTo use Erebus you need to wrap it to provide your backend configuration. Create a module like the example below in your app:\n\n```elixir\ndefmodule MyApp.Erebus do\n  def encrypt(struct, handle, version) do\n    opts = Application.get_env(:my_app, :erebus)\n\n    Erebus.encrypt(struct, handle, version, opts)\n  end\n\n  def decrypt(struct, fields) do\n    opts = Application.get_env(:my_app, :erebus)\n\n    Erebus.decrypt(struct, fields, opts)\n  end\nend\n```\n\nIn an encrypted struct, Erebus requires several fields for each encrypted property. Follow the\nexample below to define your structs:\n\n```elixir\ndefmodule SecureModel\n  @type t :: %__MODULE__{\n      # `first` is an encrypted field\n      first: String.t(),\n      # `second` is another encrypted field\n      second: String.t(),\n\n      # this field contains the ciphertext for the `first` field\n      first_encrypted: binary(),\n      # this field contains the ciphertext for the `second` field\n      second_encrypted: binary(),\n\n      # this field contains a hashed version of the unencrypted `first` field\n      first_hash: String.t(),\n      # this field contains a hashed version of the unencrypted `second` field\n      second_hash: String.t(),\n\n      # this field contains the DEK (data encryption key)\n      dek: map()\n    }\nend\n```\n\nIn this example `first` and `second` are the names of the encryptable fields. The _unsuffixed_ fields are virtual, meaning they are only used for encrypting (before write), or are populated after decrypting the equivalent `*_encrypted` fields – only _suffixed_ fields are written to the database. The `dek` field contains the DEK.\n\nThe `*_hash` suffixed fields are hashed (using SHA512) versions of the plain text field content. They can be used for finding exact matches without having to decrypt the content.\n\nWhen using [Ecto](https://hex.pm/packages/ecto), fields are defined using the `hashed_encrypted_field(:field_name)` and `data_encryption_key()` macros, which create all the necessary auxiliary fields for you:\n\n```elixir\nuse Erebus.Schema\n\nembedded_schema \"table\" do\n  hashed_encrypted_field(:first)\n  hashed_encrypted_field(:second)\n  data_encryption_key()\nend\n```\n\nAdditionally you must implement the `Erebus.Encryption` protocol to mark the fields which should be encrypted:\n\n```elixir\ndefimpl Erebus.Encryption do\n  def encrypted_fields(_), do: [:first, :second]\nend\n```\n\n### Usage with local KMS adapter\n\n1. Set the following values in your application config:\n    ```elixir\n    config :my_app, :erebus,\n      kms_backend: Erebus.KMS.Local,\n      keys_base_path: \"path_to_directory_containing_a_key_pair\",\n      private_key_password: \"1234\"\n    ```\n2. Generate asymmetric key pairs (named `public.pem` and `private.pem`) in the folder at `keys_base_path`.\n\n### Usage with Google KMS adapter\n\n1. Include [Goth](https://hex.pm/packages/goth) in your application:\n    ```elixir\n    {:goth, \"~\u003e 1.3.0-rc.2\"}\n    ```\n2. Start Goth in your `application.ex`:\n    ```elixir\n    credentials =\n      \"GCP_KMS_CREDENTIALS_PATH\"\n      |\u003e System.fetch_env!()\n      |\u003e File.read!()\n      |\u003e Jason.decode!()\n\n    scopes = [\"https://www.googleapis.com/auth/cloudkms\"]\n\n    source = {:service_account, credentials, scopes: scopes}\n\n    children = [\n      {Goth, name: MyApp.Goth, source: source}\n    ]\n    ```\n3. Pass the app's `name` in the `google_goth` option to Erebus:\n    ```elixir\n    config :my_app, :erebus,\n      kms_backend: Erebus.KMS.Google,\n      google_project: \"someproject\",\n      google_region: \"someregion\",\n      google_keyring: \"some_keyring\",\n      google_goth: MyApp.Goth\n    ```\n\nPlease note that if you're using Google KMS, your key must have access to the following roles:\n\n- [Cloud KMS CryptoKey Encrypter](https://cloud.google.com/kms/docs/reference/permissions-and-roles#cloudkms.cryptoKeyEncrypter)\n- [Cloud KMS CryptoKey Decrypter](https://cloud.google.com/kms/docs/reference/permissions-and-roles#cloudkms.cryptoKeyDecrypter)\n- [Cloud KMS CryptoKey Public Key Viewer](https://cloud.google.com/kms/docs/reference/permissions-and-roles#cloudkms.publicKeyViewer)\n\n### Ecto usage full example\n\n```elixir\ndefmodule EncryptedStuff do\n    use Ecto.Schema\n    import Ecto.Changeset\n    use Erebus.Schema\n\n    embedded_schema do\n      hashed_encrypted_field(:first)\n      hashed_encrypted_field(:second)\n      data_encryption_key()\n      field(:other, :string)\n    end\n\n    def changeset(stuff, attrs) do\n      changes =\n        stuff\n        |\u003e cast(attrs, [\n          :first,\n          :second\n        ])\n\n      encrypted_data =\n        changes\n        |\u003e MyApp.Erebus.encrypt(\"handle\", 1)\n\n      Ecto.Changeset.change(changes, encrypted_data)\n    end\n\n    defimpl Erebus.Encryption do\n      def encrypted_fields(_), do: [:first, :second]\n    end\n  end\n```\n\nIf you don't need multiple encryption keys, provide at hard-coded in `MyApp.Erebus`.\n\nCurrently Erebus only supports encoding and decoding data using Ecto changeset.\n\n## Licence\n\nISC License\n\nCopyright (c) 2024 Music Glue\n\nPermission to use, copy, modify, and/or distribute this software for any\npurpose with or without fee is hereby granted, provided that the above\ncopyright notice and this permission notice appear in all copies.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH\nREGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY\nAND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,\nINDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM\nLOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR\nOTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR\nPERFORMANCE OF THIS SOFTWARE.\n\nA copy of the licence text is also included in the file LICENSE","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvenndr%2Ferebus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fvenndr%2Ferebus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fvenndr%2Ferebus/lists"}