Skip to content

Document Encryption

WPsigner encrypts all uploaded documents and signature images at rest using AES-256-GCM, the same encryption standard used by banks and government agencies. This ensures that even if your server’s filesystem or database is compromised, your documents remain unreadable.

When a document is uploaded to WPsigner:

  1. Random filename generated — A cryptographically random 128-bit filename replaces the original
  2. File encrypted — AES-256-GCM encrypts the file contents with a unique IV (initialization vector)
  3. Stored securely — The encrypted file is saved with a .enc extension
  4. Decrypted on demand — Only when an authorized user requests the file
LayerProtection
EncryptionAES-256-GCM (authenticated encryption)
FilenameRandom 128-bit hex (impossible to guess)
Access control.htaccess blocks direct URL access
Directory listingindex.php prevents browsing
ContentEncrypted?
Uploaded PDF documents✅ Yes
Signature images✅ Yes
Completed signed PDFsGenerated on-the-fly
Database recordsNo (metadata only)

WPsigner derives its encryption key automatically from your WordPress security salts (AUTH_KEY and SECURE_AUTH_SALT in wp-config.php). This works out of the box, but has one risk: if those salts are ever regenerated, all encrypted documents become permanently unreadable.

Defining WPS_ENCRYPTION_KEY in your wp-config.php eliminates this risk entirely:

ScenarioWithout WPS_ENCRYPTION_KEYWith WPS_ENCRYPTION_KEY
Normal operation✅ Works✅ Works
WordPress salts rotatedDocuments lost✅ No impact
Security plugin regenerates saltsDocuments lost✅ No impact
Migrate to new server⚠️ Must copy exact salts✅ Just copy the key
Multiple environments⚠️ Must sync salts✅ Share one key

[!CAUTION] WordPress security plugins like Solid Security (iThemes), Wordfence, and SG Security can regenerate salts with a single click. If you haven’t defined WPS_ENCRYPTION_KEY, this will make all your encrypted documents permanently inaccessible.


WPsigner shows a generated key in the admin notice. You can also generate one manually:

Using WP-CLI:

Terminal window
wp eval "echo base64_encode(random_bytes(32));"

Using PHP:

echo base64_encode(random_bytes(32));

This produces a 44-character Base64 string like a8f3c9d1e6b20a4f7b8c2d3e4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3g==.

Open your wp-config.php file and add this line before the line that says /* That's all, stop editing! */:

define('WPS_ENCRYPTION_KEY', 'your-generated-key-here');

[!IMPORTANT] Store your encryption key in a secure location (password manager, encrypted note, or offline backup). If you lose this key and need to reinstall WordPress, your encrypted documents cannot be recovered.

Recommended backup locations:

  • Password manager (1Password, Bitwarden, etc.)
  • Encrypted USB drive
  • Printed and stored in a safe
  • Your hosting provider’s secret management

After adding the key, go to any WPsigner admin page. The security recommendation notice should disappear, confirming that WPsigner is now using your dedicated key.


WPsigner checks for encryption keys in this order:

PrioritySourceWhere it lives
1 (highest)WPS_ENCRYPTION_KEY constantwp-config.php (filesystem)
2 (fallback)Derived from WordPress saltswp-config.php (filesystem)

In both cases, the key never touches the database. It exists only in wp-config.php on the filesystem, protecting against SQL injection attacks.


If WPsigner detects that your WordPress salts have changed (and you haven’t defined WPS_ENCRYPTION_KEY), it will show a critical red notice in the admin:

🚨 WPsigner — Encryption Key Changed WordPress security salts have been regenerated. Previously encrypted documents cannot be decrypted with the current salts.

  1. Restore original salts — Find the original AUTH_KEY and SECURE_AUTH_SALT values from a backup of your wp-config.php and restore them
  2. If no backup exists — The encrypted documents are permanently lost. You can dismiss the notice to reset the key for future documents

The best prevention is to define WPS_ENCRYPTION_KEY before any salt rotation occurs. Once defined, salt changes have zero impact on document encryption.


ParameterValue
AlgorithmAES-256-GCM
Key size256 bits (32 bytes)
IV size96 bits (12 bytes, per NIST recommendation)
Authentication tag128 bits (16 bytes)
Key derivationHMAC-SHA256 (when using salt fallback)
  • Authenticated encryption — Detects any tampering with encrypted data
  • NIST approved — Standard for US government classified information
  • Performance — Hardware-accelerated on modern CPUs (AES-NI)
  • No padding oracle attacks — GCM mode is immune to these

Encrypted files are stored as:

Base64( IV (12 bytes) + Auth Tag (16 bytes) + Ciphertext )

The IV is generated using PHP’s random_bytes() (CSPRNG) for each encryption operation, ensuring no two files share an IV.


What happens if I change my WPS_ENCRYPTION_KEY?

Section titled “What happens if I change my WPS_ENCRYPTION_KEY?”

All previously encrypted documents will become unreadable. Only change this key if you have no existing encrypted documents, or if you’re prepared to lose access to them.

Encryption is applied automatically when the OpenSSL extension is available (which is standard on all modern PHP installations). If OpenSSL is not available, files are stored without encryption with a warning in the logs.

Minimally. AES-256-GCM with hardware acceleration (AES-NI) encrypts at several GB/s. For typical documents (1-10MB), the overhead is imperceptible.

Is the encryption key exposed in the database?

Section titled “Is the encryption key exposed in the database?”

No. Whether you use WPS_ENCRYPTION_KEY or the salt-derived fallback, the key exists only in wp-config.php on the filesystem. A database breach (SQL injection) cannot expose the encryption key.