Key Rotation

Key Rotation is the process of periodic renewal of cryptographic keys to maintain security, reduce compromise risk, and comply with security best practices.

What is Key Rotation?

Key rotation is a security practice that consists of regularly replacing cryptographic keys used to encrypt and decrypt data, authenticate users, and protect communications.

Importance of Rotation

Risk Reduction

  • Limited Compromise: Limits impact of compromised keys
  • Exposure Window: Reduces exposure window
  • Attacks: Hinders brute force attacks
  • Security: Maintains long-term security

Regulatory Compliance

  • Standards: Compliance with security standards
  • Regulations: Regulatory compliance
  • Audits: Audit preparation
  • Certifications: Certification maintenance

Best Practices

  • Industry: Industry standards
  • Recommendations: Expert recommendations
  • Security: Robust security practices
  • Management: Proactive risk management

Rotation Types

Scheduled Rotation

  • Schedule: Rotation according to fixed schedule
  • Periodic: Regular rotation (daily, weekly, monthly)
  • Automatic: Automatic rotation
  • Predictable: Easy to plan

Event-Based Rotation

  • Compromise: Rotation after suspected compromise
  • Personnel: Rotation after personnel changes
  • System: Rotation after system changes
  • Emergency: Emergency rotation

Gradual Rotation

  • Transition: Gradual transition between keys
  • Coexistence: Temporary key coexistence
  • Migration: Gradual data migration
  • Compatibility: Compatibility maintenance

Rotation Strategies

Simple Rotation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import datetime
import secrets
from cryptography.hazmat.primitives.asymmetric import rsa
from cryptography.hazmat.primitives import serialization

class SimpleKeyRotation:
    def __init__(self, rotation_interval_days=90):
        self.rotation_interval = datetime.timedelta(days=rotation_interval_days)
        self.current_key = None
        self.key_history = []
        self.last_rotation = None
    
    def generate_new_key(self, key_size=2048):
        """Generate new key"""
        private_key = rsa.generate_private_key(
            public_exponent=65537,
            key_size=key_size
        )
        return private_key
    
    def should_rotate(self):
        """Check if key rotation is necessary"""
        if self.last_rotation is None:
            return True
        
        return datetime.datetime.now() - self.last_rotation > self.rotation_interval
    
    def rotate_key(self):
        """Rotate the key"""
        if not self.should_rotate():
            return False
        
        # Generate new key
        new_key = self.generate_new_key()
        
        # Save previous key in history
        if self.current_key is not None:
            self.key_history.append({
                'key': self.current_key,
                'created': self.last_rotation,
                'retired': datetime.datetime.now()
            })
        
        # Update current key
        self.current_key = new_key
        self.last_rotation = datetime.datetime.now()
        
        return True

# Usage example
key_rotation = SimpleKeyRotation(rotation_interval_days=30)
if key_rotation.should_rotate():
    key_rotation.rotate_key()

Rotation with Data Migration

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
class DataMigrationKeyRotation:
    def __init__(self, encryption_service):
        self.encryption_service = encryption_service
        self.old_key = None
        self.new_key = None
        self.migration_status = "idle"
    
    def start_rotation(self):
        """Start rotation process"""
        # Generate new key
        self.new_key = self.generate_new_key()
        
        # Keep previous key
        self.old_key = self.encryption_service.get_current_key()
        
        # Change status
        self.migration_status = "migrating"
        
        return True
    
    def migrate_data(self, encrypted_data):
        """Migrate encrypted data"""
        if self.migration_status != "migrating":
            raise ValueError("Rotation not started")
        
        # Decrypt with old key
        decrypted_data = self.encryption_service.decrypt(
            encrypted_data, 
            self.old_key
        )
        
        # Encrypt with new key
        new_encrypted_data = self.encryption_service.encrypt(
            decrypted_data, 
            self.new_key
        )
        
        return new_encrypted_data
    
    def complete_rotation(self):
        """Complete rotation"""
        if self.migration_status != "migrating":
            raise ValueError("Migration not in progress")
        
        # Update encryption service
        self.encryption_service.set_current_key(self.new_key)
        
        # Clean old key
        self.old_key = None
        self.migration_status = "completed"
        
        return True

# Usage example
class EncryptionService:
    def __init__(self):
        self.current_key = None
    
    def get_current_key(self):
        return self.current_key
    
    def set_current_key(self, key):
        self.current_key = key
    
    def encrypt(self, data, key):
        # Implement encryption
        return f"encrypted_{data}"
    
    def decrypt(self, encrypted_data, key):
        # Implement decryption
        return encrypted_data.replace("encrypted_", "")

encryption_service = EncryptionService()
rotation = DataMigrationKeyRotation(encryption_service)

Rotation Automation

Automatic Rotation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import schedule
import time
import logging
from datetime import datetime

class AutomatedKeyRotation:
    def __init__(self, key_manager, rotation_interval_hours=24):
        self.key_manager = key_manager
        self.rotation_interval = rotation_interval_hours
        self.logger = logging.getLogger(__name__)
    
    def setup_schedule(self):
        """Setup rotation schedule"""
        schedule.every(self.rotation_interval).hours.do(self.rotate_keys)
        self.logger.info(f"Rotation scheduled every {self.rotation_interval} hours")
    
    def rotate_keys(self):
        """Rotate keys automatically"""
        try:
            self.logger.info("Starting automatic key rotation")
            
            # Get keys that need rotation
            keys_to_rotate = self.key_manager.get_keys_for_rotation()
            
            for key_id in keys_to_rotate:
                self.key_manager.rotate_key(key_id)
                self.logger.info(f"Key {key_id} rotated successfully")
            
            self.logger.info("Automatic rotation completed")
            
        except Exception as e:
            self.logger.error(f"Error in automatic rotation: {e}")
    
    def start_scheduler(self):
        """Start scheduler"""
        self.setup_schedule()
        
        while True:
            schedule.run_pending()
            time.sleep(60)  # Check every minute

# Usage example
class KeyManager:
    def __init__(self):
        self.keys = {}
    
    def get_keys_for_rotation(self):
        """Get keys that need rotation"""
        keys_to_rotate = []
        for key_id, key_info in self.keys.items():
            if self.should_rotate_key(key_info):
                keys_to_rotate.append(key_id)
        return keys_to_rotate
    
    def should_rotate_key(self, key_info):
        """Check if a key needs rotation"""
        # Implement rotation logic
        return True
    
    def rotate_key(self, key_id):
        """Rotate a specific key"""
        # Implement key rotation
        pass

key_manager = KeyManager()
automated_rotation = AutomatedKeyRotation(key_manager)
# automated_rotation.start_scheduler()  # Run in separate thread

Event-Driven Rotation

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
class EventDrivenKeyRotation:
    def __init__(self, key_manager):
        self.key_manager = key_manager
        self.event_handlers = {
            'key_compromise': self.handle_compromise,
            'personnel_change': self.handle_personnel_change,
            'system_change': self.handle_system_change,
            'emergency': self.handle_emergency
        }
    
    def handle_event(self, event_type, event_data):
        """Handle rotation event"""
        if event_type in self.event_handlers:
            self.event_handlers[event_type](event_data)
        else:
            raise ValueError(f"Unsupported event type: {event_type}")
    
    def handle_compromise(self, event_data):
        """Handle key compromise"""
        key_id = event_data.get('key_id')
        if key_id:
            self.key_manager.rotate_key_immediately(key_id)
            self.key_manager.revoke_key(key_id)
    
    def handle_personnel_change(self, event_data):
        """Handle personnel change"""
        user_id = event_data.get('user_id')
        if user_id:
            self.key_manager.rotate_user_keys(user_id)
    
    def handle_system_change(self, event_data):
        """Handle system change"""
        system_id = event_data.get('system_id')
        if system_id:
            self.key_manager.rotate_system_keys(system_id)
    
    def handle_emergency(self, event_data):
        """Handle emergency rotation"""
        self.key_manager.rotate_all_keys()

