Trust Center

Encryption Policy

Cryptographic standards, algorithms, and key-management practices.

Effective: 2026-05-21Owner: Howell & Gibbs LLCStatus: v1 — initial publicationDownload PDF

SendTax protects customer data with layered encryption — application-layer envelope encryption over per-document keys, transport encryption everywhere, and managed key custody in Google Cloud KMS. This policy is a companion to our Information Security and Access Control policies.

Items marked Roadmap are not yet in production.


1. Purpose

This policy defines the cryptographic standards SendTax uses to protect customer data, and the key-management practices that govern how those cryptographic operations are controlled. It supports the commitments made in our Information Security policy and aligns with SOC 2 Common Criteria CC6.1 and CC6.7.


2. Scope

This policy applies to all cryptographic operations performed by or on behalf of SendTax, including:

  • Encryption of customer data at rest (documents, database storage, backups).
  • Encryption of data in transit (between clients, application servers, and sub-processors).
  • Hashing of credentials and other sensitive values.
  • Cryptographic key generation, storage, use, rotation, and destruction.
  • Cryptographic implementations in source code authored by SendTax.

It does not govern the internal cryptographic implementations of our sub-processors (Clerk, Fly.io, Google Cloud, Cloudflare, Resend, Sentry, Modal), which are governed by the providers' own security programs and compliance certifications. Where we rely on a sub-processor for a cryptographic primitive — most notably KEK custody and TLS termination — that reliance is explicit in the relevant section below.


3. Definitions

TermMeaning
AEADAuthenticated Encryption with Associated Data. Provides confidentiality and integrity in a single primitive.
AADAdditional Authenticated Data. Public context (e.g., document and filer IDs) cryptographically bound to a ciphertext at encryption time.
DEKData Encryption Key. A symmetric key used to encrypt a single unit of data (e.g., one document).
KEKKey Encryption Key. A long-lived key used to wrap (encrypt) DEKs. KEKs are not used to encrypt data directly.
Envelope encryptionPattern in which data is encrypted by a per-record DEK, and the DEK itself is encrypted by a KEK.
HSMHardware Security Module. A tamper-resistant device that performs cryptographic operations without exposing key material.
KMSKey Management Service. A managed service that custodies KEKs and performs wrap/unwrap operations. SendTax uses Google Cloud KMS.

4. Approved algorithms and minimum strengths

SendTax uses only modern, widely reviewed cryptographic algorithms at minimum strengths consistent with current NIST guidance. New cryptographic code must use one of these primitives.

PurposeApproved primitiveMinimum strength
Symmetric authenticated encryptionAES-256-GCM (12-byte nonce, AEAD with AAD binding)256-bit key
Key wrappingGCP Cloud KMS (AES-256-GCM under the hood, HSM-backed available)256-bit key
Transport encryptionTLS1.2 or higher (TLS 1.3 preferred)
Password hashingbcryptProvider default (Clerk)
Token signingRS256 / ES256 (handled by Clerk for authentication JWTs)n/a
Cryptographic hashingSHA-256 or SHA-512256-bit output
Random number generationOS-provided CSPRNG (Python secrets, Node crypto.randomBytes, the cryptography library's secure RNG)n/a

Selection rationale: AES-256-GCM provides authenticated encryption in a single primitive and is FIPS-approved. Password hashing is performed by Clerk, our identity provider; SendTax does not store user passwords directly and retains bcrypt only as a residual library dependency.


5. Prohibited algorithms

The following algorithms and protocols are not used in any production code path:

  • MD5 (collision-broken; not approved even as a non-cryptographic checksum in this codebase, to avoid confusion).
  • SHA-1 and HMAC-SHA-1 (collision-broken; non-cryptographic uses such as integrity checksums in package manifests are acceptable).
  • DES, 3DES / Triple DES (insufficient key length, deprecated by NIST).
  • RC4 (biased keystream).
  • TLS 1.0 and TLS 1.1 (deprecated by IETF RFC 8996).
  • SSL (all versions).
  • ECB mode for any block cipher.
  • AES-CBC without integrity — if AES-CBC is ever required by a third-party integration, it must be accompanied by an explicit HMAC.

As of the effective date of this policy, no prohibited algorithm appears in any SendTax source code or production configuration. This was confirmed by codebase audit on 2026-05-21 and will be re-verified at each policy review and whenever a new third-party library with cryptographic dependencies is added.

Adoption of any prohibited algorithm — for example, to integrate with a third party that mandates one — requires a documented exception under § 12.


6. Encryption in transit

6.1 Public-facing traffic

All traffic between end-user clients, our application services, and our public APIs is encrypted using TLS 1.2 or higher, with TLS 1.3 preferred where supported by the client. TLS termination is performed at the Fly.io edge.

HTTP Strict Transport Security (HSTS) is enabled on public web properties, and HTTP requests are redirected to HTTPS. Certificates are issued and rotated automatically by our hosting provider; SendTax does not manage long-lived certificate private keys directly.

6.2 Service-to-service traffic

  • Communication between SendTax application services occurs over Fly.io's private network (fly-internal) and is not exposed to the public internet.
  • Database connections from the application to PostgreSQL use TLS within the Fly.io private network.
  • Outbound calls to managed sub-processors (Clerk, Google Cloud KMS, Cloudflare R2, Resend, Sentry, Modal) use the providers' published HTTPS endpoints with TLS 1.2 or higher.

6.3 Configuration

We do not pin specific cipher suites at the application layer; we rely on the secure defaults of our TLS implementations (Fly.io edge, Python ssl, Node.js tls), which exclude all algorithms listed in § 5. Underlying runtimes enforce TLS 1.2 or higher by default.


7. Encryption at rest

Customer data is protected by multiple layers of encryption at rest.

7.1 Application-layer envelope encryption (customer documents)

Documents uploaded to SendTax (tax forms, identity documents, supporting records, prepared returns) are encrypted by SendTax application code before they are written to object storage. The scheme is:

  1. A unique 256-bit DEK is generated for each document using a cryptographically secure random source.
  2. The document is encrypted with the DEK using AES-256-GCM, with a freshly generated 12-byte nonce.
  3. The DEK is wrapped (encrypted) by the production KEK held in Google Cloud KMS.
  4. The wrap operation is bound to Additional Authenticated Data (AAD) of the form sendtax-doc/v2/{document_id}/{filer_id}. KMS refuses to unwrap the DEK if a different AAD is supplied at decrypt time, and the AEAD ciphertext itself also incorporates the AAD — making ciphertext substitution across documents detectable.
  5. The wrapped DEK is stored in the database alongside the document record, with a versioned magic prefix (\x00sendtax-v2\x00) so future format upgrades can be made transparently.

The same envelope-encryption scheme is used for Friends & Family upload blobs (AAD: sendtax-ff/v2/{upload_id}) and anonymized training data contributions (AAD: sendtax-training/v2/{contribution_id}).

This scheme is implemented using the cryptography library's AESGCM primitive (an authenticated encryption mode reviewed and recommended by cryptographers).

7.2 Storage-layer encryption

Cloudflare R2 provides an additional layer of AES-256 encryption at rest by default. Customer documents are therefore encrypted twice: once by the SendTax application before upload, and once by R2 as a baseline storage primitive.

Customer data not held in object storage — profiles, return data, audit logs, tenant relationships — resides in PostgreSQL. Encryption at rest for the database and its backups is provided transparently by Fly.io Managed Postgres per Fly.io's published terms. SendTax does not maintain a separate backup pipeline outside the managed service.

7.3 Endpoint encryption

Devices used by SendTax personnel to access customer data have full-disk encryption enabled (Apple FileVault). See the Access Control Policy.

7.4 Application secrets

Application secrets (API keys, database credentials, KMS configuration) are stored in:

  • Fly.io encrypted secrets — for runtime-injected secrets, scoped per environment (development, staging, production).
  • 1Password vaults — for human-accessible operator credentials, segmented by environment (Clerk-Dev, Clerk-Staging, Clerk-Production, and equivalents).

No production secrets are stored in source control. Automated secret-scanning runs in CI on every change.


8. Key management

8.1 Key generation

  • DEKs are generated by the application using the cryptography library's secure RNG, which delegates to the OS CSPRNG.
  • KEKs are generated by Google Cloud KMS within its own cryptographic boundary. SendTax never sees raw KEK material.

8.2 Key storage and access

  • Production KEKs are stored exclusively in Google Cloud KMS. The underlying key material does not leave the KMS boundary; only wrap and unwrap operations are exposed to SendTax services.
  • Hardware Security Module (HSM) backing for production KEKs is supported by the implementation (dual-key configuration). Migration to an HSM-protected key tier is on our roadmap. (Roadmap)
  • Development KEKs are local AES-256 keys configured via the ENCRYPTION_LOCAL_KEK_HEX environment variable. Local keys are used only against development databases containing synthetic data.

8.3 Authentication to the key management service

SendTax services authenticate to Google Cloud KMS using Workload Identity Federation. No long-lived service-account key files are stored on application servers. A long-lived service-account key (GCP_SA_KEY_B64) is supported as a fallback authentication mode but is not the production default.

8.4 Key rotation

  • KEKs. Google Cloud KMS supports both operator-initiated and automatic key rotation. Because DEKs are wrapped — not encrypted directly — by the KEK, the KEK can be rotated without re-encrypting customer documents: new DEKs are wrapped under the current KEK version, while existing wrapped DEKs continue to be unwrappable under their original KEK version. We are moving toward annual automatic KEK rotation in GCP KMS; until that is enabled, KEK rotation is operator-initiated and follows the review cadence above. (Roadmap)
  • DEKs. A new DEK is generated for every document. DEKs are used exactly once and are never reused across documents or rotated periodically; the per-document scheme makes periodic DEK rotation unnecessary.
  • Application secrets. Rotated as part of the secret-rotation procedure documented in our internal runbooks, and additionally whenever a leak is suspected or a team member with access offboards.

8.5 Key destruction

  • DEKs in memory are released by the cryptography library's standard lifecycle handling and are not persisted in plaintext.
  • Wrapped DEKs at rest exist only in the database row associated with their document. When a document is deleted (§ 4.3 of the Data Retention and Deletion Policy), the row is removed and the wrapped DEK is destroyed with it. Because each DEK is unique to its document, this is sufficient to render the document's ciphertext unrecoverable from SendTax systems, independent of R2 object propagation.
  • Retired KEK versions in Google Cloud KMS may be destroyed according to GCP KMS's destruction lifecycle (24-hour soft-delete followed by destruction). SendTax does not currently use KMS key-version destruction as a routine disposal mechanism, since per-document DEK uniqueness already provides per-document unrecoverability. KMS key-version destruction remains available for bulk-deletion scenarios that may arise (for example, mass tenant offboarding) and would render all documents wrapped under that KEK version simultaneously unrecoverable.
  • Application secrets are revoked at the source (provider console or 1Password) on rotation; references in Fly.io encrypted secrets are overwritten in the same change.

9. Customer-managed encryption keys

SendTax does not currently offer customer-managed encryption keys (also referred to as BYOK or CMK). All cryptographic keys protecting customer data are generated, stored, and operated by SendTax in Google Cloud KMS as described in § 8.

This is a deliberate scope decision for the current product. Customer-managed key support is not on our current roadmap and would require changes to the application's key-selection layer before it could be supported.


10. Cryptographic library policy

SendTax uses only well-maintained, widely-reviewed cryptographic libraries, and does not introduce custom or "rolled-our-own" cryptographic primitives. The current inventory is:

LibraryUsed for
cryptography (Python)All application-layer encryption (AESGCM from hazmat.primitives.ciphers.aead).
passlib[bcrypt] (Python)Bcrypt password hashing (residual; authentication is delegated to Clerk).
Google Cloud KMS clientKey wrap/unwrap operations.
Browser / runtime native cryptoFrontend cryptographic operations (limited; no direct crypto-library dependencies on the frontend).

All cryptographic randomness (DEKs, nonces, tokens, salts) is sourced from the operating system's CSPRNG via these libraries. Non-cryptographic randomness may use standard PRNGs but must not be used for any security-relevant purpose.

Dependencies are scanned automatically in CI for known vulnerabilities; cryptographic-library security advisories are treated as high priority and patched on an expedited schedule.


11. Audit and verification

  • A codebase audit on 2026-05-21 confirmed no usage of any algorithm listed in § 5.
  • This audit will be re-run at each policy review and any time a new third-party library is added that performs cryptographic operations.
  • Findings from each audit, and any required remediation, are recorded internally.

12. Exceptions

Adoption of any algorithm or practice that deviates from this policy — including, but not limited to, integrating with a third party that mandates a prohibited algorithm — requires:

  1. Written justification describing the business need and the threat model.
  2. Approval from a second SendTax operator.
  3. A removal target date for any prohibited algorithm, or an explicit acknowledgment that the exception is permanent for a specific bounded use case.
  4. Compensating controls (e.g., wrapping the prohibited primitive inside an approved authenticated layer) where technically possible.

Exceptions are reviewed at the next policy review and are not allowed to become indefinite without explicit re-authorization.


13. Post-quantum cryptography

SendTax monitors developments in post-quantum cryptography and will evaluate and adopt post-quantum algorithms as NIST migration guidance and supporting library, runtime, and hosting-provider tooling mature. Symmetric encryption at the strength used by SendTax (AES-256) is expected to remain secure against foreseeable quantum attacks; the primary migration target is the asymmetric cryptography used in transport-layer key exchange, which is largely handled by our hosting and sub-processor providers rather than by SendTax application code.


14. Enforcement

Violations of this policy may result in revocation of access, termination of employment or contract, and, where applicable, civil or criminal referral.


15. Related policies


16. Document control

This policy is reviewed at least semi-annually, and additionally whenever a new cryptographic library is introduced, a primitive in § 4 is deprecated by NIST or IETF, or a material change to our key-management architecture ships. Material changes are noted in the version line at the top of this document.


17. Contact

Security disclosures[email protected]
Cryptography questions[email protected]
General[email protected]
Operating entityHowell & Gibbs LLC