Torna al blog
Technical

Privacy-Enhancing Technologies (PETs): Future-Proofing Data Usage

Sarah Chen, Privacy EngineerOctober 20, 202517 min di lettura
PETsEncryptionAnonymizationData Privacy

TLDR: "Anonymized" data gets re-identified 99.98% of the time. Real privacy requires cryptographic guarantees—differential privacy, homomorphic encryption, federated learning. Apple and Google already use them; here's how you can too.

Read full summary This comprehensive technical guide covers production-ready PETs for consent management and analytics. Learn differential privacy with epsilon calibration, homomorphic encryption for privacy-preserving computation, secure multi-party computation for cross-organizational analytics, federated learning for decentralized model training, and zero-knowledge proofs for age verification. Includes TypeScript implementations with real-world code examples and guidance on selecting the right PET for your use case. *Summary by Claude AI*
## The "Anonymized" Dataset That Identified 87% of Americans In 2019, researchers demonstrated they could re-identify 99.98% of Americans in any "anonymized" dataset using just 15 demographic attributes. The Netflix Prize dataset was de-anonymized. The NYC taxi dataset exposed celebrity rides. Hospital "anonymized" discharge records were re-linked to patients. Every traditional anonymization technique has failed. K-anonymity, l-diversity, t-closeness—all of them can be defeated by a determined adversary with auxiliary information. When regulators and researchers start picking apart your "anonymized" datasets, "we removed the names" won't protect you. Privacy-Enhancing Technologies (PETs) take a fundamentally different approach. Instead of hoping your anonymization holds up, PETs provide *mathematical guarantees* that individual-level data cannot be extracted—even by the data holder themselves. Apple uses differential privacy for emoji usage statistics. Google uses it for Chrome metrics. These aren't theoretical techniques; they're production-grade privacy infrastructure. ## What are Privacy-Enhancing Technologies and Why Should You Care? Privacy-Enhancing Technologies (PETs) represent a paradigm shift in how organizations can derive value from data while mathematically guaranteeing individual privacy. Unlike traditional anonymization techniques that have repeatedly failed (the Netflix Prize dataset, NYC taxi data, and countless others), PETs provide provable privacy guarantees through cryptographic and statistical methods. **Why are PETs becoming essential for modern businesses?** The privacy landscape has fundamentally changed. Third-party cookies are deprecated, consent rates are declining (averaging 43% in Europe), and regulators are increasingly skeptical of "anonymization" claims. Meanwhile, data-driven decisions remain critical for business success. PETs resolve this tension by enabling insights from data without accessing the underlying personal information. Consider a practical example: You want to understand which marketing campaigns drive conversions, but 60% of your users have declined analytics consent. Traditional approaches fail here—you either violate consent or lose insight. With differential privacy, you can analyze the consented 40% and apply the insights broadly with mathematical confidence that no individual's data influenced the result. ## Understanding the PET Landscape ### The Hierarchy of Privacy Protection ```typescript // privacy-protection-hierarchy.ts interface PrivacyTechnique { name: string; category: 'obfuscation' | 'cryptographic' | 'statistical' | 'architectural'; privacyGuarantee: 'heuristic' | 'computational' | 'information_theoretic'; datautility: number; // 0-100 scale implementationComplexity: 'low' | 'medium' | 'high' | 'very_high'; productionReadiness: 'experimental' | 'emerging' | 'mature'; bestFor: string[]; } const privacyTechniques: PrivacyTechnique[] = [ { name: 'Pseudonymization', category: 'obfuscation', privacyGuarantee: 'heuristic', datautility: 95, implementationComplexity: 'low', productionReadiness: 'mature', bestFor: ['Basic GDPR compliance', 'Internal data separation'] }, { name: 'K-Anonymity', category: 'statistical', privacyGuarantee: 'heuristic', datautility: 70, implementationComplexity: 'medium', productionReadiness: 'mature', bestFor: ['Dataset publication', 'Research data sharing'] }, { name: 'Differential Privacy', category: 'statistical', privacyGuarantee: 'information_theoretic', datautility: 65, implementationComplexity: 'high', productionReadiness: 'mature', bestFor: ['Analytics', 'Machine learning', 'Census data'] }, { name: 'Homomorphic Encryption', category: 'cryptographic', privacyGuarantee: 'computational', datautility: 85, implementationComplexity: 'very_high', productionReadiness: 'emerging', bestFor: ['Cloud computation', 'Medical data analysis'] }, { name: 'Secure Multi-Party Computation', category: 'cryptographic', privacyGuarantee: 'computational', datautility: 90, implementationComplexity: 'very_high', productionReadiness: 'emerging', bestFor: ['Cross-organizational analytics', 'Private auctions'] }, { name: 'Federated Learning', category: 'architectural', privacyGuarantee: 'heuristic', // Without DP, FL alone doesn't guarantee privacy datautility: 80, implementationComplexity: 'high', productionReadiness: 'mature', bestFor: ['Mobile ML', 'Healthcare consortiums', 'Banking fraud detection'] }, { name: 'Zero-Knowledge Proofs', category: 'cryptographic', privacyGuarantee: 'computational', datautility: 50, // Only proves statements, doesn't return data implementationComplexity: 'very_high', productionReadiness: 'emerging', bestFor: ['Age verification', 'Credential proofs', 'Blockchain privacy'] }, { name: 'Synthetic Data', category: 'statistical', privacyGuarantee: 'heuristic', // Unless combined with DP datautility: 75, implementationComplexity: 'medium', productionReadiness: 'mature', bestFor: ['Testing', 'Model development', 'Data sharing'] } ]; ``` ## Differential Privacy: The Gold Standard for Analytics Differential privacy provides a mathematical guarantee that the output of an analysis doesn't depend significantly on any single individual's data. This means that whether or not your data is included, the results look essentially the same. ### How Differential Privacy Works ```typescript // differential-privacy-engine.ts interface DifferentialPrivacyConfig { epsilon: number; // Privacy budget (lower = more private) delta: number; // Failure probability (typically 1/n²) sensitivity: number; // Maximum change from one record mechanism: 'laplace' | 'gaussian' | 'exponential'; } interface PrivacyBudget { total: number; used: number; remaining: number; queries: PrivacyQuery[]; } interface PrivacyQuery { id: string; timestamp: Date; queryType: string; epsilonUsed: number; result: number; } class DifferentialPrivacyEngine { private config: DifferentialPrivacyConfig; private budgetTracker: Map; private queryLog: PrivacyQuery[]; constructor(config: DifferentialPrivacyConfig) { this.config = config; this.budgetTracker = new Map(); this.queryLog = []; } // ============================================ // NOISE MECHANISMS // ============================================ /** * Laplace mechanism - optimal for counting queries * Adds noise drawn from Laplace distribution */ private laplaceMechanism(trueValue: number, epsilon: number, sensitivity: number): number { const scale = sensitivity / epsilon; const noise = this.sampleLaplace(scale); return trueValue + noise; } /** * Gaussian mechanism - better for composition * Adds noise drawn from Gaussian distribution */ private gaussianMechanism( trueValue: number, epsilon: number, delta: number, sensitivity: number ): number { // sigma = sensitivity * sqrt(2 * ln(1.25/delta)) / epsilon const sigma = sensitivity * Math.sqrt(2 * Math.log(1.25 / delta)) / epsilon; const noise = this.sampleGaussian(0, sigma); return trueValue + noise; } /** * Exponential mechanism - for non-numeric outputs * Selects outputs with probability proportional to exp(epsilon * utility / (2 * sensitivity)) */ private exponentialMechanism( options: T[], utilityFunction: (option: T) => number, epsilon: number, sensitivity: number ): T { const scores = options.map(opt => utilityFunction(opt)); const expScores = scores.map(score => Math.exp((epsilon * score) / (2 * sensitivity)) ); const totalScore = expScores.reduce((a, b) => a + b, 0); const probabilities = expScores.map(s => s / totalScore); // Sample according to probabilities const rand = Math.random(); let cumulative = 0; for (let i = 0; i < options.length; i++) { cumulative += probabilities[i]; if (rand < cumulative) { return options[i]; } } return options[options.length - 1]; } // ============================================ // COMMON ANALYTICS QUERIES // ============================================ /** * Private count query * How many users match a condition? */ async privateCount( datasetId: string, condition: (record: any) => boolean, epsilon: number = this.config.epsilon ): Promise<{ result: number; confidence: { lower: number; upper: number } }> { // Check budget this.checkBudget(datasetId, epsilon); // Get true count const dataset = await this.getDataset(datasetId); const trueCount = dataset.filter(condition).length; // Add noise (sensitivity is 1 for counting queries) const noisyCount = this.laplaceMechanism(trueCount, epsilon, 1); // Calculate confidence interval const confidenceInterval = this.calculateConfidenceInterval(epsilon, 1, 0.95); // Log query and deduct budget this.logQuery(datasetId, 'count', epsilon, noisyCount); return { result: Math.max(0, Math.round(noisyCount)), confidence: { lower: Math.max(0, Math.round(noisyCount - confidenceInterval)), upper: Math.round(noisyCount + confidenceInterval) } }; } /** * Private sum query * What is the sum of a numeric field? */ async privateSum( datasetId: string, field: string, bounds: { min: number; max: number }, epsilon: number = this.config.epsilon ): Promise<{ result: number; confidence: { lower: number; upper: number } }> { this.checkBudget(datasetId, epsilon); const dataset = await this.getDataset(datasetId); // Clip values to bounds (required for sensitivity calculation) const clippedValues = dataset.map(record => { const value = record[field] as number; return Math.max(bounds.min, Math.min(bounds.max, value)); }); const trueSum = clippedValues.reduce((a, b) => a + b, 0); const sensitivity = bounds.max - bounds.min; const noisySum = this.laplaceMechanism(trueSum, epsilon, sensitivity); this.logQuery(datasetId, 'sum', epsilon, noisySum); const confidenceInterval = this.calculateConfidenceInterval(epsilon, sensitivity, 0.95); return { result: noisySum, confidence: { lower: noisySum - confidenceInterval, upper: noisySum + confidenceInterval } }; } /** * Private mean query * What is the average of a numeric field? */ async privateMean( datasetId: string, field: string, bounds: { min: number; max: number }, epsilon: number = this.config.epsilon ): Promise<{ result: number; confidence: { lower: number; upper: number } }> { // Split epsilon between count and sum const epsilonCount = epsilon / 2; const epsilonSum = epsilon / 2; const countResult = await this.privateCount( datasetId, () => true, epsilonCount ); const sumResult = await this.privateSum( datasetId, field, bounds, epsilonSum ); const noisyMean = countResult.result > 0 ? sumResult.result / countResult.result : 0; return { result: noisyMean, confidence: { lower: bounds.min, // Conservative bounds for mean upper: bounds.max } }; } /** * Private histogram * Distribution of values across bins */ async privateHistogram( datasetId: string, field: string, bins: { label: string; min: number; max: number }[], epsilon: number = this.config.epsilon ): Promise<{ bins: { label: string; count: number }[] }> { // Split epsilon across bins const epsilonPerBin = epsilon / bins.length; const results = await Promise.all( bins.map(async bin => { const count = await this.privateCount( datasetId, record => { const value = record[field] as number; return value >= bin.min && value < bin.max; }, epsilonPerBin ); return { label: bin.label, count: count.result }; }) ); return { bins: results }; } // ============================================ // PRIVACY BUDGET MANAGEMENT // ============================================ /** * Initialize budget for a dataset */ initializeBudget(datasetId: string, totalEpsilon: number): void { this.budgetTracker.set(datasetId, { total: totalEpsilon, used: 0, remaining: totalEpsilon, queries: [] }); } /** * Check if budget is available */ private checkBudget(datasetId: string, requiredEpsilon: number): void { const budget = this.budgetTracker.get(datasetId); if (!budget) { throw new Error(`No budget initialized for dataset ${datasetId}`); } if (budget.remaining < requiredEpsilon) { throw new Error( `Insufficient privacy budget. Required: ${requiredEpsilon}, Available: ${budget.remaining}` ); } } /** * Log query and deduct from budget */ private logQuery( datasetId: string, queryType: string, epsilonUsed: number, result: number ): void { const budget = this.budgetTracker.get(datasetId); if (!budget) return; const query: PrivacyQuery = { id: generateUUID(), timestamp: new Date(), queryType, epsilonUsed, result }; budget.queries.push(query); budget.used += epsilonUsed; budget.remaining -= epsilonUsed; } /** * Get current budget status */ getBudgetStatus(datasetId: string): PrivacyBudget | undefined { return this.budgetTracker.get(datasetId); } // ============================================ // UTILITY FUNCTIONS // ============================================ private sampleLaplace(scale: number): number { const u = Math.random() - 0.5; return -scale * Math.sign(u) * Math.log(1 - 2 * Math.abs(u)); } private sampleGaussian(mean: number, sigma: number): number { // Box-Muller transform const u1 = Math.random(); const u2 = Math.random(); const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2); return mean + sigma * z; } private calculateConfidenceInterval( epsilon: number, sensitivity: number, confidence: number ): number { // For Laplace mechanism: CI = sensitivity * ln(1/(1-confidence)) / epsilon return (sensitivity * Math.log(1 / (1 - confidence))) / epsilon; } } ``` ### Practical Epsilon Selection Guide | Use Case | Recommended Epsilon | Privacy Level | Notes | |----------|-------------------|---------------|-------| | US Census | 0.1 - 1.0 | Very High | Billions of people, used by academics | | Medical Research | 0.5 - 2.0 | High | Sensitive data, strict regulations | | Marketing Analytics | 1.0 - 4.0 | Moderate | Balance utility with privacy | | A/B Testing | 2.0 - 6.0 | Lower | Often aggregated anyway | | Internal Metrics | 4.0 - 10.0 | Basic | Less sensitive, trusted parties | ## Federated Learning: Keep Data Where It Lives Federated learning enables training machine learning models across decentralized data sources without centralizing the data. Instead of bringing data to the model, you bring the model to the data. ```typescript // federated-learning-engine.ts interface FederatedLearningConfig { modelArchitecture: ModelArchitecture; aggregationStrategy: 'fedavg' | 'fedprox' | 'scaffold'; minClientsPerRound: number; maxClientsPerRound: number; localEpochs: number; localBatchSize: number; differentialPrivacy?: { enabled: boolean; noiseMultiplier: number; clipNorm: number; deltaTarget: number; }; secureAggregation: boolean; } interface FederatedClient { id: string; dataSize: number; lastParticipation: Date; modelVersion: number; computeCapability: 'low' | 'medium' | 'high'; } interface FederatedRound { roundNumber: number; participatingClients: string[]; globalModelBefore: ModelWeights; clientUpdates: Map; globalModelAfter: ModelWeights; metrics: RoundMetrics; } class FederatedLearningServer { private config: FederatedLearningConfig; private globalModel: ModelWeights; private clients: Map; private roundHistory: FederatedRound[]; private privacyAccountant: PrivacyAccountant; constructor(config: FederatedLearningConfig) { this.config = config; this.clients = new Map(); this.roundHistory = []; if (config.differentialPrivacy?.enabled) { this.privacyAccountant = new PrivacyAccountant(config.differentialPrivacy); } } // ============================================ // FEDERATED TRAINING LOOP // ============================================ async runFederatedRound(): Promise { const roundNumber = this.roundHistory.length + 1; // 1. Select clients for this round const selectedClients = this.selectClients(); // 2. Distribute current global model await this.distributeModel(selectedClients); // 3. Wait for client updates const clientUpdates = await this.collectClientUpdates(selectedClients); // 4. Aggregate updates (with optional secure aggregation) const aggregatedUpdate = this.config.secureAggregation ? await this.secureAggregate(clientUpdates) : this.federatedAverage(clientUpdates); // 5. Apply differential privacy if enabled const privatizedUpdate = this.config.differentialPrivacy?.enabled ? this.applyDifferentialPrivacy(aggregatedUpdate) : aggregatedUpdate; // 6. Update global model const previousModel = { ...this.globalModel }; this.globalModel = this.applyUpdate(this.globalModel, privatizedUpdate); // 7. Evaluate and record metrics const metrics = await this.evaluateModel(); const round: FederatedRound = { roundNumber, participatingClients: selectedClients.map(c => c.id), globalModelBefore: previousModel, clientUpdates, globalModelAfter: this.globalModel, metrics }; this.roundHistory.push(round); // 8. Update privacy budget if (this.privacyAccountant) { this.privacyAccountant.accountForRound(selectedClients.length); } return round; } // ============================================ // CLIENT SELECTION // ============================================ private selectClients(): FederatedClient[] { const eligibleClients = Array.from(this.clients.values()) .filter(client => this.isClientEligible(client)); // Sample clients weighted by data size for better convergence const weights = eligibleClients.map(c => c.dataSize); const totalWeight = weights.reduce((a, b) => a + b, 0); const probabilities = weights.map(w => w / totalWeight); const numToSelect = Math.min( Math.max(this.config.minClientsPerRound, Math.floor(eligibleClients.length * 0.1)), this.config.maxClientsPerRound ); const selected: FederatedClient[] = []; const usedIndices = new Set(); while (selected.length < numToSelect && usedIndices.size < eligibleClients.length) { const rand = Math.random(); let cumulative = 0; for (let i = 0; i < eligibleClients.length; i++) { if (usedIndices.has(i)) continue; cumulative += probabilities[i]; if (rand < cumulative) { selected.push(eligibleClients[i]); usedIndices.add(i); break; } } } return selected; } private isClientEligible(client: FederatedClient): boolean { // Check if client has participated recently (to ensure freshness) const hoursSinceLastParticipation = (Date.now() - client.lastParticipation.getTime()) / (1000 * 60 * 60); // Don't over-sample the same clients if (hoursSinceLastParticipation < 1) return false; // Ensure model version is current const currentVersion = this.roundHistory.length; if (client.modelVersion < currentVersion - 5) return false; return true; } // ============================================ // AGGREGATION STRATEGIES // ============================================ /** * FedAvg: Weighted average of client updates */ private federatedAverage(updates: Map): ModelWeights { const clientList = Array.from(updates.entries()); const totalSamples = clientList.reduce((sum, [_, update]) => sum + update.numSamples, 0); // Initialize aggregated weights const aggregated: ModelWeights = {}; for (const [clientId, update] of clientList) { const weight = update.numSamples / totalSamples; for (const [layerName, layerWeights] of Object.entries(update.weights)) { if (!aggregated[layerName]) { aggregated[layerName] = new Array(layerWeights.length).fill(0); } for (let i = 0; i < layerWeights.length; i++) { aggregated[layerName][i] += weight * layerWeights[i]; } } } return aggregated; } /** * Secure Aggregation: Sum updates without seeing individual contributions */ private async secureAggregate( updates: Map ): Promise { // In production, this would use cryptographic protocols like: // - Secret sharing (Shamir's) // - Pairwise masking // - Trusted execution environments // Simplified simulation of secure aggregation const numClients = updates.size; const clientList = Array.from(updates.entries()); // Generate pairwise masks that cancel out in aggregation const masks = this.generatePairwiseMasks(clientList.map(([id]) => id)); // Each client would add their mask to their update // When summed, masks cancel: sum(mask_ij) = 0 for all pairs // Server only sees sum of (update + mask), never individual updates const maskedSum = this.federatedAverage(updates); return maskedSum; } // ============================================ // DIFFERENTIAL PRIVACY FOR FL // ============================================ private applyDifferentialPrivacy(update: ModelWeights): ModelWeights { const dpConfig = this.config.differentialPrivacy!; const clippedAndNoised: ModelWeights = {}; for (const [layerName, weights] of Object.entries(update)) { // 1. Clip the update to bound sensitivity const l2Norm = Math.sqrt(weights.reduce((sum, w) => sum + w * w, 0)); const clipFactor = Math.min(1, dpConfig.clipNorm / l2Norm); const clipped = weights.map(w => w * clipFactor); // 2. Add Gaussian noise calibrated to the sensitivity const sigma = dpConfig.noiseMultiplier * dpConfig.clipNorm; const noised = clipped.map(w => w + this.sampleGaussian(0, sigma)); clippedAndNoised[layerName] = noised; } return clippedAndNoised; } private sampleGaussian(mean: number, sigma: number): number { const u1 = Math.random(); const u2 = Math.random(); const z = Math.sqrt(-2 * Math.log(u1)) * Math.cos(2 * Math.PI * u2); return mean + sigma * z; } } // ============================================ // FEDERATED CLIENT IMPLEMENTATION // ============================================ class FederatedLearningClient { private clientId: string; private localData: any[]; private localModel: ModelWeights; private config: ClientConfig; constructor(clientId: string, localData: any[], config: ClientConfig) { this.clientId = clientId; this.localData = localData; this.config = config; } /** * Perform local training on client's private data */ async trainLocally(globalModel: ModelWeights): Promise { // Start with global model this.localModel = { ...globalModel }; // Local training loop for (let epoch = 0; epoch < this.config.localEpochs; epoch++) { const batches = this.createBatches(this.localData, this.config.batchSize); for (const batch of batches) { // Forward pass const predictions = this.forward(batch); // Compute loss const loss = this.computeLoss(predictions, batch); // Backward pass const gradients = this.backward(loss); // Update local model this.applyGradients(gradients); } } // Compute update (difference from global model) const update = this.computeModelDelta(globalModel, this.localModel); return { clientId: this.clientId, weights: update, numSamples: this.localData.length, localLoss: this.evaluateLocal() }; } private computeModelDelta(before: ModelWeights, after: ModelWeights): ModelWeights { const delta: ModelWeights = {}; for (const [layerName, weights] of Object.entries(after)) { delta[layerName] = weights.map((w, i) => w - before[layerName][i]); } return delta; } } ``` ## Homomorphic Encryption: Compute on Encrypted Data Homomorphic encryption allows computations to be performed on ciphertext, producing an encrypted result that, when decrypted, matches the result of operations performed on the plaintext. This enables privacy-preserving cloud computation. ```typescript // homomorphic-encryption-engine.ts type EncryptionScheme = 'bfv' | 'ckks' | 'tfhe'; interface HomomorphicEncryptionConfig { scheme: EncryptionScheme; polyModulusDegree: number; // Power of 2: 4096, 8192, 16384 coeffModulusBits: number[]; scaleBits: number; // For CKKS securityLevel: 128 | 192 | 256; } interface EncryptedVector { ciphertext: Uint8Array; scale: number; chainIndex: number; isNTT: boolean; } interface HomomorphicContext { publicKey: Uint8Array; secretKey: Uint8Array; // Never leaves client relinKeys: Uint8Array; galoisKeys: Uint8Array; encoder: Encoder; encryptor: Encryptor; decryptor: Decryptor; evaluator: Evaluator; } class HomomorphicEncryptionEngine { private config: HomomorphicEncryptionConfig; private context: HomomorphicContext; constructor(config: HomomorphicEncryptionConfig) { this.config = config; this.context = this.initializeContext(); } // ============================================ // ENCRYPTION/DECRYPTION // ============================================ /** * Encrypt a vector of numbers * Client-side operation - secret key never leaves client */ encrypt(values: number[]): EncryptedVector { // Encode numbers into polynomial const plaintext = this.context.encoder.encode(values); // Encrypt polynomial const ciphertext = this.context.encryptor.encrypt(plaintext); return { ciphertext: ciphertext.toBytes(), scale: plaintext.scale, chainIndex: ciphertext.chainIndex, isNTT: true }; } /** * Decrypt an encrypted vector * Client-side operation - requires secret key */ decrypt(encrypted: EncryptedVector): number[] { const ciphertext = Ciphertext.fromBytes(encrypted.ciphertext); // Decrypt to plaintext polynomial const plaintext = this.context.decryptor.decrypt(ciphertext); // Decode polynomial to numbers return this.context.encoder.decode(plaintext); } // ============================================ // HOMOMORPHIC OPERATIONS (Server-side, no secret key) // ============================================ /** * Add two encrypted vectors */ add(a: EncryptedVector, b: EncryptedVector): EncryptedVector { const ctA = Ciphertext.fromBytes(a.ciphertext); const ctB = Ciphertext.fromBytes(b.ciphertext); // Match scales if using CKKS if (this.config.scheme === 'ckks') { this.matchScales(ctA, ctB); } const result = this.context.evaluator.add(ctA, ctB); return { ciphertext: result.toBytes(), scale: result.scale, chainIndex: result.chainIndex, isNTT: result.isNTT }; } /** * Add a plaintext constant to encrypted vector */ addPlain(encrypted: EncryptedVector, constant: number[]): EncryptedVector { const ct = Ciphertext.fromBytes(encrypted.ciphertext); const plain = this.context.encoder.encode(constant); const result = this.context.evaluator.addPlain(ct, plain); return { ciphertext: result.toBytes(), scale: result.scale, chainIndex: result.chainIndex, isNTT: result.isNTT }; } /** * Multiply two encrypted vectors (element-wise) * This is computationally expensive */ multiply(a: EncryptedVector, b: EncryptedVector): EncryptedVector { const ctA = Ciphertext.fromBytes(a.ciphertext); const ctB = Ciphertext.fromBytes(b.ciphertext); // Multiplication increases ciphertext size let result = this.context.evaluator.multiply(ctA, ctB); // Relinearize to reduce size result = this.context.evaluator.relinearize(result, this.context.relinKeys); // Rescale to manage noise (CKKS) if (this.config.scheme === 'ckks') { result = this.context.evaluator.rescale(result); } return { ciphertext: result.toBytes(), scale: result.scale, chainIndex: result.chainIndex, isNTT: result.isNTT }; } /** * Compute sum of all elements in encrypted vector */ sumElements(encrypted: EncryptedVector): EncryptedVector { const ct = Ciphertext.fromBytes(encrypted.ciphertext); const slotCount = this.config.polyModulusDegree / 2; let result = ct; // Rotate and add to sum all slots for (let i = 1; i < slotCount; i *= 2) { const rotated = this.context.evaluator.rotateVector( result, i, this.context.galoisKeys ); result = this.context.evaluator.add(result, rotated); } return { ciphertext: result.toBytes(), scale: result.scale, chainIndex: result.chainIndex, isNTT: result.isNTT }; } /** * Compute dot product of encrypted vectors */ dotProduct(a: EncryptedVector, b: EncryptedVector): EncryptedVector { // Element-wise multiply const product = this.multiply(a, b); // Sum all elements return this.sumElements(product); } } // ============================================ // PRACTICAL USE CASE: Privacy-Preserving Analytics // ============================================ class PrivacyPreservingAnalyticsService { private heEngine: HomomorphicEncryptionEngine; constructor() { this.heEngine = new HomomorphicEncryptionEngine({ scheme: 'ckks', polyModulusDegree: 8192, coeffModulusBits: [60, 40, 40, 40, 60], scaleBits: 40, securityLevel: 128 }); } /** * Client encrypts their data locally, sends ciphertext to server * Server computes statistics without seeing data */ async computePrivateStatistics( encryptedData: EncryptedVector[], operation: 'mean' | 'variance' | 'sum' ): Promise { const n = encryptedData.length; if (operation === 'sum') { let sum = encryptedData[0]; for (let i = 1; i < n; i++) { sum = this.heEngine.add(sum, encryptedData[i]); } return sum; } if (operation === 'mean') { let sum = encryptedData[0]; for (let i = 1; i < n; i++) { sum = this.heEngine.add(sum, encryptedData[i]); } // Multiply by 1/n (as plaintext constant) const scale = new Array(this.getSlotCount()).fill(1 / n); return this.heEngine.multiplyPlain(sum, scale); } if (operation === 'variance') { // Var(X) = E[X²] - E[X]² // This requires multiple rounds due to multiplication depth // Compute mean const mean = await this.computePrivateStatistics(encryptedData, 'mean'); // Compute sum of squares const squares = encryptedData.map(d => this.heEngine.multiply(d, d)); const meanSquares = await this.computePrivateStatistics(squares, 'mean'); // Compute (mean)² const squaredMean = this.heEngine.multiply(mean, mean); // Subtract (this is add with negation) const negSquaredMean = this.heEngine.negate(squaredMean); return this.heEngine.add(meanSquares, negSquaredMean); } throw new Error(`Unknown operation: ${operation}`); } } ``` ## Zero-Knowledge Proofs: Prove Without Revealing Zero-knowledge proofs allow one party to prove a statement is true without revealing any information beyond the validity of the statement itself. This is particularly useful for age verification, credential checking, and regulatory compliance. ```typescript // zero-knowledge-proofs.ts interface ZKProof { proof: Uint8Array; publicInputs: string[]; verificationKey: Uint8Array; } interface AgeVerificationCircuit { // Prove: user's age >= minimumAge // Without revealing: actual birth date or exact age minimumAge: number; currentTimestamp: number; } class ZeroKnowledgeAgeVerification { private provingKey: Uint8Array; private verificationKey: Uint8Array; /** * User generates proof of age without revealing birth date * This runs on the user's device */ async generateAgeProof( birthDate: Date, minimumAge: number ): Promise { const currentTime = new Date(); const ageInYears = this.calculateAge(birthDate, currentTime); // The circuit proves: ageInYears >= minimumAge // Without revealing: birthDate or ageInYears // Private inputs (never shared) const privateInputs = { birthYear: birthDate.getFullYear(), birthMonth: birthDate.getMonth() + 1, birthDay: birthDate.getDate() }; // Public inputs (shared with verifier) const publicInputs = { minimumAge, currentYear: currentTime.getFullYear(), currentMonth: currentTime.getMonth() + 1, currentDay: currentTime.getDate() }; // Generate the proof const proof = await this.generateProof(privateInputs, publicInputs); return { proof, publicInputs: [ minimumAge.toString(), currentTime.toISOString() ], verificationKey: this.verificationKey }; } /** * Verifier checks proof without learning birth date * This can run on a server */ async verifyAgeProof(zkProof: ZKProof): Promise { return this.verifyProof( zkProof.proof, zkProof.publicInputs, zkProof.verificationKey ); } private calculateAge(birthDate: Date, currentDate: Date): number { let age = currentDate.getFullYear() - birthDate.getFullYear(); const monthDiff = currentDate.getMonth() - birthDate.getMonth(); if (monthDiff < 0 || (monthDiff === 0 && currentDate.getDate() < birthDate.getDate())) { age--; } return age; } } // ============================================ // ZK FOR CONSENT VERIFICATION // ============================================ class ZeroKnowledgeConsentVerification { /** * Prove that user has valid consent for a purpose * Without revealing: when consent was given, consent ID, or full consent record */ async generateConsentProof( consentRecord: ConsentRecord, purposeId: string ): Promise { // Private inputs const privateInputs = { consentId: consentRecord.id, consentTimestamp: consentRecord.timestamp.getTime(), allPurposes: consentRecord.purposes, consentSignature: consentRecord.signature }; // Public inputs const publicInputs = { purposeId, currentTime: Date.now(), consentValidityPeriod: 365 * 24 * 60 * 60 * 1000 // 1 year in ms }; // Circuit proves: // 1. consentRecord.purposes includes purposeId with 'granted' status // 2. currentTime - consentTimestamp < consentValidityPeriod // 3. consentSignature is valid const proof = await this.generateProof(privateInputs, publicInputs); return { proof, publicInputs: [purposeId, publicInputs.currentTime.toString()], verificationKey: this.verificationKey }; } /** * Third party verifies consent without seeing the full record */ async verifyConsentProof( zkProof: ZKProof, expectedPurposeId: string ): Promise<{ valid: boolean; purposeVerified: string }> { const isValid = await this.verifyProof( zkProof.proof, zkProof.publicInputs, zkProof.verificationKey ); return { valid: isValid, purposeVerified: isValid ? expectedPurposeId : '' }; } } ``` ## Selecting the Right PET for Your Use Case ### Decision Framework ```typescript // pet-selection-framework.ts interface UseCase { description: string; dataTypes: ('numeric' | 'categorical' | 'text' | 'images')[]; parties: number; // How many organizations involved computationType: 'statistics' | 'ml_training' | 'ml_inference' | 'verification'; latencyRequirement: 'real_time' | 'seconds' | 'minutes' | 'hours'; dataLocation: 'centralized' | 'distributed' | 'on_device'; regulatoryContext: string[]; } class PETSelectionAdvisor { recommendPET(useCase: UseCase): PETRecommendation[] { const recommendations: PETRecommendation[] = []; // Analytics on centralized data if ( useCase.computationType === 'statistics' && useCase.dataLocation === 'centralized' ) { recommendations.push({ pet: 'Differential Privacy', fit: 'excellent', rationale: 'Best for aggregate statistics with provable privacy guarantees', implementation: 'Use Google DP library or OpenDP', limitations: ['Requires privacy budget management', 'Utility decreases with more queries'] }); } // Cross-organizational analytics if (useCase.parties > 1 && useCase.computationType === 'statistics') { recommendations.push({ pet: 'Secure Multi-Party Computation', fit: 'good', rationale: 'Enables joint computation without sharing raw data', implementation: 'Use MP-SPDZ or CrypTen', limitations: ['High communication overhead', 'Complex setup'] }); } // ML on distributed data if ( useCase.computationType === 'ml_training' && useCase.dataLocation === 'distributed' ) { recommendations.push({ pet: 'Federated Learning', fit: 'excellent', rationale: 'Train models without centralizing data', implementation: 'Use TensorFlow Federated or PySyft', limitations: ['Requires orchestration infrastructure', 'Heterogeneous data challenges'] }); // Add DP for stronger guarantees recommendations.push({ pet: 'Federated Learning + Differential Privacy', fit: 'excellent', rationale: 'FL alone may leak information through model updates; DP adds formal guarantees', implementation: 'Use TFF with DP or Opacus', limitations: ['Additional utility loss from noise'] }); } // Verification without disclosure if (useCase.computationType === 'verification') { recommendations.push({ pet: 'Zero-Knowledge Proofs', fit: 'excellent', rationale: 'Prove statements without revealing underlying data', implementation: 'Use Circom + SnarkJS or ZoKrates', limitations: ['Computationally expensive proof generation', 'Limited to specific statement types'] }); } // Cloud computation on sensitive data if ( useCase.computationType === 'ml_inference' && useCase.latencyRequirement !== 'real_time' ) { recommendations.push({ pet: 'Homomorphic Encryption', fit: 'moderate', rationale: 'Compute on encrypted data without decryption', implementation: 'Use Microsoft SEAL or HElib', limitations: ['Very high computational overhead', 'Limited operations supported'] }); } return recommendations.sort((a, b) => this.fitScore(b.fit) - this.fitScore(a.fit) ); } private fitScore(fit: string): number { switch (fit) { case 'excellent': return 3; case 'good': return 2; case 'moderate': return 1; default: return 0; } } } ``` ## FAQ: Privacy-Enhancing Technologies ### Which PET should I start with? Start with differential privacy for analytics use cases. It's the most mature, has the best tooling (Google's DP library, OpenDP, IBM diffprivlib), and provides the strongest guarantees. If you're doing machine learning on distributed data, add federated learning. Reserve homomorphic encryption and MPC for specific use cases where nothing else works—the computational overhead is significant. ### Is differential privacy truly "anonymous"? Differential privacy doesn't make data anonymous in the traditional sense—it makes the *output of an analysis* provably privacy-preserving. The key insight is that with DP, an adversary cannot reliably determine whether any specific individual's data was included in the dataset, regardless of what auxiliary information they have. This is a much stronger guarantee than k-anonymity or pseudonymization. ### How much does implementing PETs cost? Costs vary dramatically by technology. Differential privacy can often be implemented with existing data infrastructure using open-source libraries—the main cost is expertise ($50k-$150k for consulting/training). Federated learning requires infrastructure changes ($200k-$500k for a production system). Homomorphic encryption and MPC are typically $500k+ for enterprise deployments due to computational requirements and specialized expertise. ### Can PETs satisfy GDPR requirements? PETs can help demonstrate data protection by design (Article 25) and support lawful processing. However, PETs alone don't satisfy GDPR—you still need proper consent management, data subject rights handling, and documentation. Differential privacy with strong epsilon values may qualify data as "anonymous" under GDPR, but this hasn't been definitively tested in court. Many DPAs accept PETs as mitigating factors in their assessments. ### What's the performance impact of PETs? Differential privacy: Negligible—just adds noise to results. Federated learning: 2-10x training time depending on network conditions and number of clients. Homomorphic encryption: 1000-10000x slower than plaintext computation. Secure MPC: 100-1000x slower with high network overhead. Zero-knowledge proofs: Proof generation is expensive (seconds to minutes), but verification is fast. ### How do I explain PETs to non-technical stakeholders? Focus on outcomes, not mechanisms. "Differential privacy lets us answer questions about user behavior without being able to identify any individual user's behavior." "Federated learning means we can improve our recommendation model using data that never leaves users' devices." "Zero-knowledge proofs let us verify someone is over 18 without learning their actual birth date." These explanations capture the privacy benefit without requiring cryptographic knowledge. ## The Future of Privacy-Preserving Analytics The convergence of stricter regulations, cookie deprecation, and increasing consumer privacy awareness makes PETs not just nice-to-have, but essential infrastructure. Organizations investing in PET capabilities today will have significant advantages: 1. **Regulatory readiness**: When regulators inevitably tighten "anonymization" requirements, PETs provide defensible technical measures 2. **Data collaboration**: PETs enable valuable cross-organizational analytics that would otherwise be impossible 3. **Consumer trust**: Demonstrable privacy protection becomes a competitive differentiator 4. **Future-proofing**: As privacy expectations evolve, PET-enabled infrastructure adapts more easily than traditional approaches The question isn't whether to adopt PETs, but which ones and how quickly. Start with differential privacy for your analytics workloads—the learning curve is manageable and the benefits are immediate. Then evaluate federated learning if you have distributed data sources. Reserve the heavier cryptographic approaches for specific high-value use cases where the overhead is justified.
S

Sarah Chen, Privacy Engineer

Autore presso GetCookies, specializzato in conformità privacy, gestione del consenso e ottimizzazione del marketing digitale.

Pronto a semplificare il consenso cookie?

GetCookies rende la conformità GDPR, CCPA e privacy globale senza sforzo. Inizia oggi.