# Usage example
event_rotation = EventDrivenKeyRotation(key_manager)
event_rotation.handle_event('key_compromise', {'key_id': 'key_123'})

Best Practices

Rotation Frequency

  • Session Keys: Frequent rotation (daily/weekly)
  • Encryption Keys: Regular rotation (monthly/quarterly)
  • Signing Keys: Less frequent rotation (annual)
  • Root Keys: Very infrequent rotation

Lifecycle Management

  • Generation: Secure key generation
  • Distribution: Secure distribution
  • Usage: Controlled usage
  • Rotation: Scheduled rotation
  • Revocation: Revocation when necessary
  • Destruction: Secure destruction

Monitoring and Auditing

  • Logging: Logging of all operations
  • Monitoring: Continuous monitoring
  • Alerts: Alerts for failures
  • Audit: Regular audit

Rotation Tools

AWS KMS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import boto3
from botocore.exceptions import ClientError

class AWSKMSKeyRotation:
    def __init__(self, region_name='us-east-1'):
        self.kms_client = boto3.client('kms', region_name=region_name)
    
    def enable_automatic_rotation(self, key_id, rotation_period_days=365):
        """Enable automatic rotation"""
        try:
            response = self.kms_client.enable_key_rotation(
                KeyId=key_id
            )
            return response
        except ClientError as e:
            print(f"Error enabling rotation: {e}")
            return None
    
    def rotate_key(self, key_id):
        """Rotate key manually"""
        try:
            response = self.kms_client.create_key(
                Description=f"Rotated key for {key_id}",
                KeyUsage='ENCRYPT_DECRYPT'
            )
            return response['KeyMetadata']['KeyId']
        except ClientError as e:
            print(f"Error rotating key: {e}")
            return None

# Usage example
kms_rotation = AWSKMSKeyRotation()
kms_rotation.enable_automatic_rotation('alias/my-key')

HashiCorp Vault

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import hvac

class VaultKeyRotation:
    def __init__(self, vault_url, token):
        self.client = hvac.Client(url=vault_url, token=token)
    
    def rotate_transit_key(self, key_name):
        """Rotate transit key"""
        try:
            response = self.client.secrets.transit.rotate_key(
                name=key_name
            )
            return response
        except Exception as e:
            print(f"Error rotating key: {e}")
            return None
    
    def rekey_transit_key(self, key_name, new_key_name):
        """Rekey transit key"""
        try:
            response = self.client.secrets.transit.rekey(
                name=key_name,
                new_name=new_key_name
            )
            return response
        except Exception as e:
            print(f"Error rekeying key: {e}")
            return None

# Usage example
vault_rotation = VaultKeyRotation('http://localhost:8200', 'my-token')
vault_rotation.rotate_transit_key('my-encryption-key')
  • PKI - Infrastructure that manages key rotation
  • HSM - Device that facilitates key rotation
  • Key Escrow - System that complements key rotation
  • RSA - Algorithm that requires key rotation
  • AES - Algorithm that requires key rotation
  • CISO - Role that oversees key rotation
  • General Cybersecurity - Discipline that includes key rotation
  • Security Breaches - Incidents that require key rotation
  • Attack Vectors - Attacks that require key rotation
  • Incident Response - Process that includes key rotation
  • SIEM - System that monitors key rotation
  • SOAR - Automation that manages key rotation
  • EDR - Tool that protects key rotation
  • Firewall - Device that complements key rotation
  • VPN - Connection that requires key rotation
  • Dashboards - Visualization of key rotation metrics
  • Logs - Key rotation operation logs

References