Skip to content

[keymanager/wsd] Add /keys:decaps KOL API with DecapAndSeal + Open orchestration#650

Open
atulpatildbz wants to merge 1 commit intogoogle:mainfrom
atulpatildbz:wsd_decaps_go
Open

[keymanager/wsd] Add /keys:decaps KOL API with DecapAndSeal + Open orchestration#650
atulpatildbz wants to merge 1 commit intogoogle:mainfrom
atulpatildbz:wsd_decaps_go

Conversation

@atulpatildbz
Copy link
Collaborator

@atulpatildbz atulpatildbz commented Feb 9, 2026

Implements the Go orchestration layer (KOL) for POST /v1/keys:decap. This key exchange endpoint allows workloads to recover a shared secret from a KEM encapsulation.

Flow:

  1. Workload sends {key_handle, ciphertext: {algorithm, ciphertext}} to WSD
  2. WSD looks up binding UUID from the KEM→Binding map (populated during /v1/keys:generate_kem)
  3. WSD calls KPS DecapAndSeal — decapsulates the shared secret using the KEM private key, reseals it with the binding public key
  4. WSD calls WSD KCC Open — unseals the shared secret using the binding private key
  5. WSD returns the plaintext shared secret (base64-encoded) to the workload

Changes:

  • Endpoint: Added POST /v1/keys:decap (aligned with API contract)
  • JSON: Used snake_case for JSON fields in DecapsRequest and DecapsResponse
  • C headers: Added key_manager_decap_and_seal (KPS) and key_manager_open (WSD) declarations
  • CGO bridges: Added DecapAndSeal() and Open() Go wrappers for the Rust FFI functions
  • KPS service: Extended Service with DecapAndSeal method
  • WSD server: Added DecapSealer/Opener interfaces, handleDecaps handler
  • Tests: Verified with TestHandleDecapsSuccess in and Rust unit tests

Testing

tested with encap operation manually.
Testing generate + decap + seal + open
Code for manual testing: atulpatildbz@ac4b947

Copy link
Collaborator

@NilanjanDaw NilanjanDaw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR. Over-all comment: I think we need to align the message formats for the APIs. Lets define them in a separate proto file, so that they can be easily reviewed.

Comment on lines +71 to +78
// Use a sentinel byte so the pointer is always valid.
var aadSentinel [1]byte
aadPtr := (*C.uint8_t)(unsafe.Pointer(&aadSentinel[0]))
aadLen := C.size_t(0)
if len(aad) > 0 {
aadPtr = (*C.uint8_t)(unsafe.Pointer(&aad[0]))
aadLen = C.size_t(len(aad))
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we add a AAD context for the HPKE seal/open operation?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. I added an explicit AAD context for the decaps flow and pass it through both KPS DecapAndSeal and WSD Open: "wsd:keys:decaps:v1::". Addressed in commit 02d8655.

return
}

encapsulatedKey, err := base64.StdEncoding.DecodeString(req.EncapsulatedKey)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to align the message format and the params a bit. The encapsulatedKey is expected to be raw bytes and packed as below

message DecapsRequest {
  KeyHandle key_handle = 1;
  KemCiphertext ciphertext = 2;
}

// The results of an Encaps operation.
message KemCiphertext {
  KemAlgorithm algorithm = 1;
  bytes ciphertext = 2;  // `Nenc` bytes long.
}

Copy link
Collaborator Author

@atulpatildbz atulpatildbz Feb 13, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to the requested shape: DecapsRequest{ keyHandle, ciphertext{ algorithm, ciphertext } }.
The proto contract is in keymanager/workload_service/proto/key_management.proto (commit 4d604da), and handler parsing/validation was updated in commit 02d8655.

Comment on lines 171 to 173
resp := DecapsResponse{
SharedSecret: base64.StdEncoding.EncodeToString(plaintext),
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Response should be encoded as follows

// The results of a Decaps operation.
message KemSharedSecret {
  KemAlgorithm algorithm = 1;
  bytes secret = 2;  // `Nsecret` bytes long.
}

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated response encoding to KemSharedSecret shape: sharedSecret{ algorithm, secret }. Implemented in commit 02d8655 (including test updates).

@atulpatildbz
Copy link
Collaborator Author

Thanks for the PR. Over-all comment: I think we need to align the message formats for the APIs. Lets define them in a separate proto file, so that they can be easily reviewed.

Thanks for the review. I aligned the API message formats and added a dedicated proto file: keymanager/workload_service/proto/key_management.proto (commit 4d604da). I then updated the WSD /keys:decaps handler/tests to use that proto-shaped payload/response (commit 02d8655).

@atulpatildbz atulpatildbz force-pushed the wsd_decaps_go branch 5 times, most recently from acab338 to 4f935f5 Compare February 15, 2026 10:56
@atulpatildbz atulpatildbz force-pushed the wsd_decaps_go branch 6 times, most recently from d2ae0b3 to 4deb925 Compare February 28, 2026 07:57
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.

2 participants