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+A256GCM → ML-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 |
PS256 → Falcon-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
-
Stream! -- supply an
InputStream
and enable chunked transfer (8 kB+
) in your HTTP client. -
Monitor lifecycle headers -- rotate keys before OldKey expiry to avoid emergency migrations.
-
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.