---
title: "Security & Audit"
space: "Digital Signing"
url: "https://www.prilk.com/docs/digital-signing/security-audit"
updated: "2026-05-15"
---

## Security & Audit

How keys are protected, what's logged, and what notifications signers receive.

### Key storage

| Key material | Storage |
|---|---|
| CA private key | Encrypted in database (Fernet/AES via Frappe Password field) |
| Signer's keystore | Encrypted in database (Fernet/AES via Frappe Password field) |
| Signer's keystore password | Encrypted in database (Fernet/AES via Frappe Password field) |

**No private key material is stored as files on disk.** During the signing operation, keys are written to a temporary file, used, and deleted immediately. The Frappe encryption key (in `site_config.json`) is the master secret protecting everything; treat it like the root encryption secret of the site.

### Audit trail — Signature Log

Every signing attempt (success **or** failure) is recorded in **Signature Log** with:

| Field | Detail |
|---|---|
| Document reference | DocType + name (e.g., `Sales Order / SO-0042`) |
| Signer | User + full name |
| Certificate serial | The X.509 serial used |
| Timestamp | When the signing occurred |
| IP address | Where the signing originated |
| Status | Success / Failed |
| SHA-256 hash | Of the signed PDF — detects post-signing file tampering |
| Error message | If failed |

The Signature Log is **append-only** — no edits, no deletes via the desk UI.

### Email notifications

After every successful signing, the signer receives an email containing:

- Which document was signed (with link)
- When it was signed (UTC + signer's timezone)
- From which IP address
- Which certificate was used (serial)

The email includes a warning to **contact the administrator immediately if the signing wasn't initiated by them**. This is the primary tripwire if 2FA is bypassed or credentials are stolen.

### 2FA enforcement

2FA is the second factor that gates every signing. Without it, a stolen password would allow unlimited signings.

- Set per-DocType in **Signable DocTypes → Require 2FA** (recommended: always on)
- Enforced globally for signers via **System Settings → Two Factor Authentication**
- TOTP via authenticator app — no SMS option (SIM-swap risk)

### CA private key — operational guidance

Your CA private key is the trust anchor. If compromised, an attacker could issue fake certificates that look like they came from you.

- The key is stored encrypted in the database (Frappe Password field)
- The Frappe encryption key (in `site_config.json`) is the actual secret — back up separately, restrict file permissions
- Rotate the CA every 5–10 years; plan a transition where both old and new CAs are trusted by verifiers
- For higher security, consider an air-gapped CA — generate certificates offline and import to the database

### Auditing checklist

| Question | Where to look |
|---|---|
| Who signed document X? | Document form → "Signed by" field, or Signature Log |
| Did anyone fail to sign in the last 24 hours? | Signature Log → filter Status = Failed, Date = today |
| Are there expired certificates still on the system? | Signing Certificate List → filter Status = Expired |
| Has the CRL been published recently? | Signing Settings → CRL Last Generated timestamp |
| Has the CA private key been accessed recently? | Frappe Activity Log on Signing Settings DocType |

### Backup considerations

- **Database** (encrypted at rest by your hosting provider) contains all key material
- **`site_config.json`** contains the Frappe encryption key — back up separately, restrict to fewest people
- A backup without the encryption key is **useless** — you can't decrypt keystores
- Test your restore process annually

### Related

- [Verifying a Signature](/docs/digital-signing/verifying-signature) — integrity guarantees in detail
- [Signers & Certificates](/docs/digital-signing/signers-certificates) — revocation flow
