Skip to content
Learni
View all tutorials
Sécurité et Privacy

How to Implement Privacy Engineering in 2026

Lire en français

Introduction

Privacy Engineering encompasses practices that embed personal data protection into system design from the ground up, following Privacy by Design principles. In 2026, with AI's rise and stricter regulations like GDPR in Europe and enhanced CNIL oversight, neglecting privacy can lead to massive fines (up to 4% of global revenue). This beginner tutorial walks you through essential techniques step by step: identifying PII (Personally Identifiable Information), pseudonymization via hashing, anonymization, and consent management.

Why it matters: Picture an e-commerce site—a leaked email list destroys trust. We'll start from basics using Node.js to build a practical tool that processes 1,000 user data entries, protects them, and verifies consent. By the end, you'll have a working, scalable script. (128 words)

Prerequisites

  • Node.js 20+ installed
  • Basic JavaScript/TypeScript knowledge
  • An editor like VS Code
  • Terminal (bash or PowerShell)

Initialize the project

terminal
mkdir privacy-engineer-demo
cd privacy-engineer-demo
npm init -y
npm install typescript @types/node crypto-js ts-node
npm install -D @types/crypto-js
npx tsc --init
mkdir src
data/users.json

This command sets up a Node.js TypeScript project and installs CryptoJS for secure hashing. The users.json file will be created manually to simulate PII data. Avoid npm install without a lockfile for reproducibility.

Identify PII in your data

PII includes email, IP, name, etc. Use a simple regex to detect it. Analogy: Like an antivirus scanner for viruses, scan your datasets for PII before processing. Concrete example: In data/users.json, add:

[
{"id":1, "email":"user@example.com", "ip":"192.168.1.1", "name":"John Doe"},
{"id":2, "email":"test@privacy.com", "ip":"10.0.0.1", "name":"Jane Smith"}
]

Always log detected PII for audits.

PII detection and hashing script

src/pii-handler.ts
import CryptoJS from 'crypto-js';
import fs from 'fs';

type User = { id: number; email: string; ip: string; name: string };

const users: User[] = JSON.parse(fs.readFileSync('./data/users.json', 'utf-8'));

const isPII = (value: string): boolean => {
  const emailRegex = /[^@\s]+@[^@\s\.]+\.[^@\s\.]+/;
  const ipRegex = /\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/;
  return emailRegex.test(value) || ipRegex.test(value) || value.length > 3;
};

const pseudonymize = (value: string, salt: string = 'privacy-salt-2026'): string => {
  return CryptoJS.SHA256(value + salt).toString();
};

const processUsers = () => {
  const processed = users.map(user => {
    const emailHash = isPII(user.email) ? pseudonymize(user.email) : user.email;
    const ipHash = isPII(user.ip) ? pseudonymize(user.ip) : user.ip;
    const nameHash = isPII(user.name) ? pseudonymize(user.name) : user.name;
    return { ...user, email: emailHash, ip: ipHash, name: nameHash };
  });
  fs.writeFileSync('./data/users-pseudonymized.json', JSON.stringify(processed, null, 2));
  console.log('PII pseudonymisés avec succès !');
};

processUsers();

This script reads users.json, detects PII via regex (email/IP/long names), and applies SHA256 with salt for pseudonymization (GDPR Article 4). Output saved to users-pseudonymized.json. Pitfall: Without a unique salt per environment, rainbow table attacks are possible—change it in production.

Pseudonymization vs anonymization

  • Pseudonymization: Replace PII with a reversible hash using a key (like the code above). Great for analytics.
  • Anonymization: Irreversible, removes all links (e.g., replace email with 'user_123').
Analogy: Pseudonymization is a removable mask; anonymization is destruction. Test it: node -r ts-node/register src/pii-handler.ts → Check the JSON output; hashes reveal nothing without the salt.

Implement irreversible anonymization

src/anonymizer.ts
import fs from 'fs';

import type { User } from './pii-handler';

const users: User[] = JSON.parse(fs.readFileSync('./data/users-pseudonymized.json', 'utf-8'));

const anonymize = (user: User): any => {
  return {
    userId: user.id,
    email: `user_${user.id}@anon.com`, // Remplace par faux email
    ip: '0.0.0.0', // IP neutre
    name: `User_${user.id}`, // ID générique
    timestamp: new Date().toISOString()
  };
};

const anonymizedData = users.map(anonymize);
fs.writeFileSync('./data/users-anonymized.json', JSON.stringify(anonymizedData, null, 2));
console.log('Données anonymisées pour analytics !');

