From file to ciphertext.
A beginner’s guide to Linux, OpenSSL, and what encryption can—and cannot—promise.
What happens to your file here?
- Plaintext + exact passphraseYour file bytes or UTF-8 text. Passphrase spaces, case and Unicode matter.
- Fresh salt → password KDF → keyPBKDF2-HMAC-SHA-256, 600,000 iterations, random 16-byte salt. PBKDF2 is not memory-hard.
- AES-GCM + fresh nonce + header256-bit key by default (128-bit optional), random 12-byte nonce, full header authenticated as AAD.
- Ciphertext + 128-bit tag → .sfvThe header stores the version, cipher, KDF settings, salt and nonce; filename metadata is encrypted. Download explicitly.
Going the other way
SFV header → validate bounds → same passphrase + stored salt → same key → authenticate/decrypt → plaintext. The app reads cipher and KDF metadata for you. The tag covers ciphertext and the header; no plaintext is released until authentication succeeds. Wrong passphrases or changed ciphertext/tag cause a generic authentication failure. Unsupported/malformed headers are rejected before key derivation.
The salt and nonce are not passwords and need not be secret. They do not let someone recover a strong passphrase, but attackers can attempt offline guesses. Authentication is not a digital signature or proof of identity. See the exact SFV format and return to the browser vault to create or open .sfv files.
Start with a disposable practice file.
These are commands for your own Linux terminal—not JavaScript, not something this page runs. Only decrypt files you own or are authorized to access. Use a maintained OpenSSL 3.x package from your distribution; ask its package manager/admin if OpenSSL is missing. First inspect your installed version and supported flags:
Check your tools
openssl version
openssl enc -helpCore flags below are documented in OpenSSL 3.0 and 3.5. The automated Linux command test reports the exact version it runs. The examples deliberately use the common default salted format (8-byte salt in these versions), not the newer -saltlen flag, which OpenSSL 3.0 does not support. Do not assume all releases, vendor builds or provider configurations have identical capabilities. Using AES or PBKDF2 alone does not establish FIPS validation/compliance.
Create an isolated workspace
umask 077
workdir=$(mktemp -d "${TMPDIR:-/tmp}/file-vault-demo.XXXXXXXX") && cd "$workdir"
pwdumask 077 restricts permissions on new files to their owner (normally 600 for files, 700 for directories). It does not fix permissions of existing files. mktemp -d creates a new private directory; $(...) captures its path. && changes directory only if creation succeeds. pwd prints where you are. If setup reports an error, stop. Run subsequent blocks only inside the new directory. This is a private workspace, not a guarantee of secure storage; temporary directories may be cleaned automatically.
Make public test content
printf '%s\n' 'PUBLIC practice file. Not a real secret.' > './original.bin'This is intentionally nonsecret text. printf writes the literal sample and a newline; > writes it to a file and overwrites an existing file. The .bin name is just a name; encryption works on bytes of any file type. For your own file, work on a copy in a private directory instead, and keep the original safe. Never put sensitive text into a literal shell command: shell history and process arguments can expose it.
Encrypt and decrypt a file in the terminal.
No authentication: these AES-256-CBC examples hide content but do not protect it from tampering. Use the authenticated browser vault or an established authenticated file-encryption tool for important data—not bare CBC. OpenSSL CMS is a different, certificate/key-based workflow; this beginner guide does not claim a tested authenticated CMS recipe.
Use a strong, unique passphrase. The commands deliberately omit -pass: OpenSSL prompts interactively, with confirmation on encryption and no terminal echo. Do not place a real password in command arguments, environment variables or shell history. The passphrase is not embedded in the file. Lost passphrases cannot be recovered.
Before every command, ensure its output path does not already exist. OpenSSL -out can truncate/overwrite a file, even if decryption later fails. The examples use three distinct names and never delete the original. Do not point input and output at the same file.
Encrypt → original.bin.enc
openssl enc -aes-256-cbc -e -pbkdf2 -iter 600000 -md sha256 -salt \
-in './original.bin' -out './original.bin.enc'At the two prompts, type the same passphrase. The output is binary by default: a salted OpenSSL header and AES-CBC ciphertext with PKCS#7 padding. The .enc extension is a convention, not stored algorithm metadata or proof of security.
Decrypt → recovered.bin
openssl enc -aes-256-cbc -d -pbkdf2 -iter 600000 -md sha256 -salt \
-in './original.bin.enc' -out './recovered.bin'Enter the exact original passphrase at the prompt. Use the same cipher, digest, PBKDF2 settings, salt convention and encoding. A zero exit status means the operation completed and padding was accepted, not that the result is authentic.
Check this practice round trip
cmp './original.bin' './recovered.bin' && printf '%s\n' 'Practice files match byte for byte.'cmp compares the two local files; it is normally silent if they match. && prints the success message only on a match. This tests a round trip while you still have a trusted original. It does not add authentication to CBC or establish trust in files received later.
What OpenSSL does in this example
- File bytes + prompted passphraseNo text conversion. The filename itself is not encrypted/stored by enc.
- Random salt → PBKDF2-HMAC-SHA-256600,000 iterations derive the 32-byte AES key and 16-byte CBC IV from the password and salt.
- PKCS#7 padding → AES-256-CBCWhole blocks are encrypted. No authentication tag is produced.
- Salted header + ciphertext → .encDecrypt reads the salt, derives the same key/IV, decrypts, then checks padding. Changed data can still pass.
Unlike SFV, a normal enc salted header is not a self-describing authenticated container: keep the exact OpenSSL version, cipher, KDF, iteration count, digest, salt length and whether Base64 was used with your backup, separately from the passphrase. Older files may use different derivation defaults. Do not guess parameters or downgrade to legacy algorithms; consult the creator’s recorded settings. Do not add manual -S salts or key/IV overrides: explicit-salt behavior changed in OpenSSL 3.0.
Every argument, explained.
General shape: openssl enc -CIPHER [-e | -d] [KDF options] -in INPUT -out OUTPUT. Brackets and uppercase placeholders here are notation, not characters to type. | in this notation means “choose one”; in a real shell command it pipes output into the next program.
| Argument | What it means in these commands |
|---|---|
openssl | Runs the OpenSSL command-line program installed on your machine. |
enc | Selects its symmetric encryption/decryption subcommand. It is not the SFV format reader and does not support GCM or CCM authenticated modes. |
-aes-256-cbc | Selects AES with a 256-bit key in CBC mode. It provides no integrity/authentication by itself. It is a flag, not -cipher aes-256-cbc. |
-e | Encrypt. This is enc’s default, made explicit for clarity. |
-d | Decrypt instead of encrypt. It does not authenticate the recovered bytes. |
-pbkdf2 | Use PBKDF2 password-based derivation rather than enc’s older default derivation. With -md sha256 this uses HMAC-SHA-256. Without an explicit -iter, documented defaults use only 10,000 iterations. |
-iter 600000 | Set 600,000 derivation iterations. Also enables PBKDF2; we include both flags for clarity. Repeat exactly on decrypt. This follows OWASP’s PBKDF2-SHA-256 minimum reviewed 2026-10-22, not a universal forever setting; it neither makes PBKDF2 memory-hard nor authenticates CBC. |
-md sha256 | Set SHA-256 as the derivation digest (HMAC-SHA-256 with PBKDF2). This is not a file integrity hash or authentication check. Repeat it on decrypt. |
-salt | Use a random salt on encryption (already the default); it is stored with ciphertext and read on decryption. A salt prevents identical password derivations across files, not password guessing itself. It is not a secret or an authentication tag. |
-in '…' | Read bytes from the named input file. Without it, enc reads standard input. Quotes belong to the shell, not the filename. |
-out '…' | Write bytes to this separate output file, potentially overwriting it. Without it, enc writes standard output. Keep recovered plaintext private; do not pipe it straight into an interpreter or application. |
-a (optional) | Base64-encode after encryption; Base64-decode before decryption. Use on both sides. It is encoding, not extra encryption; output grows by about one third plus line breaks/header/padding overhead. Normal output includes line breaks. |
Shell punctuation is part of the explanation, too.
Single quotes keep a path with spaces literal: './my document.pdf'. Replace the whole quoted filename with your own path; ./ denotes the current directory and avoids a leading dash being mistaken for an option. A literal apostrophe needs different shell quoting; do not paste an untrusted filename as shell syntax. Double quotes in "$workdir" expand the variable while keeping its path one argument. A backslash at the very end of a line joins it to the next line: no spaces after that backslash. You can instead put the entire command on one line without the backslash.
Optional Base64 example (still unauthenticated CBC)
Use different, previously nonexistent output paths. The only cryptographic settings are unchanged; -a adds/removes printable Base64 encoding. Keep the normal line breaks. A Base64 file is not an SFV vault.
Encrypt with Base64 output
openssl enc -aes-256-cbc -e -pbkdf2 -iter 600000 -md sha256 -salt -a \
-in './original.bin' -out './original.bin.enc.b64'Decrypt Base64 input
openssl enc -aes-256-cbc -d -pbkdf2 -iter 600000 -md sha256 -salt -a \
-in './original.bin.enc.b64' -out './recovered-base64.bin'To encrypt real text, save it to a private file using a trusted local editor, then encrypt that file. The public printf practice sample above is not a pattern for entering secrets. No secret-bearing pipe examples, passwords in arguments, obsolete ciphers, or disabled padding are needed.
A decrypted file is not automatically a trustworthy file.
- “bad decrypt” / wrong passphrase
- Usually wrong password/settings, truncated data, or invalid padding. OpenSSL may already have written partial or garbage plaintext before reporting failure. Do not use that output. A wrong password can also pass padding by chance; neither absence nor presence of this error is a reliable authenticity test.
- Modified ciphertext, but no error
- CBC is malleable: modifying a non-final ciphertext block can corrupt one plaintext block and deliberately flip bits in the next while leaving final padding valid. Our Linux regression test demonstrates an exit status of zero with changed plaintext. This is expected behavior, not proof that the file was safe.
- “bad magic number” / “wrong final block length”
- Check the source format, complete file transfer, recorded parameters and whether Base64 was used. These messages vary by version and do not reliably diagnose a particular cause. A browser
.sfvfile is simply the wrong format for enc. - Unknown option / missing algorithm
- Read
openssl versionandopenssl enc -help; check vendor documentation and provider configuration. Do not “fix” it with an older cipher or weaker KDF. - Permission denied / output exists
- Check your directory and filenames without broadening permissions. Stop if a desired output already exists; choose a new name. Do not use root privileges just to encrypt your own file.
Keep the original until a trusted recovery test and backup succeed. We never recommend automatic deletion. Save encrypted output and its settings to storage you control; do not rely on the temporary practice directory. Move/backup deliberately, verify your copy, keep the passphrase separately, and restrict access to recovered plaintext. Moving to shared or non-POSIX filesystems may change permissions. Encryption does not erase originals, temporary plaintext, swap, shell history, editor backups, or saved downloads.
For important files, prefer an established authenticated file-encryption tool/format, or the browser’s authenticated SFV workflow within its documented limits. Do not build your own ad-hoc “CBC plus hash” scheme. This guide does not make the application externally audited; a compromised origin/browser/extension/device can still observe secrets. There is no browser execution of these terminal commands and no automatic clipboard use: Copy buttons copy only the displayed public example you choose.
Official references
Reviewed 2026-10-22. Match the documentation to your installed version.
- OpenSSL 3.0 enc: syntax, defaults and lack of authenticated modes
- OpenSSL 3.5 enc: syntax and salt-length behavior
- OpenSSL passphrase sources and exposure warnings
- OWASP: password derivation guidance (not an endorsement of CBC file encryption)
- File Vault limits, threat model and interoperability tests
Select command text to copy it, or use its Copy button. Nothing runs in this browser.