Skip to content

Fix dir.uvf encryption: magic bytes, AAD chunk size, and seed key#134

Open
daniel-marthaler wants to merge 1 commit intoshift7-ch:feature/cipherduck-uvffrom
daniel-marthaler:fix/dir-uvf-aad-chunk-number-size
Open

Fix dir.uvf encryption: magic bytes, AAD chunk size, and seed key#134
daniel-marthaler wants to merge 1 commit intoshift7-ch:feature/cipherduck-uvffrom
daniel-marthaler:fix/dir-uvf-aad-chunk-number-size

Conversation

@daniel-marthaler
Copy link
Copy Markdown

Summary

Three fixes in encryptFile() (universalVaultFormat.ts) to match the Java cryptolib (cryptolib 2.3.0.uvfdraft-SNAPSHOT):

  1. Magic bytes: 0x757666010x75766600 (cryptolib uses UVF_DRAFT, version byte is 0x00)
  2. Chunk AAD: 4-byte → 8-byte chunk number (Java long, big-endian)
  3. Header key: use seed for given seedId, not always initialSeed

Background

The dir.uvf files created by the web frontend could not be decrypted by the Katta desktop client (Cyberduck-based). The desktop client threw:

CryptoAuthenticationException: Failure to decrypt due to an unauthentic ciphertext

The root cause was that AES-GCM includes the AAD in the authentication tag. Any mismatch in AAD between encryption (TypeScript) and decryption (Java cryptolib) causes GCM tag verification to fail. The magic bytes mismatch (0x01 vs 0x00) affected the header AAD, and the chunk number size mismatch (4 vs 8 bytes) affected the block AAD.

dir.uvf format (UVF Draft)

Offset  Size  Content
 0       4    Magic: 0x75766600
 4       4    Seed ID (uint32 BE)
 8      12    Header nonce
20      48    AES-GCM(headerKey, fileKey, AAD=bytes[0..7])
68      12    Block nonce
80      48    AES-GCM(fileKey, content, AAD=chunkNr[8]+nonce[12])

Changes

File Change
frontend/src/common/universalVaultFormat.ts Magic bytes, chunk AAD, seed key
frontend/test/common/universalVaultFormat.spec.ts Updated test assertion

Test plan

  • All 84 frontend tests pass
  • End-to-end verified: vault created via web UI, opened in desktop client (vault "Anita")
  • Verify no regression for vault creation via desktop client

Note: This replaces the closed #122 (fork was deleted and recreated).

🤖 Generated with Claude Code

Three fixes in encryptFile() to match Java cryptolib (v3/UVF draft):

1. Magic bytes: 0x75766601 -> 0x75766600 (cryptolib uses UVF draft,
   version byte is 0x00 not 0x01)
2. Chunk AAD: 4-byte -> 8-byte chunk number (Java long, big-endian)
3. Header key: use seed for given seedId, not always initialSeed

The magic bytes mismatch caused the GCM authentication tag to fail
because the general header (magic + seedId) is used as AAD for the
file key wrap operation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant