Implementing Secure Data Storage

Implementing Secure Data Storage

Secure storage goes beyond basic encryption to encompass access controls, audit logging, backup strategies, and incident response. GDPR Article 32 requires "appropriate technical and organisational measures" considering the state of the art, costs, and risks. This technology-neutral approach allows flexibility but requires careful security assessment and implementation.

Encryption at rest protects data from unauthorized access if storage media is compromised. However, encryption alone isn't sufficient. Key management becomes critical – encrypted data is only as secure as its decryption keys. Hardware security modules (HSMs) or key management services provide secure key storage and rotation. Application-level encryption enables fine-grained control but requires careful implementation to avoid vulnerabilities.

// Secure data storage implementation
class SecureDataStorage {
  constructor() {
    this.encryptionAlgorithm = 'aes-256-gcm';
    this.keyDerivationIterations = 100000;
    this.auditLogger = new AuditLogger();
  }

  // Store data with multiple security layers
  async storeSecurely(data, metadata) {
    try {
      // Generate unique document ID
      const documentId = this.generateDocumentId();
      
      // Classify data sensitivity
      const classification = this.classifyData(data);
      
      // Apply appropriate encryption
      const encryptedData = await this.encryptData(data, classification);
      
      // Add integrity check
      const integrityHash = await this.calculateIntegrityHash(encryptedData);
      
      // Store with access controls
      const storageRecord = {
        id: documentId,
        data: encryptedData,
        metadata: {
          ...metadata,
          classification,
          integrityHash,
          createdAt: new Date().toISOString(),
          version: 1,
          accessControl: this.generateAccessControl(classification)
        }
      };
      
      // Store in appropriate location based on classification
      const storageLocation = this.selectStorageLocation(classification);
      await storageLocation.store(storageRecord);
      
      // Log access
      await this.auditLogger.log({
        action: 'data_stored',
        documentId,
        userId: metadata.userId,
        classification,
        timestamp: new Date().toISOString()
      });
      
      // Backup if required
      if (classification.requiresBackup) {
        await this.backupData(storageRecord);
      }
      
      return { success: true, documentId };
    } catch (error) {
      await this.handleStorageError(error, data, metadata);
      throw error;
    }
  }

  // Multi-layer encryption based on data sensitivity
  async encryptData(data, classification) {
    if (classification.level === 'public') {
      return data; // No encryption needed
    }

    // Get appropriate key based on classification
    const encryptionKey = await this.getEncryptionKey(classification);
    
    // Serialize data
    const serialized = JSON.stringify(data);
    const dataBuffer = Buffer.from(serialized, 'utf8');
    
    // Generate IV
    const iv = crypto.randomBytes(16);
    
    // Encrypt
    const cipher = crypto.createCipheriv(this.encryptionAlgorithm, encryptionKey, iv);
    const encrypted = Buffer.concat([
      cipher.update(dataBuffer),
      cipher.final()
    ]);
    
    const authTag = cipher.getAuthTag();
    
    // Additional encryption layer for highly sensitive data
    if (classification.level === 'highly_sensitive') {
      const doubleEncrypted = await this.addEncryptionLayer(encrypted, classification);
      return {
        data: doubleEncrypted.toString('base64'),
        iv: iv.toString('base64'),
        authTag: authTag.toString('base64'),
        algorithm: this.encryptionAlgorithm,
        doubleDncrypted: true
      };
    }
    
    return {
      data: encrypted.toString('base64'),
      iv: iv.toString('base64'),
      authTag: authTag.toString('base64'),
      algorithm: this.encryptionAlgorithm
    };
  }

  // Classify data sensitivity
  classifyData(data) {
    const classification = {
      level: 'internal',
      requiresEncryption: true,
      requiresBackup: true,
      retentionClass: 'standard',
      accessLevel: 'restricted'
    };

    // Check for highly sensitive data
    const sensitiveFfields = ['ssn', 'creditCard', 'bankAccount', 'medicalRecord'];
    const hasSensitiveData = Object.keys(data).some(key => 
      sensitiveFfields.some(field => key.toLowerCase().includes(field))
    );
    
    if (hasSensitiveData) {
      classification.level = 'highly_sensitive';
      classification.accessLevel = 'highly_restricted';
      classification.retentionClass = 'sensitive';
    }
    
    // Check for PII
    const piiFields = ['email', 'phone', 'address', 'dateOfBirth'];
    const hasPII = Object.keys(data).some(key =>
      piiFields.some(field => key.toLowerCase().includes(field))
    );
    
    if (hasPII) {
      classification.level = classification.level || 'confidential';
      classification.requiresEncryption = true;
    }
    
    return classification;
  }

  // Generate access control rules
  generateAccessControl(classification) {
    const acl = {
      owner: 'system',
      permissions: []
    };

    switch (classification.level) {
      case 'highly_sensitive':
        acl.permissions = [
          { role: 'data_protection_officer', access: ['read'] },
          { role: 'security_admin', access: ['read', 'audit'] },
          { role: 'system', access: ['read', 'write', 'delete'] }
        ];
        break;
      case 'confidential':
        acl.permissions = [
          { role: 'admin', access: ['read', 'write'] },
          { role: 'support_tier2', access: ['read'] },
          { role: 'system', access: ['read', 'write', 'delete'] }
        ];
        break;
      default:
        acl.permissions = [
          { role: 'authenticated', access: ['read'] },
          { role: 'admin', access: ['read', 'write', 'delete'] }
        ];
    }

    return acl;
  }

  // Retrieve data with access control
  async retrieveSecurely(documentId, userId, purpose) {
    try {
      // Verify access permission
      const hasAccess = await this.verifyAccess(documentId, userId, purpose);
      if (!hasAccess) {
        throw new Error('Access denied');
      }
      
      // Retrieve encrypted data
      const storageRecord = await this.retrieveStorageRecord(documentId);
      
      // Verify integrity
      const integrityValid = await this.verifyIntegrity(storageRecord);
      if (!integrityValid) {
        throw new Error('Data integrity check failed');
      }
      
      // Decrypt data
      const decryptedData = await this.decryptData(
        storageRecord.data,
        storageRecord.metadata.classification
      );
      
      // Log access
      await this.auditLogger.log({
        action: 'data_accessed',
        documentId,
        userId,
        purpose,
        timestamp: new Date().toISOString()
      });
      
      // Apply any field-level access controls
      const filteredData = this.applyFieldLevelAccess(
        decryptedData,
        userId,
        storageRecord.metadata.classification
      );
      
      return filteredData;
    } catch (error) {
      await this.auditLogger.log({
        action: 'data_access_failed',
        documentId,
        userId,
        error: error.message,
        timestamp: new Date().toISOString()
      });
      throw error;
    }
  }
}