Pattern 1: Encrypting Payment Data
This pattern demonstrates the fundamental approach to handling sensitive payment card data in a PCI-DSS compliant way: encrypt the sensitive parts, preserve the useful parts, and delete the originals.
The Pattern
For any object containing a credit card number, the pattern is:
- Encrypt the full
card_numberusing a strong encryption key. - Extract analytics-safe fields like
card_last_fourandcard_brand. - Delete the original plaintext
card_number.
Implementation
You can apply this pattern with a single mapping processor.
-
Start with a Foundation: Begin with a pipeline that simply passes through payment data, like the
encryption-foundation.yamlfrom the previous tutorial. -
Add the Encryption Processor: Add this processor to your pipeline. It implements the complete pattern in one step.
Add this processor to your pipeline- mapping: |
# 1. ENCRYPT
# Encrypt the full card number after cleaning it.
let clean_card = this.payment.card_number.re_replace_all("[^0-9]", "")
root.payment.card_number_encrypted = clean_card.encrypt_aes("gcm", env("CARD_ENCRYPTION_KEY"))
# 2. PRESERVE
# Extract the last 4 digits and card brand.
root.payment.card_last_four = clean_card.slice(-4)
root.payment.card_brand = if clean_card.has_prefix("4") { "visa" } else { "unknown" }
# 3. DELETE
# Remove the original plaintext field.
root.payment = this.payment.without("card_number")
Verification
When you run data through this pipeline, the output payment object will no longer contain the plaintext card_number. Instead, it will have the card_number_encrypted, card_last_four, and card_brand fields, satisfying both security requirements and business analytics needs. This same pattern can be applied to other sensitive payment fields like the CVV and cardholder name.