Key Management Policy
Key Management Policy
Project /Organization: ALAI Holding AS — Drop Payment App Policy Number: POL-SEC-KM-001 Version: 1.0 Date: 2026-02-23 Author: ALAI SecurityArchitectTeam Status: Draft Reviewers: CISO, CTO, DPO Next Review: 2027-02-23 (annual) or after Phase 2 AWS KMS integration Classification: Confidential — Restricted Distribution
Document History
| Version | Date | Author | Changes |
|---|---|---|---|
| 0.1 | 2026-02-12 | Security Agent (ALAI) | Initial standards from security audit |
| 1.0 | 2026-02-23 | Security Architect (ALAI) |
Sources: legal/ikt-sikkerhetspolicy.md §6.3, docs/SECURITY-COMPLIANCE/data-encryption-policy.md, security/security-hardening-implementation.md
1. Purpose & Scope
Purpose: This policy defines the lifecycle management requirements for all cryptographic keys and secrets used by ALAI Holding AS forin the Drop payment app,application. includingDrop generation,processes distribution,regulated storage,financial usage,data rotation,(fødselsnummer, revocation,bank andaccounts, destruction.
Regulatorydata, basis:
- records)
- requiring systematic key management per GDPR Art.
3232,— appropriate technical measures for personal data Personopplysningsloven (LOV-2018-06-15-38) § 28IKT-forskriften (FOR-2003-05-21-630) §§ 5-6- DORA
(EU) 2022/2554Art. 9(4)(d),—andencryption key management Hvitvaskingsloven (LOV-2018-06-01-23) § 30 — KYC data protection at rest
Scope: All cryptographic keys and secrets in use across:
- Production, staging, and development environments
for Drop AWS infrastructure (KMS, Secrets Manager, S3, App Runner)- All
employeecloudandinfrastructurecontractor(AWS — EEA regions, Phase 2+) - All developer workstations handling Confidential or Restricted data
- All third-party integrations where ALAI
HoldingholdsASkeysholds(Sumsub, Neonomics, Swan, BankID) - JWT signing keys, database encryption keys, TLS certificate private keys, API authentication keys
Policy Owner: Alem Bašić, CISO (security@getdrop.alem@alai.no)
Operational Owner: ALAI Platform/Security team
2. Key InventoryTypes & Purposes
2.1 CompleteCurrent KeyMVP TaxonomyKeys
| Key ID | Type | Algorithm | Purpose | |||
|---|---|---|---|---|---|---|
JWT-01 |
JWT_SECRET | env |||||
| ||||||
| ||||||
| ||||||
| ||||||
TLS-EXT |
TLS Certificate Key | ECDSA P-256 | External HTTPS (getdrop.no) | |||
| SUMSUB-01 | Webhook HMAC Key | HMAC-SHA-256 | Verify Sumsub KYC webhooks | KYC data integrity | env var |
|
| SENTRY-01 | DSN Token | Bearer token | Sentry error reporting | Error data | SENTRY_DSN env var |
2.2 Phase 2 Target Keys (AWS KMS)
| Key ID | Type | Algorithm | Purpose | Classification Protected | Owner | |
|---|---|---|---|---|---|---|
| KEK-01 | Key Encryption Key | AES-256 | Master key for database DEKs | Restricted | Security team | |
| KEK-02 | Key Encryption Key | AES-256 | Fødselsnummer encryption master | Restricted (L4) | Security team | |
| DEK-PII-* | Data Encryption Key | AES-256-GCM | Per-record PII field encryption | Confidential/Restricted | Application | |
| DEK-FNR-* | Data Encryption Key | AES-256-GCM | Fødselsnummer field encryption | Restricted | Application | |
| TLS-EXT | TLS Certificate Key | — | ||||
TLS-INT |
Ed25519 | Internal mTLS (Phase 3) | — | Platform team | ||
| JWT-02 | JWT Signing Key | RS256 (RSA-4096) or EdDSA | Asymmetric JWT signing | — | Security team | |
| BACKUP-01 | Backup Encryption Key | AES-256-GCM | Database backup encryption | Restricted | Security team | |
| SUMSUB-01 | Webhook HMAC Key | HMAC-SHA-256 | Sumsub webhook verification | KYC data integrity | Engineering | |
| NEONOMICS-01 | OAuth Client Secret | HMAC-SHA-256 | PSD2 API authentication | |||
SWAN-01 |
|
2.2 Secrets Inventory (AWS Secrets Manager)
| ||
| ||
| ||
| ||
|
3. Key Hierarchy
AWS KMS Root of Trust (eu-north-1 primary — Stockholm)
|
+-- drop-national-id-key (AES-256-GCM — annual rotation)
| +-- DEK-{user_id}-{timestamp}: Per-record envelope DEKs
| +-- Encrypts: foedselsnummer field in users table
| +-- Stored: base64(encryptedDEK || iv || tag || ciphertext)
|
+-- drop-db-master-key (AES-256 XTS — annual rotation)
| +-- Encrypts: PostgreSQL database at rest (Phase 2 — AWS RDS)
|
+-- drop-kyc-key (AES-256-GCM — annual rotation)
| +-- Encrypts: KYC document objects in AWS S3 (SSE-KMS)
|
+-- AWS KMS Root of Trust (eu-west-1 — SEPARATE REGION)
+-- drop-backup-key (AES-256 — annual rotation)
+-- Encrypts: All database backup files
AWS Secrets Manager (eu-north-1)
+-- JWT_SECRET (HMAC-SHA-256 — quarterly rotation)
| +-- Signs: Drop JWT session tokens (HS256 via jose ^6.1.3)
+-- SUMSUB_SECRET_KEY (API key — annual)
+-- BANKID_CLIENT_SECRET (OIDC client secret)
+-- DATABASE_URL (connection string)
Cloudflare / Let's Encrypt
+-- TLS Certificate (ECDSA P-256 — 90-day automated rotation)
+-- External HTTPS: getdrop.no
BankID Norge AS CA
+-- BankID Certificate (RSA-2048 — per BankID renewal schedule)
+-- Used for: BankID JWT signature verification (Phase 2)
4. Key Lifecycle
4.3.1 Lifecycle Overview
flowchartGeneration LR(CSPRNG GEN[Generation] -->|"AWS/ KMS CSPRNG"|/ DIST[Distribution]HSM)
DIST↓
-->|"RuntimeDistribution API(encrypted call\nneverchannel inonly env— files"|never STORE[Storage]plaintext)
STORE↓
-->|"Storage (KMS / Secrets Manager\naccess controlled"| USE[Usage]
USE -->|"Scheduled"| ROT[Rotation]
ROT -->|"New key active\noverlap period"| USE
ROT -->|"Old key retired"| ARCH[ArchiveManager / Revoke]env ARCHvar -->|"End— ofnever life"|in DEST[Destruction]code)
REVOKE[Emergency↓
Revocation]Usage -->|"Compromise(access detected"|controlled, DESTall USEoperations -->logged)
REVOKE↓
Rotation (scheduled — see §3.6)
↓
Revocation (on compromise — immediate)
↓
Destruction (secure erase — verified)
4.3.2 Generation
Entropy requirements:
- All keys MUST be generated using
AWS KMS oraCSPRNGcryptographically secure random number generator (CSPRNG) - Minimum entropy: 256 bits for symmetric keys
- NEVER
useuse: timestamps, UUIDs, user-supplied passphrases,timestamps, UUIDs,or predictable values as keys - NEVER generate Restricted (L4) keys in application code
for Restricted data— use AWS KMSGenerateKeyorAPIGenerateDataKey
Approved key generation methods:
| Key Type | Generation Method | |
|---|---|---|
| ||
| ||
crypto.randomBytes(32).toString('hex') (Node.js OS CSPRNG) |
||
crypto.randomBytes(32) |
||
openssl |
||
| Ed25519 | openssl genpkey -algorithm ed25519 |
JWT signing (Phase 2) |
| RSA-4096 | openssl genrsa -aes256 4096 |
Legacy JWT (Phase 2) |
| AWS KMS-managed | AWS KMS GenerateKey API |
Restricted data keys |
| HMAC-SHA-256 | crypto.randomBytes(32) as key material |
Webhook verification |
Current MVP: JWT_SECRET is generated and set as environment variable by operator at deployment. Must be cryptographically random — minimum 32 bytes.
Generation environment:environment rule:
- Keys
All KMS-managed keys forprotecting Restricteddata:(L4) data (fødselsnummer) MUST be generated within AWS KMSHSMs—key materialneverleaves AWSJWT_SECRET: generated usingcrypto.randomBytes(32)then storedinAWSapplicationSecrets ManagerAll key generation events logged in AWS CloudTrail
4.3.3 Distribution
Principles:
NEVERNever transmit keys in plaintext over any channelNEVERNever include keys in source code,config files committed to.envGit,version control, orlog outputlogsNEVERNever send keys via email, Slack, or any messaging platformAlwaysNeverfetchhardcodesecretskeysat—applicationfatalruntimeerrorfromifAWSJWT_SECRETSecretsnotManagersetorinKMSproductionAPI(enforced inauth.ts)
Distribution methods:
| Scenario | Method | |
|---|---|---|
| AWS Secrets Manager | / ||
| ||
| Developer |
.env committed to git |
|
| CI/CD |
GitHub Actions encrypted secrets ( |
|
| Third-party API keys | ||
| Emergency key recovery | Dual approval process — see §7 |
Current MVP protection: .env file excluded from git via .gitignore. JWT_SECRET fatal error if missing in production enforced in src/drop-app/src/lib/auth.ts.
4.3.4 Storage
Storage hierarchy for(Phase Drop:2 target):
Level 1 — AWS KMS HSMs(HSM-backed)
(FIPS├── 140-2KEK-01: LevelMaster 3)
+-- drop-national-id-key (foedselsnummerfor encryption)
+-- drop-db-master-key (database TDEPII — Phase 2)
+-- drop-kyc-key (KYC document S3 encryption)
+-- drop-backup-key (backupfield encryption
—├── eu-west-1)KEK-02: Master key for fødselsnummer encryption (separate key)
└── Root of trust for all derived keys
Level 2 — AWS Secrets Manager
+--├── JWT_SECRET (or JWT private key for RS256)
├── Database password (PostgreSQL)
├── Sumsub webhook HMAC signingkey
key)├── +--Neonomics SUMSUB_SECRET_KEYOAuth (APIclient key)secret
+--├── BANKID_CLIENT_SECRETSwan (OIDCOAuth secret)client +--secret
DATABASE_URL└── (connectionBankID string)client credentials
Level 3 — Application memory (ephemeral only)
+--├── Decrypted DEKDEKs during active encryption/decryption
+--└── JWT_SECRETDecrypted secrets during tokenrequest signing/verificationhandling
NOTE:Note: NEVER persist Level 3 to disk or logs
Level 4 — CI/CD (GitHub Actions secrets)
├── Staging environment secrets
└── Deployment credentials (scoped to specific environments)
Current MVP storage (pre-AWS):
JWT_SECRET: Environment variable — set at deployment by operator- Third-party API keys: Vaultwarden (vault.basicconsulting.no) for local dev, environment variables in deployment
Prohibited storage locations:
- Source code or config files in
Gitversion control (.envin git) - Application logs or Sentry error messages
(Sentry, BetterStack) UnencryptedBrowserdatabaselocalStoragecolumnsor sessionStorage- Email attachments or Slack messages
BrowserUnencryptedlocalStoragedatabaseorcolumnssessionStoragefor ContainerRestrictedimage layersdata
4.3.5 Usage
Access control principles:
| Principle | Implementation |
|---|---|
| Least privilege | |
| Separation of duties | |
| Key purpose binding | not used |
| Audit all access | |
KMSCurrent enforcement: JWT_SECRET loaded at startup only, fatal if missing. No key policyever roles:returned in API responses. Session tokens stored as SHA-256 hashes only.
| ||
| | |
| | |
| | |
| |
4.3.6 Rotation Schedule
| Key Type | Rotation Period | Method | Owner | Alert if Overdue | ||
|---|---|---|---|---|---|---|
JWT signing key () |
Security team | Yes — 7 days overdue | ||||
Database KEK (AES-256, Phase 2) |
Annual | AWS KMS automatic |
Security team | Yes — 14 days overdue | ||
| Database DEKs (PII, Phase 2) | Quarterly | Automated via key rotation API | Platform | Yes — 7 days overdue | ||
| ||||||
| ||||||
| ||||||
| TLS |
90 days | Automated ( |
Platform | Yes — 14 days before expiry | ||
| Platform | Yes — | before |||||
Sumsub webhook key |
Manual via Sumsub dashboard | Engineering | Yes | |||
| Neonomics OAuth secret | Per Neonomics policy | Via Neonomics developer portal | Engineering | Yes | ||
| Swan OAuth secret | Per Swan policy | Via Swan developer portal | Engineering | Yes | ||
| Backup encryption key (Phase 2) | Annual | Manual + dual approval | Security team | Yes — 7 days overdue |
JWT_SECRETJWT rotation overlapoverlap: procedure:
Generate newOldJWT_SECRETvalueremains Deployvalid for 24 hours after newsecretkey activation toAWSallowSecrets ManagerRolling deploy of Drop app (picks up new secret)Wait for all existingin-flight sessions toexpirecomplete.(max 24h — JWT expiry)All sessions issued with old secretUsers arenowNOTinvalidlogged—outusersonre-authenticateDelete old secret version from Secrets Manager
AWSRotation KMSmonitoring: automaticCalendar rotation:reminders for manual rotations. AWS KMS generatesrotation new key material annually while retaining all prior versionsalerts for decryptionautomated ofkeys existing(Phase ciphertext.2).
4.3.7 Revocation Procedures
Trigger conditions for immediate revocation:
- Known or suspected key compromise
(key material logged, unauthorized access) - Employee departure
with(forkeykeysmanagementinIAMpersonalrole accessknowledge) - System compromise where key was in use
DetectionRegulatoryofrequirementunauthorizedordecryptionlawinenforcementCloudTrailorder- Vendor security breach (Sumsub, Neonomics, Swan notify Drop)
Emergency JWT revocation procedure (target: < 1 hour):
Step 1: Alert Security Lead via #security-incident Slack channel
Step 2: Identify scope — which data was accessible with compromised key?
Step 3: AWS KMS: Disable compromised key (prevents new encrypt/decrypt)
Step 4: Generate replacement key via KMS CreateKey
Step 5: Re-encrypt all data protected by compromised key (Restricted first)
Step 6: Update KMS key references in application configuration
Step 7: Deploy updated configuration
Step 8: Verify all systems using new key
Step 9: Audit CloudTrail: What decrypt operations used compromised key in last 30 days?
Step 10: Assess breach notification requirement (data-breach-response-plan.md §5)
-> GDPR Art. 33 / Personopplysningsloven § 32: 72h to Datatilsynet if personal data affected
-> Finanstilsynet notification if payment data affected
Step 11: Document in incident log
Step 12: Post-mortem within 48 hours
JWT_SECRET emergency rotation (session compromise):
Step 1: Generate new JWT_SECRET immediately
Step 2: Deploy new secret to AWSproduction Secrets(zero-downtime: Managerold valid 5min overlap)
Step 3: RollingAll deployexisting Dropsessions applicationwill —be invalidated (revoke all in-flightin sessions invalidatedtable)
Step 4: All usersUsers must re-authenticate (expected UX impact — communicate via status page)
Step 5: Audit all sessions active during compromise window
Step 6: Assess if breach notification required (see data-breach-response-plan.md)
Step 7: Document in incident log
Step 8: Post-mortem within 48 hours
Database key revocation (Phase 2):
- Disable compromised key in AWS KMS
- Re-encrypt all data protected by compromised key with new key
- Priority: Restricted (L4) data first → Confidential → Internal
Certificate revocation:
- Immediately upon compromise: Revoke via CA (Let's Encrypt ACME revoke)
- Notify all certificate consumers
- OCSP response updated within 1 hour
4.3.8 Destruction
When destruction is required:
- Key has been rotated out and overlap period expired
Crypto-shredding:Systemdeleting user foedselsnummer by destroying envelope DEK (GDPR Art. 17)decommissionedSystemGDPRdecommissionederasure via crypto-shredding (destroy key → all data encrypted with it is unreadable)
Destruction methods:
| Key Location | Destruction Method | Verification |
|---|---|---|
| AWS KMS |
KMS scheduled key deletion (7- |
KMS |
| AWS Secrets Manager | Delete |
|
| Application memory | Language runtime GC (explicit Buffer.fill(0) for sensitive buffers) |
Code review |
| Local .env file | shred -vzu .env on developer machine |
Developer responsibility |
Crypto-shredding for GDPR erasure (Art. 17):Verification: WhenAfter destruction, confirm that decryption with destroyed key fails on a usertest requests account deletion:ciphertext.
Thelog:The└──ciphertextDEK-FNR-{ID}: Fødselsnummer field DEKs (foedselsnummer)quarterlybecomesrotation)permanently│unreadable└── - Encrypts: users.fodselsnummer (national ID — L4 Restricted)
│
├── KEK-03: AML/KYC Records Master (annual rotation)
│ └── DEK-AML-{ID}: AML
retention:recordtransactionDEKs │ └── Encrypts: KYC documents, AML investigation recordsretained│5├──yearsBACKUP-KEK:perBackupHvitvaskingslovenEncryption§Master (annual rotation — different KMS region) │ └── Encrypts: All database backup snapshots │ ├── TLS Root CA (managed by cert-manager / Let's Encrypt) │ ├── External TLS Certificate (*.getdrop.no — 90 day rotation) │ └── Internal mTLS Certificates (30
Destruction envelopeDocument DEKevery forkey thatdestruction user'sin foedselsnummerlegal/internkontroll.md iswith: deletedkey ID, date, reason, verification method, actor.
4. Key Hierarchy (Phase 2 Target)
AWS KMS Root (HSM-backed — EEA region)
│
├── KEK-01: General PII Encryption Master (annual rotation)
│ └── DEK-PII-{ID}: Per-record PII field DEKs (quarterly rotation)
│ └── Encrypts: name-as-stored, email, phone (if field-encrypted)
│
├── KEK-02: Fødselsnummer Master Key (annual rotation — SEPARATE from theKEK-01)
database│ 5. Key Management System
MVP (Current):
- JWT secret: environment variable with OS CSPRNG generation
- Third-party secrets: Vaultwarden (vault.basicconsulting.no) for local dev
- No formal KMS — acceptable for pre-production MVP
Phase 2 Target:
- Primary KMS: AWS KMS (
eu-north-1EEA region —Stockholm region)Backup KMS:AWS KMS (eu-west-1—IrelandIreland)orforeu-central-1Frankfurt)drop-backup-key - Secrets
management:Manager: AWS Secrets Manager for application secrets - Secondary: AWS KMS cross-region replication for disaster recovery
- HSM: AWS CloudHSM (
eu-north-1)for KEK-02 fødselsnummer — L4 Restricted data)
KMS access control (Phase 2):
| Role | Permissions | MFA Required |
|---|---|---|
key-admin |
Create, rotate, schedule deletion — NO decrypt | YES |
key-encrypt |
Encrypt only (specific key IDs) | YES |
key-decrypt |
Decrypt only (specific key IDs) | YES |
key-auditor |
List, describe, view audit logs — no crypto ops | YES |
| CI/CD pipeline | Encrypt only (staging key IDs) | N/A (service account) |
| Application service | Encrypt + Decrypt (specific keys, VPC constraint) | N/A (IAM role) |
6. Access Controls for Key Operations
Separation of duties:
| Operation | Required |
|
|---|---|---|
| Create new |
CISO + | approver (Phase 2: AWS IAM |
Documented | ||
| ||
| Rotate |
||
| Emergency revocation | CISO alone (time-critical) | Immediate + incident ticket within 1 hour |
| Destroy key | CISO + Legal (if litigation hold) | Written approval before KMS deletion |
| Grant service access to key | CISO + system owner | IAM policy review |
Current MVP: Alem Bašić (CEO/CISO) is sole key custodian. Dual approval to be implemented when team is hired (Phase 2).
7. FoedselsnummerKey FieldEscrow Encryption& — Implementation PatternRecovery
Key:Escrow policy: JWT signing key and backup encryption keys must have recovery path.
Current MVP recovery:
drop-national-id-keyJWT_SECRET(AWSrecovery:KMS — separateRe-generate fromdatabaseCSPRNG,masterredeploy.key)AllStored:usersOnlyre-authenticate.- If
src/drop-app/src/lib/encrypt.tsJWT_SECRET(is lost: Service restarts with new secret. All sessions invalidated. This is acceptable for MVP.
Phase 2 implementation)
// Envelope encryptionescrow for foedselsnummer
// Key: drop-national-id-keyKEKs (AWS KMS):
//
Stored:- AWS
base64(encryptedDEKKMS ||provides ivmulti-region || tag || ciphertext)
async function encryptNationalId(fodselsnummer: string): Promise<string> {
const iv = crypto.randomBytes(12); // 96-bit random IVredundancy — neverno reusedseparate constescrow dekneeded =for awaitKMS-only kmsClient.generateDataKey({keys
KeyId:- AWS
process.env.NATIONAL_ID_KEY_ARN,KMS KeySpec:deletion 'AES_256'has });minimum const7-day cipherwaiting =period crypto.createCipheriv('aes-256-gcm',(protection dek.Plaintext,against iv);accidental constdeletion)
ciphertext- AWS
=KMS Buffer.concat([cipher.update(fodselsnummer,CloudTrail 'utf8'),provides cipher.final()]);full constaudit tagtrail
=
cipher.getAuthTag();Phase dek.Plaintext.fill(0);2 //escrow Zerofor DEKBackup plaintextencryption key (offline):
- Key material exported encrypted from
memoryAWS afterKMS use(if //exportable) Return:OR
base64(encryptedDEK- Backup
||KMS ivkey ||replication tagto ||second ciphertext)region return(recommended Buffer.concat([dek.CiphertextBlob,for iv,KMS-native tag,keys)
ciphertext]).toString('base64');- Physical
}escrow:
Encrypted key file stored in fireproof safe + separate secure off-site copy
AccessRecovery restriction:procedure (Phase 2):
- CISO
ComplianceopensfunctionemergencyhaskeyIAMrecoveryaccessrequest (documented) - Escrow holder(s) convene
- Key material combined and imported to
KMSdrop-compliance-decrypt - All
Applicationkeycoderecoverycannoteventsdecryptloggedfoedselsnummerandexceptpost-mortemduringrequiredexplicitwithincompliance48workflows.hours
8. Audit Logging for Key Operations
All key operations loggedmust inbe AWS CloudTrail, including:logged:
- Key
creationgeneration:(actor, key ID, key type,timestamp)timestamp - Encryption/
decryptiondecryption:(actor, key ID,context,operation,timestamp)timestamp (not data content) - Key
rotationrotation:(actor, old keyversion,ID, new keyversion,ID,timestamp)timestamp - Key
disablingrevocation:/ deletion scheduling (actor, key ID, reason,timestamp)timestamp - Key destruction: actor, key ID, verification, timestamp
- Access grant/revoke: actor, grantee, key ID, permissions, timestamp
- Failed access
attemptsattempts:(actor, key ID, reason,timestamp)timestamp
Log destination:destination (Phase 2): AWS CloudTrail → S3SIEM (— immutable, append-only)only
+Current BetterStackMVP: aggregationManual log in legal/internkontroll.md for all key operations
Log retention: 5 years (AMLHvitvaskingsloven compliance§30) — Hvitvaskingslovenkey §operation 30)logs are AML-relevant
Alert on:
DecryptOff-hoursoperationsaccessbytounexpected IAM roleKEKs- Failed
KMSaccess attempts > 3 in 5 minutes Off-hoursKeyaccessdeletiontodrop-national-id-keyorscheduleddrop-kyc-keyAnyKeyrotationScheduleKeyDeletionevent (immediate alert)overdue
9. ExceptionCompliance ProcessMapping
Exceptions not permitted for: Restricted (L4) data (foedselsnummer, KYC documents) — no exceptions to field-level encryption.
Exception request process:
Submit request to: [email protected]Required: system, data classification, key being excepted, business justification, risk assessment, compensating controls, duration (max 12 months)Approval: CISOLogged in: compliance registerReview: Quarterly — exceptions > 12 months require board-level approval
Active exceptions:
| AWS KMS (Phase |
|||
| Key custodian documentation | Key |
||
| Key rotation | IKT-sikkerhetspolicy §6.3 | Rotation schedule (§3.6) | |
| Key destruction | IKT-forskriften § 5 | Destruction procedures (§3.8) | |
| Access controls | DORA Art. 9(4) | Access controls (§6) | |
| Crypto-shredding for GDPR erasure | GDPR Art. 17 | Key destruction triggers data erasure | |
| 5-year AML record retention | Hvitvaskingsloven §30 | Key retention aligned with data retention | |
| Audit trail | DORA Art. 10 | Logging (§8) |
10. Emergency Procedures — Key Compromise
Immediate response checklist (execute within 1 hour of suspected compromise):
□ Alert CISO immediately: [email protected] / +47 40 47 42 51
□ ActivateCreate incident responsechannel: — notify: Security Lead + CISO + CTO#incident-key-compromise-{DATE}
□ Identify scope:which Whichkey was compromised (JWT, database, API key)
□ Identify what data was accessible with compromised key?key
□ AWS KMS: Disable compromisedRevoke key immediately □(see For JWT_SECRET compromise: rotate immediately (all sessions invalidated)§3.7)
□ Generate replacement key
□ Re-encryptDeploy new key to all systems (zero-downtime rotation if possible)
□ For JWT: Revoke ALL active sessions (UPDATE sessions SET revoked=1)
□ For database key: Begin re-encryption of affected data protected by compromised key (Restricted data first)
□ Audit CloudTrail:logs: What wasoperations decryptedused usingthe compromised key in lastpast 30 days?
□ Assess breach notification requirement (see data-breach-response-plan.md §5)
-> GDPR Art. 33 / Personopplysningsloven § 32: 72h to Datatilsynet
-> Finanstilsynet notification if payment data affected
□ Document everything in incident log
□ Post-mortem within 48 hours
Re-encryption priority:priority (if database key compromised):
Foedselsnummer (drop-national-id-key) — Restricted (L4),: highestFødselsnummer, priorityAML records — IMMEDIATE
- Confidential (L3): Transaction data, KYC
documents (drop-kyc-key)records — Restrictedwithin (L4)4 hours
Database backup filesInternal (drop-backup-key)L2): Logs, session data — Restrictedwithin (L4)24 hours
Estimated impact of JWT compromise:
- All active user sessions must be invalidated
DatabaseAll masterusers (drop-db-master-key)must — Phase 2re-authenticate
- Expected customer impact: temporary app disruption
- Communication: In-app notification + email explaining security measures taken
Approval
Role
Name
Date
Signature
Author
ALAI Security ArchitectTeam
2026-02-23
CISO
Alem Bašić
CTO
Alem Bašić
DPO (GDPRcompliance relevance)
TBD — appointment required
Management
Alem Bašić