Skip to content

fix(secrets): EncryptLargeString fails on UTF-8 files (rune vs byte chunking)#320

Closed
simple-container-forge[bot] wants to merge 7 commits into
mainfrom
forge/workflow/99171cbe-7c27-4976-a999-931b834b5d62/run/848b1368-5c8d-4c6d-86dd-da2c832417a6
Closed

fix(secrets): EncryptLargeString fails on UTF-8 files (rune vs byte chunking)#320
simple-container-forge[bot] wants to merge 7 commits into
mainfrom
forge/workflow/99171cbe-7c27-4976-a999-931b834b5d62/run/848b1368-5c8d-4c6d-86dd-da2c832417a6

Conversation

@simple-container-forge

Copy link
Copy Markdown
Contributor

Summary

  • EncryptLargeString was chunking by rune count (lo.ChunkString) but rsa.EncryptOAEP enforces a byte limit. A 128-rune window of 3-byte UTF-8 characters (e.g. box-drawing ) yields 384 bytes, exceeding the OAEP-SHA256 maximum of 190 bytes for a 2048-bit key, producing crypto/rsa: message too long for RSA key size.
  • Fixed by replacing the lo.ChunkString loop with a byte-slice loop sized to the exact OAEP limit: rsaKey.Size() - 2*sha256.Size - 2 (190 bytes for 2048-bit keys).
  • Added a defensive guard that returns a clear error for keys too small for OAEP-SHA256.
  • Added 5 regression tests: box-drawing, emoji, mixed Cyrillic/arrows, chunk-boundary-mid-rune, and small-key guard.
  • DecryptLargeString is unchanged — it joins raw bytes so chunks split mid-rune reconstruct correctly. Backward-compatible with existing encrypted secrets.

Files changed

  • pkg/api/secrets/ciphers/encryption.goEncryptLargeString RSA branch only
  • pkg/api/secrets/ciphers/encryption_extra_test.go — 5 new UTF-8 regression tests

Test plan

  • go test ./pkg/api/secrets/ciphers/... -v -count=1 — all 32 tests pass including 5 new UTF-8 tests
  • TestEncryptLargeString_UTF8_BoxDrawing — 256× (768 bytes) round-trips correctly
  • TestEncryptLargeString_UTF8_Emoji — 100× 🔑 (400 bytes) round-trips correctly
  • TestEncryptLargeString_UTF8_Mixed — real-world section header with box-drawing/arrows/Cyrillic
  • TestEncryptLargeString_UTF8_ChunkBoundaryMidRune — 64× (192 bytes) splits mid-rune, verifies 2 chunks, reconstructs correctly
  • TestEncryptLargeString_SmallKey_TooSmall — synthetic 512-bit modulus triggers guard with "RSA key too small"

Workflow run: https://app.simple-forge.com/agent-workflow-runs/848b1368-5c8d-4c6d-86dd-da2c832417a6

🤖 Generated with Claude Code

Forge Workflow Engine and others added 4 commits June 12, 2026 17:45
…d-4c6d-86dd-da2c832417a6 init

idempotency: 99171cbe-7c27-4976-a999-931b834b5d62:848b1368-5c8d-4c6d-86dd-da2c832417a6:init
idempotency: pm:run

Co-authored-by: Max Warner (pm) <forge-agent+pm@simple-forge.com>
idempotency: architect:run

Co-authored-by: Dan Johnson (architect) <forge-agent+architect@simple-forge.com>
…RSA-OAEP overflow on UTF-8 files

lo.ChunkString splits by rune count but rsa.EncryptOAEP enforces a byte
limit. A 128-rune chunk of 3-byte characters (e.g. box-drawing ─) is
384 bytes — well over the OAEP-SHA256 maximum of 190 bytes for a 2048-bit
key — causing "crypto/rsa: message too long for RSA key size" on any
secret file with dense multi-byte UTF-8 content.

Fix: replace lo.ChunkString with a byte-slice loop sized to the exact
OAEP limit (rsaKey.Size() - 2*sha256.Size - 2 = 190 for 2048-bit).
Add a guard that returns a clear error for pathologically small keys.
DecryptLargeString is unchanged; it joins raw bytes so split-mid-rune
chunks reconstruct correctly.

Add five regression tests covering box-drawing, emoji, mixed Cyrillic/
arrows, chunk-boundary-mid-rune, and the small-key guard path.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
idempotency: developer:run

Co-authored-by: David Black (developer) <forge-agent+developer@simple-forge.com>
@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown

Semgrep Scan Results

Repository: api | Commit: 0b56dea

Check Status Details
✅ Semgrep Pass 0 total findings (no error/warning)

Scanned at 2026-06-12 17:55 UTC

Maria Currie (qa) and others added 2 commits June 12, 2026 17:53
idempotency: qa:run

Co-authored-by: Maria Currie (qa) <forge-agent+qa@simple-forge.com>
idempotency: devops:run

Co-authored-by: William Smith (devops) <forge-agent+devops@simple-forge.com>
@github-actions

Copy link
Copy Markdown

Security Scan Results

Repository: api | Commit: 0b56dea

Check Status Details
✅ Secret Scan Pass No secrets detected
✅ Dependencies (Trivy) Pass 0 total (no critical/high)
✅ Dependencies (Grype) Pass 2 total (no critical/high)
📦 SBOM Generated 527 components (CycloneDX)

Scanned at 2026-06-12 17:55 UTC

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