← Back to Blog

Batch Encryption for Enterprise Workflows

Batch Encryption for Enterprise Workflows - QNSQY post-quantum encryption guide

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:

  1. Backup software creates an unencrypted backup file
  2. QNSQY encrypts the backup file
  3. Shred the unencrypted backup file
  4. 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) and chown root:root so 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

  1. NIST SP 800-57 Part 1 Rev. 5: Recommendation for Key Management - https://csrc.nist.gov/pubs/sp/800/57/pt1/r5/final
  2. NIST FIPS 203: Module-Lattice-Based Key-Encapsulation Mechanism Standard (ML-KEM) - https://csrc.nist.gov/pubs/fips/203/final
  3. NIST SP 800-38D: Recommendation for Block Cipher Modes of Operation: GCM - https://csrc.nist.gov/pubs/sp/800/38/d/final
  4. RFC 9106: Argon2 Memory-Hard Function for Password Hashing - https://www.rfc-editor.org/rfc/rfc9106

Related Articles

Scale Your Encryption

QNSQY Pro and Business are built for automation.

View Plans

Originally published at quantumsequrity.com/blog/batch-encryption-enterprise.