Skip to content
5.0 Upwork, 100+ reviews Adobe Certified since 2021 New: become your own Magento developer Learn more →
Magento glossary

What is the Magento crypt-key?

Short answer The Magento crypt key is the secret key in app/etc/env.php under crypt → key. Magento’s Encryptor uses it to encrypt secrets before they go into the database, such as payment gateway passwords and API keys saved in config fields that use the Magento\Config\Model\Config\Backend\Encrypted backend model. It also signs the JWT admin and customer API tokens in 2.4.x. Since 2.3 the cipher is ChaCha20-Poly1305 through libsodium. You rotate it with bin/magento encryption:key:change. I treat it like the database password: lose it and every encrypted value has to be re-entered by hand.

How it works
  1. The installer generates a random key 01
  2. Application code encrypts on write 02
  3. Application code decrypts on read 03
  4. Rotation via bin/magento encryption:key:change 04
  5. Secrets management, never commit env.php 05
Each step is explained below

Most common mistake Committing env.php to git

How it works

Five steps from key generation to rotation in production

There is nothing mysterious about the crypt key. It is one value in env.php and one framework class that uses it. This is the path from install to rotation.

  1. 01

    The installer generates a random key

    During bin/magento setup:install Magento generates a random key and writes it to app/etc/env.php as 'crypt' => ['key' => '...']. You can also pass your own with --key. After a rotation the same key value holds several keys, one per line, oldest first and newest last. Magento always encrypts with the last one.

  2. 02

    Application code encrypts on write

    When Magento saves a secret, for example a payment gateway password in core_config_data, it calls Magento\Framework\Encryption\EncryptorInterface::encrypt(). The encryptor takes the newest key, encrypts with ChaCha20-Poly1305 through libsodium, base64-encodes the result and puts a prefix in front such as 1:3:. The first number is the key version (which line in crypt/key), the second is the cipher version. That prefix is what you see when you look at an encrypted config value in the database.

  3. 03

    Application code decrypts on read

    decrypt() reads that prefix, picks the matching key line and cipher, and decrypts. If that key is no longer in env.php the value comes back empty and cannot be recovered. I see this most often when someone restores a production database onto a server with a different env.php, or deletes the "old" key lines to tidy up. Payment and shipping API credentials suddenly stop working, with nothing obvious in the logs.

  4. 04

    Rotation via bin/magento encryption:key:change

    bin/magento encryption:key:change adds a new key line to crypt/key and re-encrypts the values Magento knows about, such as encrypted rows in core_config_data, with the new key. The old lines stay in env.php so anything not re-encrypted (third-party module columns, older backups) can still be read. Before I run it on a live store I take a database backup and a copy of env.php, and afterwards I check that payment and shipping methods still connect.

  5. 05

    Secrets management, never commit env.php

    app/etc/env.php is in Magento’s default .gitignore for good reason: it holds the crypt key, the database password and the admin path. On my deployments it lives only on the server or comes from a secrets store at deploy time, never from git or a container image. I also keep a copy of the key in a password manager. Lose env.php with no copy of the key and every encrypted config value has to be entered again by hand.

When to rotate

Four moments when rotating the crypt-key is the obvious move

Rotating the key takes a few minutes if you plan it. These are the four moments when I tell a client to do it.

  • On a new install, check the key is unique

    Right after bin/magento setup:install I open app/etc/env.php and check that crypt/key is a long random value, not a placeholder, not blank, and not copied from another project. Install scripts and Docker templates sometimes pass the same --key to every environment. If production shares a key with staging or a public template, rotate it with bin/magento encryption:key:change before you enter any real API credentials.

  • After personnel change or suspected env.php leak

    Anyone who has had read access to app/etc/env.php may still have the key on a laptop or in an old backup. When a developer or agency leaves the project, a laptop goes missing, or env.php gets pasted into a chat by mistake, I rotate the key with bin/magento encryption:key:change. New values are then encrypted with a key they never saw. I also change the database password and any API credentials they could have read, because rotating the key does not change those.

  • After upgrading an old store with legacy ciphertext

    Stores that started on Magento 2.0 to 2.2 can still hold values encrypted with the old mcrypt-era ciphers. Those still decrypt, because the cipher version sits in the prefix, but they are not on the current libsodium cipher. After moving such a store to 2.4.x I rotate the key so config values are written again with the current cipher, and I run bin/magento encryption:payment-data:update for stored payment data.

  • After a breach or PCI-DSS incident

    This is the case Adobe pushed hard in 2024 after CosmicSting (CVE-2024-34102), where attackers could read env.php and forge admin API tokens with the key. If a server is compromised or a backup leaks, I rotate the key so new tokens and new encrypted values use a key the attacker does not have. Rotation does not protect secrets that were already stolen, so I also change the payment, shipping and API credentials at the provider, reset admin passwords and remove unknown integrations.

Common mistakes

Three crypt-key mistakes that wreck a Magento store

