I'm implementing streaming file uploads for an encrypted, self-destructing file sharing service (https://phntm.sh, open source). Currently I buffer entire files in memory, which crashes on large files. I'm switching to chunked AES-256-GCM.
Would appreciate a security review of the wire format. Here's what I've designed:
\---
**Wire Format**
Header (28 bytes):
\[4-byte magic "PHNT"\]\[4-byte version\]\[4-byte chunk\_size\]\[4-byte total\_chunks\]\[base\_iv (12 bytes)\]
Each chunk:
\[chunk\_iv (12 bytes)\]\[ciphertext\]\[auth\_tag (16 bytes)\]
**Header Fields**
| Offset | Size | Field | Description |
|--------|------|-------|-------------|
| 0 | 4 | Magic | PHNT (0x50 0x48 0x4E 0x54) |
| 4 | 4 | Version | 1 (little-endian uint32) |
| 8 | 4 | Chunk Size | Plaintext chunk size (default: 64KB) |
| 12 | 4 | Total Chunks | Number of chunks in file |
| 16 | 12 | Base IV | Random 12-byte IV for this file |
**Chunk Nonce Derivation**
`For chunk i (0-indexed):`
`chunk_nonce = base_iv[0:8] || (base_iv[8:12] XOR little_endian_uint32(i))`
This XORs the last 4 bytes of the base IV with the chunk counter, giving each chunk a unique 12-byte nonce.
\---
**My Questions**
1. Nonce derivation: Is XOR with counter secure here? I'm using 8 bytes of the base IV unchanged, and XORing the last 4 with the chunk number. The base IV is random per file.
2. Chunk size: 64KB seems reasonable. Any concerns with this size vs larger/smaller?
3. Per-chunk auth tags: Each chunk has its own 16-byte GCM tag. This means corruption is detected immediately per-chunk. Any downsides vs a single tag over the whole file?
4. Key reuse: Same key encrypts multiple files, each with a unique random base IV. Any issues with this pattern?
5. Missing attacks: What am I not considering?
\---
**References**
* NIST SP 800-38D for AES-GCM
* Apache Iceberg uses similar chunked GCM but with random nonces per chunk (more overhead)
* Full implementation issue: [https://github.com/aliirz/phntm.sh/issues/30](https://github.com/aliirz/phntm.sh/issues/30)
Thanks in advance for any feedback!