Skip to content

Partial Redaction

Partial redaction allows you to keep a portion of a PII field visible after crypto-shredding. Instead of replacing the entire value with an empty string or a static replacement, Tayra can preserve a prefix, suffix, or email local part while masking the rest with * characters.

When to Use Partial Redaction

Partial redaction is useful when you need to:

  • Identify records after shredding — e.g., showing "Jo**********" so support staff can confirm which customer record was erased
  • Preserve analytics — e.g., keeping the last 4 digits of a phone number for regional analysis
  • Maintain UX — e.g., showing "user@*******.***" so the user recognizes their email pattern

Use partial redaction instead of full replacement when the masked portion alone does not constitute personal data and the visible portion serves a legitimate operational need.

Configuration

Partial redaction is configured on the [PersonalData] attribute using the Masking and MaskingParameter properties. The redacted value is computed at encryption time and embedded in the ciphertext, so it is available after the key is shredded.

Mask After

Preserves the first N characters and masks the rest:

cs
[PersonalData(Masking = MaskingStrategies.MaskAfter, MaskingParameter = 2)]
public string FullName { get; set; } = "";
anchor

With FullName = "Eleanor Rigby" and MaskingParameter = 2:

  • Redacted value: "El***********"

Mask Before

Preserves the last N characters and masks the rest:

cs
[PersonalData(Masking = MaskingStrategies.MaskBefore, MaskingParameter = 4)]
public string PhoneNumber { get; set; } = "";
anchor

With PhoneNumber = "+1-555-0600" and MaskingParameter = 4:

  • Redacted value: "*******0600"

Mask Email Domain

Preserves the local part (before @) and masks the domain, keeping the structure (dots and @):

cs
[PersonalData(Masking = MaskingStrategies.MaskEmailDomain)]
public string Email { get; set; } = "";
anchor

With Email = "eleanor@example.com":

  • Redacted value: "eleanor@*******.***"

Masking Strategy Reference

StrategyParameterDescriptionExample InputExample Output
MaskingStrategies.MaskAfterNumber of leading chars to keepMasks everything after the first N characters"Jane Doe""Ja******"
MaskingStrategies.MaskBeforeNumber of trailing chars to keepMasks everything before the last N characters"+1-555-1234""*******1234"
MaskingStrategies.MaskEmailDomainN/AKeeps local part, masks domain (preserving dots)"jane@corp.co""jane@****.**"

Fluent API

Use named methods on PersonalDataBuilder for built-in strategies:

csharp
e.PersonalData(c => c.Name).WithMaskAfter(2);
e.PersonalData(c => c.Phone).WithMaskBefore(4);
e.PersonalData(c => c.Email).WithMaskEmailDomain();

Custom Masking

Use WithMask() to define custom masking logic inline:

csharp
// Keep last 4 characters of a tax ID
e.PersonalData(c => c.TaxId)
    .WithMask(value => new string('*', value.Length - 4) + value[^4..]);

// Show only the first initial
e.PersonalData(c => c.Name)
    .WithMask(value => value[0] + new string('*', value.Length - 1));

Custom masking is fluent API only — the lambda is captured directly, no registration needed.

How It Works

When a field with a masking strategy is encrypted:

  1. The strategy's Mask method computes the partially masked value.
  2. The redacted value is stored alongside the ciphertext in the wire format with a TAYRA_M: prefix.
  3. On decryption, if the key is available, the original plaintext is returned.
  4. If the key has been shredded, the stored redacted value (after the TAYRA_M: prefix) is returned instead of the standard replacement.

INFO

The TAYRA_M: prefix in the stored value distinguishes redacted ciphertext from regular ciphertext. This is an internal implementation detail; you do not need to handle it directly.

Edge Cases

  • If MaskingParameter is 0 or negative with MaskAfter/MaskBefore, the entire value is masked.
  • If MaskingParameter exceeds the string length, the entire value is preserved (no masking).
  • If MaskEmailDomain is used on a value without @, the entire value is masked.
  • Empty or null values produce an empty string regardless of the strategy.

Redaction vs. Full Replacement

ConcernFull ReplacementPartial Redaction
Data minimizationMaximum — no original data visiblePartial — some characters visible
Record identificationNot possiblePossible with prefix/suffix
AnalyticsNot possibleLimited analytics on visible portion
Re-identification riskNoneLow (depends on visible portion)
GDPR complianceStrongest erasure guaranteeAcceptable when visible portion is non-identifying

WARNING

Carefully consider whether the visible portion of a redacted value could be used to re-identify a data subject, especially in combination with other data. When in doubt, use full replacement (no Masking configured).

See Also