Every crypt-key emergency I’ve been called in to triage came from one of these three mistakes. Audit your repo, your backup pipeline, and your rotation runbook before you need them.

  • Committing env.php to git

    The single most common Magento security leak. app/etc/env.php holds the crypt-key, the DB password, the admin frontname, and the session config, one accidental git add app/etc and the whole site is exposed in the git history forever, even after a delete commit. Always confirm env.php is listed in .gitignore (it is, by default, in fresh installs, but custom .gitignore rewrites often miss it). Commit a sample env.php.example only. If you discover env.php in git history, ROTATE the crypt-key immediately and rewrite the git history with git filter-repo.

  • Restoring a DB dump without the matching crypt.key

    When you copy a production DB dump down to staging, the ciphertext in vault_payment_token, oauth_token, and encrypted rows of core_config_data all expect to be decrypted with the production crypt-key. Restoring the dump onto a fresh Magento install with its own auto-generated crypt-key turns every encrypted column into garbage, saved-payment-tokens silently fail at checkout, API integrations 401, and encrypted config fields decrypt to noise. The crypt-key MUST travel alongside any DB dump. If you forgot, the only fix is to clear vault_payment_token, regenerate API integrations, and re-enter every encrypted config value via admin.

  • Running encryption:key:change on a live store without maintenance mode

    The rotation walks every encrypted column in the database and can take several minutes on a large store. Any concurrent vault-token-save or admin config-save during that walk can end up encrypted with one key but pointing at another via the version marker, leaving permanently-broken rows that no key in env.php can decrypt. Always wrap the rotation in bin/magento maintenance:enable first, run the rotation, verify a few decrypts work, then maintenance:disable. On a CI/CD pipeline this is a release-window job, not a hot-fix.

FAQ

Magento crypt-key: frequently asked questions

  • Can I change the crypt-key manually by editing env.php?
    No, never. The crypt-key in env.php is the symmetric key Magento uses to decrypt every encrypted DB column (saved-payment-tokens, OAuth tokens, integration secrets, encrypted core_config_data rows). If you swap the value in env.php without re-encrypting the DB, every existing ciphertext becomes permanently undecryptable, the version marker on each ciphertext (0_:, 1_:) points at a key index that no longer matches the actual value. The correct path is always bin/magento maintenance:enable followed by bin/magento encryption:key:change, which atomically generates the new key, walks every encrypted column, and re-encrypts each row with the new key while keeping the old key in the array as a fallback.
  • What happens if I’ve lost the original crypt-key?
    Every saved payment token, OAuth/API credential, and encrypted config field that was encrypted with the lost key is permanently unrecoverable, AES-256 is unbreakable in practice without the key. The practical recovery path is: 1) clear vault_payment_token (customers will re-enter cards on next checkout), 2) regenerate every API integration in admin (Stores → Integrations) so external systems re-pair, 3) re-enter every encrypted config field manually in admin (payment-gateway credentials, SMTP passwords, third-party API keys flagged with backend_model="Magento\Config\Model\Config\Backend\Encrypted"). Then generate a fresh strong crypt-key by running bin/magento encryption:key:change, even though there’s nothing left to re-encrypt, the command writes the new key cleanly. Document the new key in your password manager immediately.
  • Does the crypt-key rotation require downtime?
    For any production store, yes, always run in maintenance mode. bin/magento encryption:key:change walks every encrypted column in the database, and on a large store with hundreds of thousands of saved-payment-tokens or many encrypted config rows the walk can take several minutes. Any concurrent write during the walk, a customer saving a new card, an admin saving a config field, an API call provisioning a token, can end up encrypted with one key but with a version marker pointing at another, leaving a permanently-broken row. The safe sequence is: bin/magento maintenance:enable, then the rotation, then a spot-check decrypt on a sample of the rotated rows, then maintenance:disable. Schedule it inside a release window, not as a hot-fix.
  • How long should the crypt-key be?
    Magento generates a 256-bit (32-byte) key by default, encoded as 64 hex characters, equal to the AES-256 key length. Do not shorten it. Do not replace it with an ASCII phrase. Do not derive it from anything memorable. The right way to generate a replacement value, if you ever need to seed one before encryption:key:change rebuilds it, is openssl rand -hex 32, which produces exactly the 64-hex-char format Magento expects. AES-256 with a properly random 256-bit key has no known practical attack; the only way the encryption becomes weak is if the key itself is short, predictable, or leaked.
  • Is the crypt-key the same as Magento’s password hash salt?
    No, completely separate systems. Customer and admin passwords are hashed with a one-way function (bcrypt or argon2 in modern Magento) using a per-row random salt that is stored in the same column as the hash. That hash is one-way: Magento can verify a password at login by re-hashing the input, but it cannot reverse the hash to retrieve the original password, the crypt-key is not involved at all. The crypt-key, by contrast, is for two-way encryption of secrets the application needs to read back and use, payment-method tokens get re-sent to the PSP, API credentials get re-sent to third-party systems, encrypted config values get decrypted at runtime. Rotating the crypt-key does not invalidate any password; rotating passwords does not affect the crypt-key.
  • How do I check if my crypt-key is the Adobe Commerce Cloud default weak key?
    Open app/etc/env.php and copy the value of crypt.key. Compare against any known-bad hashes documented in the relevant Magento Security Bulletin (Adobe publishes these at helpx.adobe.com/security). If it matches a published weak key, rotate immediately. As a defence-in-depth measure even if it does not match, on any store inherited from a previous developer or a managed-hosting provider, just rotate, bin/magento maintenance:enable && bin/magento encryption:key:change && bin/magento maintenance:disable. The rotation is cheap, the cost of running on a leaked key is potentially catastrophic. Pair the rotation with rotating the DB password and admin passwords for full key-hygiene on the inherited install.
Crypt-key audit

Want a crypt-key + env.php audit on your Magento store?

Send your storefront URL, I will check your env.php hygiene, crypt-key strength, rotation history, encrypted-column health, and backup-of-key procedure, then reply with a written hardening plan, fixed-price quote, and earliest start date. 24-business-hour turnaround.

Kishan Savaliya Online 10 AM to 7 PM IST Chat on WhatsApp