Starting from the pseudonymized JSON, this script replaces PII with generic placeholders (e.g., 'user_1@anon.com'). Perfect for BigQuery or public logs. Pitfall: Don't forget the timestamp for traceability without PII; test with ts-node src/anonymizer.ts.

User consent management

src/consent-manager.ts
class ConsentManager {
  private consents: { [key: string]: boolean } = JSON.parse(localStorage.getItem('privacy-consents') || '{}');

  requestConsent(type: 'analytics' | 'marketing' | 'cookies'): Promise<boolean> {
    return new Promise((resolve) => {
      if (this.consents[type] !== undefined) {
        resolve(this.consents[type]);
        return;
      }
      const banner = document.createElement('div');
      banner.innerHTML = `
        <div style="position:fixed;bottom:0;width:100%;background:#000;color:#fff;padding:20px;z-index:9999;">
          Autoriser <strong>${type}</strong> ? <button id="accept-${type}">Oui</button> <button id="reject-${type}">Non</button>
        </div>`;
      document.body.appendChild(banner);
      document.getElementById(`accept-${type}`)?.addEventListener('click', () => {
        this.setConsent(type, true);
        document.body.removeChild(banner);
        resolve(true);
      });
      document.getElementById(`reject-${type}`)?.addEventListener('click', () => {
        this.setConsent(type, false);
        document.body.removeChild(banner);
        resolve(false);
      });
    });
  }

  private setConsent(type: string, value: boolean): void {
    this.consents[type] = value;
    localStorage.setItem('privacy-consents', JSON.stringify(this.consents));
  }

  hasConsent(type: string): boolean {
    return this.consents[type] === true;
  }
}

// Usage exemple (à caller avant traitement)
const manager = new ConsentManager();
manager.requestConsent('analytics').then(hasConsent => {
  if (hasConsent) {
    console.log('Analytics OK, process data');
  } else {
    console.log('Pas de consent, skip');
  }
});

This class handles granular consent (IAB TCF-style) with localStorage and a simple HTML banner. It blocks processing without approval. Pitfall: In SSR (e.g., Next.js), sync with server cookies; test by opening an index.html with this script.

Integrate into a full workflow

Privacy Workflow: 1. Consent → 2. Detect PII → 3. Pseudonymize → 4. Anonymize if needed.

Add package.json scripts: "process":"ts-node src/pii-handler.ts && ts-node src/anonymizer.ts". Run npm run process. Result: Safe data for ML or dashboards.

Privacy policy configuration in YAML

privacy-config.yaml
version: '1.0'
salt: 'unique-salt-change-in-prod-2026'
pii_fields:
  - email
  - ip
  - name
  - phone
consent_types:
  analytics:
    description: 'Pour Google Analytics'
    required: false
  marketing:
    description: 'Newsletters'
    required: true
anonymization_rules:
  ip: '0.0.0.0'
  email: 'user_{id}@anon.com'
retention_days:
  logs: 30
  pii: 365

This YAML centralizes config (salt, rules). Load it with js-yaml in production for dynamic use. Pitfall: Version and encrypt it in Git; integrate via YAML.parse() in your scripts.

Package.json with workflow scripts

package.json
{
  "name": "privacy-engineer-demo",
  "version": "1.0.0",
  "scripts": {
    "detect": "ts-node src/pii-handler.ts",
    "anonymize": "ts-node src/anonymizer.ts",
    "full-privacy": "npm run detect && npm run anonymize",
    "consent-test": "ts-node src/consent-manager.ts"
  },
  "dependencies": {
    "typescript": "^5.0.0",
    "crypto-js": "^4.2.0",
    "@types/node": "^20.0.0",
    "ts-node": "^10.9.0",
    "@types/crypto-js": "^4.2.0"
  }
}

Ready-to-run scripts: npm run full-privacy chains everything. Add js-yaml for YAML support if needed. Pitfall: Pin dependencies for stable CI/CD.

Best practices

  • Privacy by Design: Integrate consent/PII checks into CI/CD (e.g., pre-commit hooks).
  • Use unique salt per environment (dev/prod) and rotate every 90 days.
  • Audit logs: Never log raw PII.
  • Stick to battle-tested libs (CryptoJS → WebCrypto in browser).
  • Document DPIA (Data Protection Impact Assessment) for >10k users.

Common mistakes to avoid

  • Hashing without salt: Easy rainbow table attacks.
  • Non-granular consent: A 'Accept All' button violates GDPR.
  • Forgetting localStorage in private/incognito mode: Fall back to cookies.
  • Partial anonymization: ID + hash can enable re-identification.

Next steps

How to Implement Privacy Engineering in 2026 | Learni