
The Problem: Encrypting One File at a Time Does Not Scale
If you need to encrypt a single file, opening a terminal and running one command is easy. But organizations do not deal with single files. A mid-size company might generate hundreds of reports per day. A hospital produces thousands of patient records. A software team builds release artifacts every hour. A law firm handles tens of thousands of documents per case.
Encrypting each of these files by hand would take a human operator all day, every day. Even worse, manual processes create mistakes: someone forgets to encrypt a file, uses a weak password, or leaves the unencrypted original sitting on a shared drive. NIST SP 800-57 (Recommendation for Key Management) emphasizes that cryptographic key management must be systematic and repeatable. Manual processes are neither.
Batch encryption solves this. You tell QNSQY "encrypt all of these files at once," and it handles the rest: one password prompt, the same settings for every file, and an entry in the audit log for the run.
How QNSQY Batch Encryption Works
The qnsqy batch command takes a list of files and encrypts them all in one operation. Think of it like a factory assembly line: instead of a craftsman working on one item at a time, you feed hundreds of items into the line and they all come out encrypted on the other side.
QNSQY processes the files one after another. Each file gets its own salt and its own keys, so learning one file's key does not reveal the others (the shared password, of course, opens them all).
The three batch operations are:
- batch encrypt: Encrypt multiple files at once
- batch decrypt: Decrypt multiple .qs files at once
- batch verify: Verify the signatures on multiple files at once
Batch needs Pro or Business. On Free, encrypt and decrypt files one at a time.
Batch Encrypt: The Basic Command
The simplest batch encrypt command takes a file glob (a pattern like *.pdf) and an output directory:
qnsqy batch encrypt *.pdf -o ./encrypted/
This encrypts every PDF file in the current directory and writes the encrypted versions to the ./encrypted/ folder. Each output file keeps its original name with .qs appended: report.pdf becomes encrypted/report.pdf.qs.
QNSQY will prompt for a password once, then reuse it for all files in the batch. You do not need to type the password 500 times for 500 files.
Progress and Results
QNSQY works through the files one after another and reports each one:
Processing 3 files...
[1/3] Processing: a.pdf OK
[2/3] Processing: b.pdf OK
[3/3] Processing: c.pdf OK
Completed: 3/3 succeeded
If a file fails, QNSQY lists it under "Failed files" with the reason and exits with a non-zero code, so scripts can react (see Error Handling below).
Encrypting a Folder
QNSQY can encrypt a whole folder into one file:
qnsqy encrypt -i /data/reports -o /encrypted/reports.qs
It packs the folder into a temporary archive in your temporary folder, encrypts that, and wipes the temporary archive afterwards. Decrypting restores the folder inside the output location you choose:
qnsqy decrypt -i /encrypted/reports.qs -o /restore/
# Decrypted to: /restore/ (folder restored)
If your temporary folder is on an SSD, the usual limits of overwriting apply to that short-lived copy too.
Batch Decrypt
Decrypting a batch works the same way. Provide a glob of .qs files and an output directory:
qnsqy batch decrypt ./encrypted/*.qs -o ./decrypted/
QNSQY prompts for the password once and decrypts all files. If different files were encrypted with different passwords, you will need to decrypt them in separate batches grouped by password.
For recipient-based encryption (where files were encrypted to a public key), provide the private key:
qnsqy batch decrypt ./encrypted/*.qs --key finance_private -o ./decrypted/
Batch Verify
If your workflow involves signed files, batch verify checks all signatures at once:
qnsqy batch verify ./signed/*.pdf --verify-key signer.pub
This checks that every file was signed by the holder of signer.pub and has not been changed since. Each file is reported as valid or invalid, and any failure makes the command exit with an error. This is useful for compliance workflows where you need to prove document integrity.
Scripting and Automation
Batch commands are designed for automation. The key feature that makes this work is --password-stdin, which reads the password from standard input instead of an interactive prompt. This lets you pipe a password from a file or environment variable.
Using a Password File
For encryption, --password-stdin reads two lines: the password and its confirmation. A password file used for encryption must therefore hold the password twice, on two lines; for decryption QNSQY reads only the first line.
qnsqy batch encrypt /data/*.csv --password-stdin -o ./encrypted/ < /etc/qnsqy/backup.key
Protect this file aggressively:
chmod 400 /etc/qnsqy/backup.key
chown root:root /etc/qnsqy/backup.key
The 400 permission means only the file owner (root) can read it.
Using Environment Variables
printf '%s\n%s\n' "$ENCRYPTION_KEY" "$ENCRYPTION_KEY" | qnsqy encrypt --password-stdin -i file.txt
The password is sent twice because QNSQY expects a password and a confirmation, even in stdin mode. printf behaves the same in every shell, unlike echo -e. Set ENCRYPTION_KEY as a secret in your CI/CD system, never in the script itself.
CI/CD Integration
CI/CD pipelines build, test and release software automatically. Adding encryption to them protects build artifacts, release packages and sensitive configuration files.
Plan for two things. Single-file qnsqy encrypt works without an account, but batch needs a signed-in Pro or Business account. And each new machine you sign in on counts toward your plan's device limit, so CI systems that start a fresh runner for every job should use single-file encryption, or a persistent runner that stays signed in.
GitHub Actions
Store the password as a GitHub Actions secret (Settings > Secrets and variables > Actions), then reference it in your workflow:
- name: Encrypt release artifacts
env:
ENCRYPTION_KEY: ${{ secrets.QNSQY_KEY }}
run: |
printf '%s\n%s\n' "$ENCRYPTION_KEY" "$ENCRYPTION_KEY" | \
qnsqy encrypt --password-stdin \
-i ./build/release.zip \
-o ./encrypted/release.zip.qs
GitHub masks the secret in logs, replacing its value with ***. The encrypted artifact can then be uploaded to your release server or artifact storage.
Jenkins Pipeline
stage('Encrypt') {
steps {
withCredentials([string(credentialsId: 'qnsqy-key', variable: 'KEY')]) {
sh 'printf "%s\\n%s\\n" "$KEY" "$KEY" | qnsqy batch encrypt ./artifacts/* --password-stdin -o ./encrypted/'
}
}
}
The withCredentials block injects the password from Jenkins' credential store, so it never appears in the pipeline definition or the build log.
GitLab CI
encrypt_artifacts:
stage: deploy
script:
- printf '%s\n%s\n' "$QNSQY_KEY" "$QNSQY_KEY" | qnsqy batch encrypt ./build/* --password-stdin -o ./encrypted/
artifacts:
paths:
- encrypted/
Store QNSQY_KEY as a masked, protected variable in your GitLab project (Settings > CI/CD > Variables) so it is only available on protected branches.
Scheduled Backup Encryption
A common use is nightly backup encryption: your backup system writes its files, and a scheduled job encrypts them right after.
Cron Job (Linux)
# Encrypt the daily backup folder every night at 2 AM
# (/etc/qnsqy/backup.key holds the password on two lines)
0 2 * * * /usr/bin/qnsqy encrypt --password-stdin -i /backups/daily -o /encrypted/backup-$(date +\%Y\%m\%d).qs < /etc/qnsqy/backup.key
This encrypts the whole backup folder into one dated file. QNSQY wipes its own temporary archive; once you have checked the encrypted copy, remove or shred the plaintext backups as your retention rules allow.
Task Scheduler (Windows)
@echo off
for /f %%d in ('powershell -NoProfile -Command "Get-Date -Format yyyyMMdd"') do set D=%%d
qnsqy encrypt --acknowledge-no-sandbox --password-stdin -i C:\Backups\Daily -o C:\Encrypted\backup-%D%.qs < C:\Secure\backup.key
Save this as a .bat file and schedule it with Windows Task Scheduler. On Windows, every QNSQY command except help and version needs --acknowledge-no-sandbox, because Windows has no kernel network filter like Linux's seccomp; run as administrator, QNSQY adds a firewall rule for each operation instead. The PowerShell date call gives the same YYYYMMDD name in every regional setting.
Integration with Backup Workflows
Encryption should be the last step before backups leave your local environment. Whether you use rsync, Veeam, Bacula, or a cloud backup service, the pattern is the same:
- Backup software creates an unencrypted backup file
- QNSQY encrypts the backup file
- Shred the unencrypted backup file
- Transfer the encrypted file to offsite storage (cloud, tape, remote server)
This way, even if the offsite storage is compromised, the attacker only gets encrypted data. Without the password or private key, the backups are useless to them. This matters for HIPAA (healthcare), PCI DSS (payment card data) and GDPR (European personal data), which all treat encryption as a key safeguard for data at rest and in transit.
Department-Based Key Management
Large organizations need different departments to have different encryption keys. The finance team should not be able to decrypt HR records, and HR should not be able to decrypt legal documents. QNSQY handles this with recipient-based encryption using public/private key pairs.
First, generate a key pair for each department:
qnsqy keygen-enc -o finance -n "Finance Department"
qnsqy keygen-enc -o hr -n "Human Resources"
qnsqy keygen-enc -o legal -n "Legal Department"
Distribute the public keys (finance.pub, hr.pub, legal.pub) to the systems that encrypt data. Keep the private keys (finance, hr, legal) secure and only give them to the people who need to decrypt.
qnsqy batch encrypt /finance/*.xlsx --recipient finance.pub -o ./encrypted/
qnsqy batch encrypt /hr/*.docx --recipient hr.pub -o ./encrypted/
qnsqy batch encrypt /legal/*.pdf --recipient legal.pub -o ./encrypted/
Only the finance team (with the finance private key) can decrypt finance files. HR files require the hr private key. This is the need-to-know principle applied to keys.
Audit Logging for Compliance
Every batch run is written to the audit log with the date and time, the operating-system user, and how many files succeeded (for example 3/3). Operations on single files also record a hash of the file's path. The log does not record file names, the algorithm or the machine name.
You can view the audit log with:
qnsqy audit
For Security Information and Event Management (SIEM) platforms such as Splunk, Elastic or Microsoft Sentinel, QNSQY exports the log in CEF, JSON or Syslog format; schedule the export to keep your SIEM current. See SIEM integration.
Performance Considerations
Batch encryption time depends on three things:
- Password hashing: each file gets its own salt, so Argon2id runs once per file. With the default settings that is 128 MB of memory and a noticeable fraction of a second per file, which dominates when you encrypt many small files.
- Disk speed: for large files, reading and writing usually limit the speed. SSDs and NVMe drives are much faster than spinning disks.
- One file at a time: batch does not encrypt files in parallel. To use more cores, run several batch jobs on separate sets of files.
Measured speeds for single files are on our validation page.
Encrypt-Then-Shred: Cleaning Up Originals
After encrypting files, you often want to securely delete the unencrypted originals. This is a two-step process:
qnsqy batch encrypt /sensitive/*.csv -o ./encrypted/ && \
for f in /sensitive/*.csv; do qnsqy shred "$f" -f; done
The && ensures the shred step only runs if the encryption succeeded. If encryption fails for any reason, the originals are preserved so you do not lose data.
Security Best Practices for Batch Operations
- Never hardcode passwords in scripts. Use environment variables from a secrets manager or password files with restricted permissions. A password sitting in a shell script is a password anyone with read access to that script can see.
- Protect password files with strict permissions. Use
chmod 400(owner read only) andchown root:rootso only the root user can read them. - Rotate passwords and keys. NIST SP 800-57 asks you to set key lifetimes based on your risk assessment.
qnsqy rekey(Pro and Business) changes a file's password; to rotate the data key itself, decrypt and encrypt again. - Monitor your audit logs. If a batch job fails silently, unencrypted files might be sitting on disk. Set up alerts for failed encryption operations.
- Test your decryption process regularly. Backups are worthless if you cannot decrypt them when you need to. Schedule monthly test restores to verify your passwords and keys work correctly.
Rekeying: Changing Passwords Without Re-Encrypting
QNSQY's rekey command (Pro and Business) changes the password on an encrypted file without writing the plaintext to disk:
qnsqy rekey -i archive.qs
You enter the old password and then the new one. QNSQY unwraps the file's data key with the old password, wraps the same data key with the new one, and rewrites the header. The contents are not re-encrypted, so it is fast even on large files.
Be clear about what this does and does not rotate. It replaces the password, not the data key: copies of the file made before the change still open with the old password, and anyone who already learned the data key can still read the file. To rotate the data key itself, for example after a suspected compromise, decrypt and encrypt again, and delete the old copies.
For many files, you can script it (old password, then the new one twice):
for f in /encrypted/*.qs; do
printf '%s\n%s\n%s\n' "$OLD_PASSWORD" "$NEW_PASSWORD" "$NEW_PASSWORD" | qnsqy rekey --password-stdin -i "$f"
done
Advanced: M-of-N Threshold Encryption (Business)
For the most sensitive data, Business supports threshold encryption: decryption needs several people to cooperate. With "3-of-5", five people each hold a private key, and any three of them together can decrypt.
No single person, including a system administrator, can open the data alone. It suits key escrow, executive financial records and other data that no one person should be able to open.
qnsqy threshold-encrypt -i sensitive_archive.tar -m 3 \
-r cfo.pub -r coo.pub -r cto.pub -r auditor.pub -r counsel.pub
Decryption needs the private keys of any 3 of the 5 recipients. Two holders can be unavailable or compromised and the other three can still recover the data; two colluding insiders cannot open it without a third.
Error Handling and Monitoring
In production environments, you need to know when batch operations fail. Silent failures are dangerous: if a nightly backup encryption fails and nobody notices for three months, you have three months of unencrypted backups sitting on disk or in cloud storage.
QNSQY batch commands return standard exit codes: 0 for success, non-zero for failure. Use these in your scripts:
qnsqy batch encrypt /data/*.csv -o ./encrypted/ || \
mail -s "ALERT: Batch encryption failed" [email protected] < /dev/null
The || operator runs the mail command only if the encryption command fails. Combine this with the audit log for a complete picture of what happened and why.
Sources
- NIST SP 800-57 Part 1 Rev. 5: Recommendation for Key Management - https://csrc.nist.gov/pubs/sp/800/57/pt1/r5/final
- NIST FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard (ML-KEM) - https://csrc.nist.gov/pubs/fips/203/final
- NIST SP 800-38D: Recommendation for Block Cipher Modes of Operation: GCM - https://csrc.nist.gov/pubs/sp/800/38/d/final
- RFC 9106: Argon2 Memory-Hard Function for Password Hashing - https://www.rfc-editor.org/rfc/rfc9106
Related Articles
Originally published at quantumsequrity.com/blog/batch-encryption-enterprise.