Files
PassKeeper/migrations/versions/a1b2c3d4e5f6_encrypt_totp_secret_at_rest.py
T

50 lines
1.5 KiB
Python

"""encrypt totp_secret at rest: widen column and add totp_iv
Revision ID: a1b2c3d4e5f6
Revises: 71d7158dd3b9
Create Date: 2026-04-18 00:00:00.000000
This migration:
1. Widens users.totp_secret from VARCHAR(64) to VARCHAR(255) to hold base64
AES-256-GCM ciphertext (plaintext secret ~32 chars → ciphertext ~64 bytes
→ base64 ~88 chars, plus GCM tag 16 bytes → up to ~120 chars; 255 is safe).
2. Adds users.totp_iv VARCHAR(64) for the base64 12-byte GCM nonce.
After running this migration you MUST run the one-time re-encryption script:
python scripts/reencrypt_totp_secrets.py
That script reads every existing plaintext totp_secret, encrypts it with the
TOTP_ENCRYPTION_KEY from .env, and writes back the ciphertext + iv.
"""
from alembic import op
import sqlalchemy as sa
revision = 'a1b2c3d4e5f6'
down_revision = '71d7158dd3b9'
branch_labels = None
depends_on = None
def upgrade():
with op.batch_alter_table('users', schema=None) as batch_op:
batch_op.alter_column(
'totp_secret',
existing_type=sa.String(length=64),
type_=sa.String(length=255),
existing_nullable=True,
)
batch_op.add_column(sa.Column('totp_iv', sa.String(length=64), nullable=True))
def downgrade():
with op.batch_alter_table('users', schema=None) as batch_op:
batch_op.drop_column('totp_iv')
batch_op.alter_column(
'totp_secret',
existing_type=sa.String(length=255),
type_=sa.String(length=64),
existing_nullable=True,
)