# AES-GCM Nonce Reuse Leading to Confidentiality and Integrity Breaks

Language: Python
Severity: Critical
CWE: CWE-323

## Source
7

## Flow
7-13

## Sink
13

## Vulnerable Code
```python
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

class IoTDeviceProvisioner:
    def __init__(self):
        self.master_key = AESGCM.generate_key(bit_length=256)
        self.static_nonce = os.urandom(12)
    
    def encrypt_device_credentials(self, device_id, wifi_ssid, wifi_password):
        cipher = AESGCM(self.master_key)
        payload = f"{device_id}|{wifi_ssid}|{wifi_password}".encode()
        encrypted_creds = cipher.encrypt(self.static_nonce, payload, None)
        return encrypted_creds.hex()
```

## Explanation

The code uses a static nonce (self.static_nonce) that is generated once in __init__ and reused for every encryption operation in encrypt_device_credentials. AES-GCM requires a unique nonce for each encryption with the same key, otherwise it breaks confidentiality and integrity guarantees, allowing attackers to decrypt messages and forge authenticated ciphertexts.

## Remediation

The fix removes the static nonce stored as an instance variable and instead generates a fresh random 12-byte nonce for each encryption call. The nonce is prepended to the ciphertext so the decrypting party can extract it. This ensures that each encryption operation uses a unique nonce, preserving AES-GCM's confidentiality and integrity guarantees.

## Secure Code
```python
from cryptography.hazmat.primitives.ciphers.aead import AESGCM
import os

class IoTDeviceProvisioner:
    def __init__(self):
        self.master_key = AESGCM.generate_key(bit_length=256)
    
    def encrypt_device_credentials(self, device_id, wifi_ssid, wifi_password):
        cipher = AESGCM(self.master_key)
        nonce = os.urandom(12)
        payload = f"{device_id}|{wifi_ssid}|{wifi_password}".encode()
        encrypted_creds = cipher.encrypt(nonce, payload, None)
        return (nonce + encrypted_creds).hex()
```
