Skip to content

Re-Encryption & Re-Signing Concepts (JWET & detached-JWS, streaming)

Both re-encryption and re-signing migrate cryptographic protection without ever disclosing plaintext and in a single streaming pass.
The pipeline now processes data as JWET (JSON Web Encryption, General JSON Serialization) or detached-JWS (JSON Web Signature) envelopes, guaranteeing crypto-agility while preserving throughput.


1 · Re-Encryption (JWET → JWET)

Re-encryption decrypts an inbound JWET with an old recipient key and immediately encrypts every block into a new JWET under a new recipient key.
No plaintext touches disk or the client socket.

1.1 Security guarantees

Guarantee How it is enforced
Zero plaintext exposure Each JWET ciphertext chunk is decrypted → re-encrypted entirely in memory.
Atomic upgrade Failure in any chunk aborts the whole stream; no mixed‐key artefacts are produced.
Forward secrecy The new key can be a post-quantum KEM (e.g. ML-KEM-768), eliminating RSA/ECC legacy risk.

1.2 Streaming pipeline

stateDiagram-v2
    [*] --> ReadJWET: JWET envelope (oldKid)
    ReadJWET --> DecryptChunk: Decrypt ciphertext block
    DecryptChunk --> EncryptChunk: Encrypt with newKid
    EncryptChunk --> WriteJWET: Emit ciphertext block
    WriteJWET --> ReadJWET
    WriteJWET --> NewJWET: End-of-stream → new JWET envelope (newKid)
    NewJWET --> [*]
  • ReadJWET -- parses the protected, recipients[*], iv, and ciphertext tag for each block.

  • DecryptChunk -- unwraps the CEK with the oldKid (alg = RSA-OAEP, ECDH-ES, ...).

  • EncryptChunk -- rewraps the CEK with the newKid (alg = ML-KEM-768, dir, ...).

  • WriteJWET -- streams the new JWET General JSON part plus the new ciphertext.

1.3 Key-lifecycle headers

Header Semantics
X-OldKey-Requested / X-OldKey-Used kid you asked for (if present in header) vs. the actual key resolved after rotation.
X-NewKey-Requested / X-NewKey-Used New kid passed via query param newKid.
X-OldKey-Algorithm-Used / X-NewKey-Algorithm-Used Hybrid algorithm pair, e.g. RSA-2048+A256GCMML-KEM-768+A256GCM.
X-Migration-Mode: true Present only if sourceKidOverride repaired a missing/erroneous kid.

2 - Re-Signing (detached-JWS → detached-JWS)

Re-signing validates the incoming detached-JWS with the old signature key, then generates a new JWS header + signature with the new key.\ Payload bytes are streamed once; no full buffering occurs.

2.1 Security & efficiency highlights

  • One IO pass -- read → verify → sign in the same loop; constant-memory, O(n) IO.

  • Authenticity chain -- each chunk must pass verification before its bytes are fed into the new signature accumulator.

  • Quantum-safe upgrade -- migrate from PS256 / RS512 to Falcon-512 / ML-DSA-87 seamlessly.

2.2 Streaming pipeline

stateDiagram-v2
    [*] --> ReadPayload: Detached-JWS payload
    ReadPayload --> VerifyChunk: Verify with oldKid
    VerifyChunk --> SignChunk: Sign with newKid
    SignChunk --> WriteChunk: Emit signed chunk
    WriteChunk --> ReadPayload
    WriteChunk --> NewJWS: End-of-stream → new detached-JWS header + σ
    NewJWS --> [*]
- VerifyChunk -- incremental signature verification (alg = PS256, Ed25519, ...).

  • SignChunk -- incremental signature generation (alg = Falcon-512, ML-DSA-87, ...).

  • WriteChunk -- concatenates the new protected header and base64url-encoded signature field.

2.3 Key-lifecycle headers

Header Semantics
X-OldKey-Requested / X-OldKey-Used Incoming kid vs. the key actually found active.
X-NewKey-Requested / X-NewKey-Used Key id supplied in newKid.
X-OldKey-Algorithm-Used / X-NewKey-Algorithm-Used PS256Falcon-512, etc.
X-Migration-Mode: true Set if sourceKidOverride was necessary.

3 - Error map (RFC 7807)

HTTP type URI Condition
400 /errors/invalid-jwet JWET malformed, missing mandatory parts (iv, tag, recipients).
400 /errors/invalid-jws Detached-JWS header or signature malformed.
401 /errors/unauthorized JWT missing / expired.
404 /errors/key-not-found kid unknown or algorithm-incompatible.
409 /errors/key-revoked Key revoked / suspended.
413 /errors/payload-too-large Any multipart segment > 5 MB.
500 /errors/crypto-failure Low-level cryptographic exception.

Problem documents include timestamp, detail, instance, and honour Accept-Language.


4 - Operational tips

  1. Stream! -- supply an InputStream and enable chunked transfer (8 kB+) in your HTTP client.

  2. Monitor lifecycle headers -- rotate keys before OldKey expiry to avoid emergency migrations.

  3. Plan annual migrations -- schedule re-encrypt / re-sign jobs to adopt stronger KEMs & PQ signatures.


Document version 2.2.0 -- generated from OpenAPI build 2025-05-31

© 2025 AnkaTech Co. All rights reserved.