What is the Magento crypt-key ?
The Magento crypt-key is a 256-bit symmetric AES key stored at app/etc/env.php under crypt.key. Magento’s Encryptor uses it to encrypt sensitive data at rest — saved-payment tokens in Magento_Vault, OAuth and REST API tokens, integration secrets, and any config field flagged with backend_model="...\Backend\Encrypted". Cipher is AES-256-CBC (2.0+) or AES-256-GCM (2.4.6+). Rotate via bin/magento encryption:key:change. Treat the crypt-key as a top-tier secret — lose it and every saved token, every API credential, every encrypted config field is gone.
Five steps from key generation to rotation in production
The crypt-key is not magic — it is a 32-byte hex string and a documented call path. Here is the wiring, end to end.
-
01
Magento installer generates a 256-bit key
At first install (
bin/magento setup:install ...), a random 32-byte hex key is generated by Magento’s installer and written toapp/etc/env.phpunder'crypt' => ['key' => '<hex>']. The same key is stored in a fallback array structure —crypt.keybecomes a multi-entry array as soon as rotations happen, with the oldest key first and the newest key last. The hex length is exactly 64 characters (32 bytes × 2 hex chars), equal to the AES-256 key length. -
02
Application code encrypts on write
When
Magento_Vaultsaves a payment-method token, the framework’sEncryptorInterface::encrypt()is called. It picks the newest key in thecrypt.keyarray, runs AES-256-CBC or AES-256-GCM with a random IV, base64-encodes the result, prepends a key-version marker (0_:,1_:, etc.) so the framework knows which key encrypted that row, and writes the ciphertext into the DB column. The same path runs for OAuth tokens, integration secrets, and encryptedcore_config_datarows. -
03
Application code decrypts on read
Encryptor::decrypt()reads the version marker on the ciphertext (0_:,1_:, ...), looks up the corresponding key in thecrypt.keyarray, and runs AES decryption with the matching cipher. If the key for that version is missing fromenv.php— because someone restored an old DB dump onto a new env, or trimmed the array thinking the old key was unused — the decrypt throws and the encrypted value is permanently unrecoverable. The version marker is the only reason multi-key rotation can work without re-encrypting the whole DB instantly. -
04
Rotation via
bin/magento encryption:key:changeThe CLI command
bin/magento encryption:key:changegenerates a new key, appends it to thecrypt.keyarray (so the array now has both old and new), then walks every encrypted column in the database —vault_payment_token,oauth_token,integration, encrypted rows incore_config_data, plus any third-party encrypted columns — and re-encrypts each row with the new key, updating the version marker. The old key is kept in the array so that historic backups and any rows the walker missed can still decrypt. -
05
Secrets management — never commit env.php
app/etc/env.phpis in.gitignoreby default for a reason — it holds the crypt-key, the DB password, the admin frontname, and the session cookie config. Production deployment loadsenv.phpfrom a secrets manager (AWS Secrets Manager, HashiCorp Vault, Cloudflare Secrets, sealed Kubernetes secrets) at runtime, never baked into a container image. Always back up the crypt-key out of band in an encrypted password manager — losing the env.php on a server with no backup of the crypt-key loses every saved payment token, every API credential, and every encrypted config field.
Four moments when rotating the crypt-key is the obvious move
Rotation is cheap with the right runbook. These are the moments where the cost of running on an inherited or possibly-leaked key dominates the cost of rotating.
-
On first Magento install — verify the key is strong
Right after
bin/magento setup:install, openapp/etc/env.phpand confirm thecrypt.keyvalue is a long random 64-character hex string — not a recognisable placeholder, not a short ASCII phrase, not blank. Some older Adobe Commerce Cloud base images defaulted to a known-weak key, and some third-party install scripts have shipped predictable defaults. If the key looks short, predictable, or matches anything documented in a Magento Security Bulletin, rotate immediately withbin/magento encryption:key:changebefore the store sees its first real saved-payment-token. -
After personnel change or suspected env.php leak
Any developer or contractor who has ever had read access to
app/etc/env.phpholds the crypt-key in their head, their laptop, or their backup archives. The moment one of them rolls off the project, or a laptop gets lost, or an env.php gets accidentally pasted into a Slack DM, the right action is to rotate immediately viabin/magento encryption:key:change. The rotation is non-disruptive in maintenance mode and invalidates the old key for any future ciphertext. Do not wait for an incident — rotate at the personnel-change milestone. -
After a Magento upgrade that changes the cipher
Magento 2.4.6 introduced AES-256-GCM as the new default cipher, alongside the legacy AES-256-CBC. Existing ciphertext stays decryptable with the old cipher because the version marker carries the cipher hint, but rotating the crypt-key after the upgrade also re-encrypts every column to the new AES-GCM cipher in one pass. GCM offers authenticated encryption (catches tampering at decrypt time), which CBC does not — so on any security-sensitive store, schedule a key rotation right after the 2.4.6+ upgrade as a cipher upgrade too.
-
After a breach or PCI-DSS incident
If a server is compromised, a backup is exfiltrated, or a PCI auditor flags a leaked credential, key rotation is the only way to invalidate every old encrypted token in one move without scanning every encrypted column by hand.
bin/magento encryption:key:changere-encrypts everything with a brand-new key, so any ciphertext copied out before the rotation can no longer be decrypted with the new env.php even if the old env.php leaks again later. Combine with a forced password reset for all admin users and a vault-token purge for every saved payment.
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.phpto gitThe single most common Magento security leak.
app/etc/env.phpholds the crypt-key, the DB password, the admin frontname, and the session config — one accidentalgit add app/etcand the whole site is exposed in the git history forever, even after a delete commit. Always confirmenv.phpis listed in.gitignore(it is, by default, in fresh installs — but custom.gitignorerewrites often miss it). Commit a sampleenv.php.exampleonly. If you discover env.php in git history, ROTATE the crypt-key immediately and rewrite the git history withgit filter-repo. -
Restoring a DB dump without the matching
crypt.keyWhen you copy a production DB dump down to staging, the ciphertext in
vault_payment_token,oauth_token, and encrypted rows ofcore_config_dataall 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 clearvault_payment_token, regenerate API integrations, and re-enter every encrypted config value via admin. -
Running
encryption:key:changeon a live store without maintenance modeThe 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.phpcan decrypt. Always wrap the rotation inbin/magento maintenance:enablefirst, run the rotation, verify a few decrypts work, thenmaintenance:disable. On a CI/CD pipeline this is a release-window job, not a hot-fix.
Magento crypt-key — frequently asked questions
-
Can I change the crypt-key manually by editing
env.php?No — never. The crypt-key inenv.phpis the symmetric key Magento uses to decrypt every encrypted DB column (saved-payment-tokens, OAuth tokens, integration secrets, encryptedcore_config_datarows). If you swap the value inenv.phpwithout 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 alwaysbin/magento maintenance:enablefollowed bybin/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) clearvault_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 withbackend_model="Magento\Config\Model\Config\Backend\Encrypted"). Then generate a fresh strong crypt-key by runningbin/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:changewalks 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, thenmaintenance: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 beforeencryption:key:changerebuilds it — isopenssl 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?
Openapp/etc/env.phpand copy the value ofcrypt.key. Compare against any known-bad hashes documented in the relevant Magento Security Bulletin (Adobe publishes these athelpx.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.
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.