Data Protection and Encryption in Practice Questions
Protecting data at rest and in transit across real systems from an engineering rather than pure-cryptography standpoint. Covers encryption strategy and key management for stored and transmitted data, secrets and sensitive-data handling, tokenization and secure elements for payment and sensitive data, and secure data handling in application code. Applied data-protection controls, distinct from cryptographic primitive design and from privacy-regulation compliance.
List and justify the controls you would put in place to protect backups and disaster-recovery artifacts from ransomware and malicious tampering, covering both on-premise and cloud environments.
Sample Answer
Direct answer
The core defense against ransomware and tampering is making backups immutable and logically isolated from anything a compromised production credential can reach; encryption alone protects confidentiality but does nothing to stop an attacker from deleting or overwriting a backup, since that is an availability and integrity problem, not a confidentiality one.
Structured elaboration
- Immutability (WORM: write-once-read-many) storage. Use object-lock retention policies on cloud object storage, or an equivalent on-premise WORM or tape solution, so that even a compromised administrator credential cannot delete or modify a backup within its retention window. This is the single highest-leverage control here, because modern ransomware playbooks specifically target backups before encrypting production.
- Air-gapped or logically isolated copies. Keep at least one copy in a separate account, tenant, or credential domain that production credentials cannot reach, or a genuinely offline copy such as tape rotated off-site. This defends against the common pattern of an attacker compromising backup-management credentials before triggering the actual ransomware payload.
- Least-privilege, separate credentials for backup operations, with multi-factor or hardware-key-gated approval required to shorten a retention lock or delete a backup early. This prevents a single stolen credential from being sufficient to destroy the recovery path.
- Versioned backups with checksum verification and automated integrity scanning, to detect tampering or partial corruption before you rely on a backup during an actual incident, rather than discovering the problem mid-recovery.
- Regular restore testing, actually decrypting a backup and validating it at the application level, not just confirming a backup job completed: an untested backup is an assumption, not a control.
- Monitoring and alerting on anomalous backup deletion or retention-policy changes, since a burst of delete calls against a backup bucket is a strong, cheap-to-detect signal of an attack in progress.
- On-premise specific hardening: physically separate backup media, such as tape rotated off-site or a dedicated backup appliance not reachable from the general network, and a hardened, minimal backup-server operating system, since a general-purpose server on the same network domain as production is itself a common ransomware pivot point.
Worked example
An attacker obtains a compromised administrator credential and attempts to destroy the last 30 days of backups before triggering ransomware on production. Object-lock retention blocks the deletion outright, even with valid admin credentials, because the retention policy itself cannot be shortened without a separate, MFA-gated approval the attacker doesn't have. The backup storage account uses a distinct identity from production, so the compromised production credential has no path to it at all. The anomalous burst of failed delete calls trips an alert, giving the security team early warning before the ransomware payload executes on production.
Trade-offs and pitfalls
Immutability and long retention windows cost storage and reduce operational flexibility, you cannot clean up backups early even when you legitimately want to, by design. Air-gapped copies add operational overhead and can lengthen recovery time. Both are deliberate trade-offs against ransomware resilience, and the retention length should be set against realistic storage cost and actual regulatory or business recovery requirements, not left at a default.
What is a Hardware Security Module, and how does it differ from a software key store or a cloud-managed key vault? Give two scenarios where an HSM is the right call and two where a managed key vault is more practical for an enterprise.
Sample Answer
Direct answer
A Hardware Security Module (HSM) is a dedicated, tamper-resistant device, physical or a dedicated cloud-rented unit, purpose-built so that raw cryptographic key material never leaves its protected boundary, even to the administrators operating it. A software key store keeps keys somewhere on a general-purpose machine, so anything with sufficient access to that machine can eventually reach the key in use. A cloud-managed key vault, a standard cloud KMS (Key Management Service), sits in between: a managed service usually backed by shared, provider-operated HSM-class hardware, giving you HSM-grade protection without owning or operating the hardware yourself.
Structured elaboration
Physical and tamper protection. An HSM is validated against a recognized hardware security standard, commonly FIPS 140-2 or 140-3 (Federal Information Processing Standards, a US government hardware-security certification), meaning it has been independently tested to resist physical and logical tampering and to zeroize, erase, its keys if tampering is detected. A software key store has no such physical protection; its security is only as strong as the general-purpose machine's operating system and access controls, which is meaningfully weaker. A cloud-managed key vault typically sits on validated HSM hardware on the provider's side, often shared across tenants by default, with a dedicated, single-tenant HSM tier usually available at a higher cost for workloads that need it.
Attestation and compliance features. HSMs, and dedicated cloud HSM tiers, can provide cryptographic attestation that a key was generated and has always lived inside validated hardware, which specific regulatory regimes, certain government or financial-sector requirements in particular, explicitly require rather than accepting a software-only or shared-tenancy guarantee.
Bring-your-own-key versus provider-managed. With a cloud key vault you can typically choose a provider-generated and provider-held key, the simplest option with the least control, or bring your own key (BYOK), generating the key material yourself, often in your own HSM, and importing it into the vault. BYOK gives more control and an independently trusted generation source, but adds the responsibility of generating and transporting that key material without ever exposing it in transit.
Two scenarios where an HSM is the right call:
- A strict regulatory or contractual requirement mandates dedicated, single-tenant, independently validated hardware with attestation, common for payment-network root-key operations, certain government workloads, or protecting a certificate authority's root signing key, where that one key's compromise would be catastrophic.
- An extremely high-value signing operation, such as a code-signing root key, where the operational cost of dedicated hardware is clearly justified by how severe a compromise of that single key would be.
Two scenarios where a managed key vault is more practical:
- Typical application-level encryption needs, envelope-encrypting a database's data keys or encrypting object storage, where strong protection with minimal operational overhead is the goal; this is the common default recommendation for most application-level key management, precisely because it hits that balance.
- A fast-moving team without dedicated hardware-security operational expertise, where standing up and maintaining physical or dedicated cloud HSM infrastructure, provisioning, patching, physical security procedures, specialized on-call knowledge, would be a real distraction from the product work, and the vault's shared-HSM-backed default tier already meets the vast majority of real threat models.
Worked example
A quick decision check: a fintech company issuing its own root certificate authority key for signing every device certificate in its fleet should use a dedicated HSM, because that one key's compromise would let an attacker impersonate any device in the fleet, an unacceptable blast radius for shared infrastructure. The same company's application team encrypting customer records in its primary database should use the default cloud KMS tier, because the operational simplicity and existing audit logging already meet the actual threat model for that data, and standing up dedicated HSM infrastructure for it would add real cost without a corresponding reduction in realistic risk.
Trade-offs and pitfalls
Provisioning a dedicated HSM "just to be safe" for a workload whose real threat model is already met by a shared cloud KMS adds real cost and operational complexity without a matching risk reduction. The opposite mistake, storing a genuinely high-value root key in a software-only key store because setting up a vault or HSM felt like more work, creates the single highest-value target in the whole security architecture with the weakest protection available.
What is format-preserving encryption, and what problem does it solve that standard symmetric encryption modes do not? Name common approaches and explain the security trade-offs involved in preserving format.
Sample Answer
Direct answer
Format-preserving encryption (FPE) is a mode of encryption that produces ciphertext in exactly the same format as the plaintext, the same character set and length, so encrypting a 16-digit credit card number produces another 16-digit number rather than the binary-looking blob standard modes like AES-GCM produce. It solves the problem of encrypting data that has to keep flowing through rigid legacy schemas, database columns, and validation rules that a normal ciphertext blob would break.
Structured elaboration
The problem it solves. Many legacy systems, database columns typed as a fixed-length numeric field, or downstream validators expecting a specific pattern, weren't built to accept an arbitrary-looking ciphertext. FPE lets you encrypt a value in place without changing the schema or touching every consumer of that field, simply because the output still "looks like" valid data of the same shape.
Common approaches. The standardized constructions are FF1 and FF3-1 (both defined in NIST's FPE standard), which build a Feistel-network cipher on top of a standard block cipher, typically AES, restricted to operate over a small alphabet, such as the digits 0 through 9, instead of raw bytes. FF3-1 is a corrected revision of an earlier version, FF3, after a published weakness was found in the original tweak handling, so FF3-1 is the one that remains recommended.
Security trade-offs of preserving format. The value is still protected by the underlying 128-bit AES key, so FPE's reduced security margin does not come from a weaker key. For a fixed key and tweak, FF1 and FF3-1 are keyed bijections (permutations) over the set of valid inputs, so there is no oversized output blob and no output collisions to search for. The weakness comes instead from the size of that input set, the domain. Two things degrade as the domain shrinks. First, the provable-security bounds of a small-domain Feistel construction are weaker than those of a full-width block cipher, because a Feistel network over a tiny alphabet has little room to mix and hide its structure. Second, there are concrete domain-size-dependent attacks: the Durak-Vaudenay attack that broke the original FF3 (and motivated the FF3-1 revision) recovers the permutation with a work factor that scales polynomially in the domain size, so it becomes practical precisely when the domain is small. This is why applying FPE to a short, low-entropy format such as a four-digit PIN is considered particularly weak, while applying it to a long value is comparatively safe.
Worked example
Because the security concern is the size of the domain, not the AES key, the right quantity to compare is how many values an attacker would have to enumerate to defeat the scheme for a given key and tweak. FPE is a bijection over that domain, so an attacker with chosen-plaintext access can query every possible input once and build the complete plaintext-to-ciphertext table, fully inverting the scheme without ever attacking AES. The cost of that codebook attack is just the domain size:
pin4_domain = 10 ** 4 # a 4-digit PIN
card16_domain = 10 ** 16 # a 16-digit card number
# A keyed bijection can be fully mapped with one chosen-plaintext query per value.
print(f"4-digit PIN: {pin4_domain:,} values to enumerate")
print(f"16-digit card: {card16_domain:.0e} values to enumerate")
print(f"The PIN domain is {card16_domain // pin4_domain:.0e}x smaller")
Output:
4-digit PIN: 10,000 values to enumerate
16-digit card: 1e+16 values to enumerate
The PIN domain is 1e+12x smaller
Ten thousand values is trivially exhaustible: an attacker who can obtain ciphertexts for chosen PINs reconstructs the entire mapping in at most 10,000 queries, and even without an oracle a domain that small is vulnerable to frequency analysis and to the domain-scaling recovery attacks that make small-domain FPE weak. The same codebook attack against the 16-digit format would need 10^16 queries, which is infeasible, so the 16-digit case is not the weak one. The lesson is the opposite of a raw key-size comparison: FPE gets riskier as the format gets shorter, so it should never be used to protect a short, low-entropy field like a PIN.
Trade-offs and pitfalls
FPE should be reserved for genuine legacy or format-compatibility constraints, not chosen by default just because it's convenient to bolt onto an existing schema. Where no such constraint exists, a standard mode with its much larger security margin is the better default.
Propose a rollout plan to enforce mutual TLS for internal service-to-service communication in a cloud-native environment using a service mesh such as Istio or Envoy. Cover automated certificate issuance and rotation, enforcing mTLS policy without breaking existing traffic, and how you would handle legacy services that cannot yet participate.
Sample Answer
Direct answer: Roll mutual TLS, or mTLS, where both the client and server in a connection present and verify a certificate, proving both identities rather than just the server's, out in phases: permissive before strict, service by service rather than cluster-wide, using the mesh's built-in certificate authority to handle issuance and rotation automatically so no team hand-manages certificates, and give legacy services that can't join the mesh a gateway exception rather than blocking the whole rollout on them.
Structured elaboration:
Automated certificate issuance and rotation. A service mesh, such as Istio or an Envoy-based mesh, ships its own certificate authority that automatically issues each workload a short-lived certificate, often valid for hours rather than months, tied to that workload's identity, and rotates it before expiry with no manual step. This is what makes mTLS operationally viable at scale, since nobody is manually reissuing certificates per service.
Enforcing mTLS without breaking traffic. Start with an inventory: identify every service and its current traffic partners before touching any policy. Then enable the mesh's permissive mode, where sidecars accept both plaintext and mTLS traffic; this lets you deploy the mTLS infrastructure everywhere with zero behavior change yet, while the mesh's own metrics show you which traffic is already using mTLS versus still plaintext. Once a namespace or service shows fully mTLS traffic in those metrics for a sustained period, flip that specific scope to strict mode, where plaintext connections are rejected, rather than flipping the whole mesh at once. Treat each namespace's move to strict as its own deploy, with the ability to revert to permissive immediately if it breaks something the metrics didn't catch.
Handling legacy services that can't join the mesh. Route their traffic through a dedicated gateway, an ingress or egress proxy that is itself part of the mesh, which terminates plain TLS or even plaintext from the legacy service on one side and speaks mTLS to the rest of the mesh on the other. This isolates the exception to one well-monitored chokepoint instead of leaving a scattered set of plaintext-tolerant services throughout the mesh. Track legacy exceptions as a list with a named owner and a target sunset date, not as a permanent architectural feature, since every exception is a gap in the zero-trust boundary the rollout is trying to build.
flowchart TB
subgraph ControlPlane[Mesh control plane]
CA[Built in certificate authority]
end
CA -->|issues short lived cert| SA[Sidecar A]
CA -->|issues short lived cert| SB[Sidecar B]
SA -->|mTLS handshake| SB
SvcA[Service A container] --> SA
SB --> SvcB[Service B container]
Legacy[Legacy service, no sidecar] -->|plain TLS| GW[Egress and ingress gateway]
GW -->|mTLS to mesh| SA
Trade-offs and pitfalls: Flipping enforcement to strict mode before traffic metrics genuinely show full mTLS adoption for that scope is the single most common way this rollout causes an outage; a service that only occasionally calls a rarely-used dependency can look fully migrated for days before that dependency is finally called and fails. Treating the gateway exception path as temporary without a real owner and deadline is the other common failure, it quietly becomes permanent.
Describe secure patterns for referencing secrets from Infrastructure-as-Code tools such as Terraform. How do you avoid hardcoding secret values in templates, keep them out of state files, and bootstrap secrets safely the first time a resource is provisioned?
Sample Answer
Direct answer
Avoid hardcoding a secret in a Terraform template by pulling it from a data source at plan or apply time (for example aws_secretsmanager_secret_version or azurerm_key_vault_secret) instead of writing the literal value into the .tf file. The harder problem is Terraform's state file: any value a data source retrieves is written into state in plaintext as part of the resource's recorded attributes, regardless of where it came from, so keeping secrets out of state takes a deliberate backend choice, not just avoiding literals in code.
Structured elaboration
Keeping secrets out of state:
- Mark the field
sensitive = true. This only redacts the value from CLI output and plan diffs; it does not encrypt the state file itself. - Store state in a backend that encrypts at rest and restricts access tightly (an S3 backend with SSE-KMS, server-side encryption using a KMS (Key Management Service) key, and a locked-down bucket policy, or Terraform Cloud/Enterprise's encrypted state storage), and treat read access to the state file as equivalent to secret access when auditing who can see what.
- Where the exposure risk is unacceptable, avoid routing the secret through Terraform's resource graph at all: provision the secrets-manager entry, but have the application fetch the value at runtime directly from the secrets manager rather than receiving it via a Terraform-managed attribute.
Bootstrapping a secret safely the first time a resource is provisioned is a chicken-and-egg problem: a common pattern is generating a fresh random value with Terraform's random_password resource and writing it straight into the secrets manager in the same apply, so the plaintext only ever exists transiently inside that one run's state, and the application itself never receives the value through a Terraform variable at all. An alternative is provisioning a placeholder secret and having a separate, out-of-band process populate the real value on first use.
Worked example (cross-tool comparison)
CloudFormation offers a meaningfully different exposure profile via dynamic references: {{resolve:secretsmanager:my-secret}} is resolved by CloudFormation at deploy time and, for most resource types, the resolved value is not persisted back into the stack template or its change set, which avoids Terraform's state-file exposure entirely for this specific case. Ansible instead relies on ansible-vault to encrypt secret values inside playbooks or variable files at rest, or a lookup plugin (a Vault or cloud-provider lookup) to fetch a secret at run time rather than storing it in inventory. The most common real-world Ansible leak is not the storage mechanism at all: verbose or debug task output prints resolved variable values to the console by default, so any task handling a secret needs no_log: true explicitly set, or the value ends up in a CI console log even though it was never committed to source control.
Trade-offs and pitfalls
Secrets leaking into build or artifact logs is a risk shared by all three tools, not unique to one: verbose/debug flags, plan output, and CI console capture are all a leak surface equivalent to source control and should be reviewed with the same seriousness. The pitfall to watch for is assuming sensitive = true or a .gitignore'd state file is "handled" when the underlying storage backend still holds the plaintext value unencrypted or over-broadly accessible.
Unlock Full Question Bank
Get access to all 44 Data Protection and Encryption in Practice interview questions and detailed answers.
Sign in to ContinueJoin thousands of developers preparing for their dream job.