Skip to content

fix(ciphers): chunk RSA plaintext by bytes not runes to prevent OAEP overflow on UTF-8 input#319

Closed
simple-container-forge[bot] wants to merge 7 commits into
mainfrom
forge/workflow/99171cbe-7c27-4976-a999-931b834b5d62/run/d97cc852-279d-4b65-affb-3d6f61fb8f82
Closed

fix(ciphers): chunk RSA plaintext by bytes not runes to prevent OAEP overflow on UTF-8 input#319
simple-container-forge[bot] wants to merge 7 commits into
mainfrom
forge/workflow/99171cbe-7c27-4976-a999-931b834b5d62/run/d97cc852-279d-4b65-affb-3d6f61fb8f82

Conversation

@simple-container-forge

Copy link
Copy Markdown
Contributor

Summary

  • EncryptLargeString was chunking plaintext with lo.ChunkString (rune-count), but RSA-OAEP enforces a byte limit. A 128-rune chunk of 3-byte UTF-8 characters = 384 bytes — well above the 190-byte OAEP-SHA256 limit for a 2048-bit key — causing crypto/rsa: message too long for RSA key size.
  • Replaced the rune-based loop with a byte-slice loop using the correct OAEP limit: maxPlain = k − 2·hLen − 2 = 190 bytes for 2048-bit / SHA-256.
  • Existing encrypted secrets are unaffected — DecryptLargeString is chunk-size agnostic.
  • Added // TODO: comment on EncryptWithPublicRSAKey noting its SHA-512/SHA-256 inconsistency with EncryptLargeString; no functional change to that function.

Changed files

File Change
pkg/api/secrets/ciphers/encryption.go Replace lo.ChunkString RSA branch with byte-slice loop; add TODO comment on EncryptWithPublicRSAKey
pkg/api/secrets/ciphers/encryption_test.go Add 3 regression tests: box-drawing UTF-8, emoji, mid-rune byte-boundary split

Test plan

  • go test ./pkg/api/secrets/ciphers/... -count=1 — all tests pass (green locally)
  • TestRSAEncryptionDecryption/RSA_encrypt/decrypt_UTF-8_multi-byte_string_(box-drawing) — was failing before fix (360 B > 190 B limit)
  • TestRSAEncryptionDecryption/RSA_encrypt/decrypt_emoji-dense_string — was failing before fix (400 B > 190 B limit)
  • TestRSAEncryptionDecryption/RSA_chunk_boundaries_do_not_corrupt_multi-byte_sequences — verifies mid-rune byte splits round-trip correctly
  • Existing RSA encrypt/decrypt large string (ASCII) still passes

Workflow run

https://app.simple-forge.com/agent-workflow-runs/d97cc852-279d-4b65-affb-3d6f61fb8f82

🤖 Generated with Claude Code

Forge Workflow Engine and others added 4 commits June 12, 2026 17:01
…d-4b65-affb-3d6f61fb8f82 init

idempotency: 99171cbe-7c27-4976-a999-931b834b5d62:d97cc852-279d-4b65-affb-3d6f61fb8f82: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>
…P overflow on UTF-8 input

EncryptLargeString was splitting the plaintext using lo.ChunkString, which
operates on rune count. For a 2048-bit key the chunk size was 128 runes — safe
for ASCII (128 bytes ≤ 190-byte OAEP-SHA256 limit) but wrong for multi-byte
UTF-8: a 128-rune box-drawing string encodes to 384 bytes, blowing past the
limit and producing "crypto/rsa: message too long for RSA key size".

Replace the rune-based loop with a byte-slice loop using the correct OAEP-SHA256
maximum plaintext size: k − 2·hLen − 2 = 256 − 64 − 2 = 190 bytes for a
2048-bit key. Existing ciphertext is unaffected — DecryptLargeString is
chunk-size agnostic.

Also add a TODO comment on EncryptWithPublicRSAKey noting its SHA-512 / SHA-256
inconsistency with EncryptLargeString; no behavioural change there.

Adds three regression tests covering box-drawing characters (U+2500, 3 B each),
emoji (U+1F600, 4 B each), and a mid-rune byte-boundary split.

Fixes: sc secrets add/hide failing with UTF-8 secret files.
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: d100f50

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

Scanned at 2026-06-12 17:23 UTC

@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown

Security Scan Results

Repository: api | Commit: d100f50

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:24 UTC

Maria Currie (qa) and others added 2 commits June 12, 2026 17:21
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>
@smecsia smecsia added the ci-run label Jun 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants