HelloJohn / docs
Security

Encryption

How HelloJohn encrypts data at rest and in transit — field-level encryption, TLS, password hashing, and self-hosted recommendations.

Encryption

HelloJohn protects sensitive data through multiple encryption layers: TLS for data in transit, field-level encryption for secrets, and bcrypt/Argon2 for passwords. This page describes exactly what is encrypted and how.


Data in Transit

All communication between clients and HelloJohn uses TLS 1.2+. TLS 1.3 is preferred and enforced when both parties support it.

ConnectionEncryption
Browser → HelloJohn APITLS 1.3 (HTTPS)
Your backend → HelloJohn APITLS 1.3 (HTTPS)
HelloJohn → your webhook endpointTLS 1.2+ (HTTPS)
HelloJohn → email provider (SMTP)STARTTLS or TLS
HelloJohn → PostgreSQLTLS (configurable)
HelloJohn → RedisTLS (configurable)

HTTP requests are automatically redirected to HTTPS. Plain HTTP is not accepted on any production endpoint.


Password Hashing

HelloJohn never stores passwords in plaintext or reversibly encrypted form. Passwords are hashed using Argon2id (memory-hard, resistant to GPU and side-channel attacks):

ParameterValue
AlgorithmArgon2id
Memory cost64 MB
Iterations3
Parallelism4
Output length32 bytes

Older deployments using bcrypt (cost factor 12) are migrated to Argon2id on next password change.

Passwords are never logged, included in error messages, or transmitted to third parties.


Sensitive Field Encryption

Certain fields are encrypted at the application layer before writing to the database, using AES-256-GCM:

FieldEncrypted
OAuth client secrets (provider credentials)✅ Yes
SMTP passwords✅ Yes
TOTP backup codes✅ Yes
Webhook signing secrets✅ Yes
Refresh tokens (stored value)✅ Yes — hashed (SHA-256)
User emails⬜ No — stored plaintext, searchable
User names⬜ No
Session metadata⬜ No

The encryption key is derived from HELLOJOHN_ENCRYPTION_KEY. If this key is rotated, all encrypted fields must be re-encrypted (see Key Rotation).


JWT Signing

Access tokens and refresh tokens are signed with Ed25519 (EdDSA). Signing is not encryption — tokens are Base64-encoded and readable, but cannot be forged without the private key.

Tokens do not contain passwords, secrets, or sensitive PII beyond the user ID and claims you configure.

See JWT Security for full details.


Database Encryption

Cloud-Hosted (HelloJohn-managed)

HelloJohn's managed infrastructure uses AES-256 encryption at rest on all storage volumes, managed by the cloud provider (AWS EBS, GCP PD).

Self-Hosted Recommendations

For self-hosted deployments, enable PostgreSQL column-level encryption or full-disk encryption:

Option 1: Full-disk encryption (Linux)

# Using dm-crypt / LUKS (set up at provisioning time)
cryptsetup luksFormat /dev/sdb
cryptsetup open /dev/sdb pg_data
mkfs.ext4 /dev/mapper/pg_data

Option 2: PostgreSQL TDE (Transparent Data Encryption)

Available on PostgreSQL Enterprise and some forks (Percona, EDB). Standard community PostgreSQL does not include native TDE.

Option 3: Managed database with encryption at rest

Use a managed PostgreSQL provider that encrypts at rest by default:

ProviderEncryption at rest
NeonAES-256 (AWS)
SupabaseAES-256 (AWS)
Amazon RDSAES-256 (optional, enable in settings)
Google Cloud SQLAES-256

For Amazon RDS, enable encryption at creation:

aws rds create-db-instance \
  --db-instance-identifier hellojohn-db \
  --storage-encrypted \
  --kms-key-id arn:aws:kms:us-east-1:123456789:key/your-key-id \
  # ... other options

Encryption Key Rotation

Application Encryption Key

The HELLOJOHN_ENCRYPTION_KEY encrypts sensitive fields (OAuth secrets, SMTP passwords, backup codes, webhook secrets).

To rotate:

  1. Generate a new 32-byte key:

    openssl rand -base64 32
  2. Set both the old and new key in the environment:

    HELLOJOHN_ENCRYPTION_KEY=new_key_base64
    HELLOJOHN_ENCRYPTION_KEY_PREVIOUS=old_key_base64
  3. Run the key rotation migration:

    hj admin rotate-encryption-key
  4. After migration completes, remove HELLOJOHN_ENCRYPTION_KEY_PREVIOUS.

HelloJohn re-encrypts all sensitive fields using the new key. During the rotation window, both keys are accepted for reads.

JWT Signing Key

See Key Rotation for JWT signing key rotation procedure.


Backup Encryption

Encrypt database backups before storing off-site:

# Encrypt backup with GPG
pg_dump --format=custom --compress=9 --dbname="$DATABASE_URL" \
  | gpg --symmetric --cipher-algo AES256 \
  > hellojohn_$(date +%Y%m%d).dump.gpg

# Decrypt to restore
gpg --decrypt hellojohn_20240120.dump.gpg \
  | pg_restore --dbname="$RESTORE_DATABASE_URL"

Or use S3 server-side encryption:

aws s3 cp hellojohn.dump \
  s3://your-backup-bucket/hellojohn.dump \
  --sse aws:kms \
  --sse-kms-key-id arn:aws:kms:us-east-1:123456789:key/your-key-id

What Is Not Encrypted

For performance and searchability, some fields are stored in plaintext:

  • User email addresses (required for lookups and matching)
  • User display names
  • Session metadata (IP addresses, user agents — unless you disable collection)
  • Audit log entries

If your compliance requirements mandate encrypting user emails, use the Backend Proxy Pattern so HelloJohn never receives raw emails — only your system does.


On this page