Skip to content

feat(kas): add ml-kem key wrapping support#3156

Closed
dmihalcik-virtru wants to merge 2 commits into
mainfrom
post-quantum-enhanced-2026-03-dm
Closed

feat(kas): add ml-kem key wrapping support#3156
dmihalcik-virtru wants to merge 2 commits into
mainfrom
post-quantum-enhanced-2026-03-dm

Conversation

@dmihalcik-virtru

Copy link
Copy Markdown
Member

Signed-off-by: David Mihalcik dmihalcik@virtru.com

Proposed Changes

  • Updated version of hackathon demo adding ml-kem support naively as a new KAO wrapper type

Checklist

  • I have added or updated unit tests
  • I have added or updated integration tests (if appropriate)
  • I have added or updated documentation

Testing Instructions

Signed-off-by: David Mihalcik <dmihalcik@virtru.com>
@github-actions github-actions Bot added comp:db DB component comp:policy Policy Configuration ( attributes, subject mappings, resource mappings, kas registry) comp:sdk A software development kit, including library, for client applications and inter-service communicati comp:kas Key Access Server docs Documentation comp:lib:ocrypto size/l labels Mar 13, 2026
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces comprehensive support for ML-KEM 768, a post-quantum cryptographic algorithm, into the system's key wrapping and unwrapping mechanisms. This update expands the range of supported cryptographic algorithms, particularly within the Key Access Server (KAS), by integrating ML-KEM into the core cryptographic library and updating relevant service logic and protocol definitions. The change aims to enhance the system's future-readiness against advancements in quantum computing by providing a new, robust key encapsulation method.

Highlights

  • ML-KEM 768 Support: Introduced support for ML-KEM 768 (Machine Learning Key Encapsulation Mechanism) for key wrapping and unwrapping operations, enhancing the cryptographic capabilities of the system.
  • Cryptographic Library Integration: Integrated ML-KEM 768 into the ocrypto library with new MLKEMDecryptor768 and MLKEMEncryptor768 types, enabling key generation, encapsulation, and decapsulation.
  • KAS Algorithm Recognition: Updated the Key Access Server (KAS) to recognize and process ML-KEM 768 as a valid key wrapping algorithm, affecting key creation, rewrap requests, and public key exports.
  • Protocol Buffer Updates: Modified protocol buffer definitions (service/policy/objects.proto and service/policy/kasregistry/key_access_server_registry.proto) to include ALGORITHM_MLKEM_768 and KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768.
  • Refactored Key Management: Refactored key management logic within service/internal/security to use a more generalized PrivateKeyCrypto interface, simplifying the handling of different asymmetric key types including ML-KEM.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Changelog
  • docs/grpc/index.html
    • Added ML-KEM 768 algorithm and KAS public key algorithm enum to the gRPC documentation.
  • lib/ocrypto/asym_decryption.go
    • Imported the crypto/mlkem package.
    • Extended PrivateKeyDecryptor interface with DecryptWithEphemeralKey for ML-KEM.
    • Introduced MLKEMDecryptor768 struct and its decryption methods.
    • Updated FromPrivatePEMWithSalt to handle MLKEM decapsulation keys.
  • lib/ocrypto/asym_encryption.go
    • Imported the crypto/mlkem package.
    • Added MLKEM scheme type constant.
    • Introduced MLKEMEncryptor768 struct for ML-KEM encapsulation.
    • Updated FromPublicPEMWithSalt to support MLKEM encapsulation keys.
    • Added newMLKEM768 function to create MLKEM encryptors.
    • Modified getPublicPart to parse MLKEM encapsulator PEM blocks.
    • Implemented Type(), KeyType(), EphemeralKey(), Metadata(), and Encrypt() methods for MLKEMEncryptor768.
    • Implemented PublicKeyInPemFormat() for MLKEMEncryptor768.
  • lib/ocrypto/ec_key_pair.go
    • Imported the crypto/mlkem package.
    • Added MLKEM768Key to KeyType constants.
    • Updated NewKeyPair to support MLKEM768Key.
    • Introduced MLKEMKeyPair struct for ML-KEM key pairs.
    • Added NewMLKEMKeyPair function to generate ML-KEM key pairs.
    • Implemented PrivateKeyInPemFormat() and PublicKeyInPemFormat() for MLKEMKeyPair.
    • Implemented GetKeyType() for MLKEMKeyPair.
  • sdk/basekey.go
    • Updated getKasKeyAlg to map MLKEM768Key to ALGORITHM_MLKEM_768.
    • Updated formatAlg to map ALGORITHM_MLKEM_768 to MLKEM768Key.
  • sdk/codegen/runner/generate.go
    • Refactored string formatting in generateInterfaceType for consistency.
  • sdk/experimental/tdf/keysplit/attributes.go
    • Added mapping for ALGORITHM_MLKEM_768 to mlkem:768.
    • Added conversion for KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768 to ALGORITHM_MLKEM_768.
  • sdk/granter.go
    • Added mapping for KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768 to ALGORITHM_MLKEM_768.
    • Added mapping for ocrypto.MLKEM768Key to ALGORITHM_MLKEM_768.
    • Added mapping for KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768 to ocrypto.MLKEM768Key.
    • Added mapping for ALGORITHM_MLKEM_768 to ocrypto.MLKEM768Key.
  • sdk/tdf.go
    • Added kMLKEMWrapped constant.
    • Modified createKeyAccess to handle ocrypto.MLKEM768Key for key wrapping.
    • Introduced generateWrapKeyWithMLKEM function for ML-KEM key wrapping.
  • service/internal/security/basic_manager.go
    • Added a case for ocrypto.MLKEM768Key in the Decrypt method to handle ML-KEM decryption.
  • service/internal/security/crypto_provider.go
    • Added AlgorithmMLKEM768 constant.
  • service/internal/security/in_process_provider.go
    • Removed unused crypto import.
    • Updated ExportCertificate to explicitly state certificates are not available for RSA/ML-KEM keys.
    • Refactored FindKeyByID to use a direct lookup from keysByID and type assertion.
    • Refactored ListKeysWith to iterate directly over keysByID and handle different key types.
    • Refactored Decrypt to use a direct key lookup and type-specific decryption logic, removing the determineKeyType helper.
  • service/internal/security/standard_crypto.go
    • Renamed StandardRSACrypto to PrivateKeyCrypto and generalized its fields to ocrypto.PrivateKeyDecryptor and ocrypto.PublicKeyEncryptor.
    • Updated loadKey to use PrivateKeyCrypto for RSA and ML-KEM algorithms.
    • Updated loadDeprecatedKeys to use PrivateKeyCrypto.
    • Replaced RSAPublicKey with a more general PublicKey method that handles PrivateKeyCrypto and StandardECCrypto.
    • Updated RSADecrypt to use the generalized PrivateKeyCrypto.
    • Updated RSAPublicKeyAsJSON to handle PrivateKeyCrypto and extract AsymEncryption for JWK export.
    • Updated Decrypt method to use PrivateKeyCrypto for decryption.
  • service/kas/access/publicKey.go
    • Updated the PublicKey endpoint logic to handle MLKEM768 and other RSA algorithms for public key export.
  • service/kas/access/rewrap.go
    • Added a new case for ocrypto.MLKEM in verifyRewrapRequests to handle ML-KEM specific rewrap logic, including ephemeral key handling.
  • service/kas/key_indexer.go
    • Added mapping for ALGORITHM_MLKEM_768 to ocrypto.MLKEM768Key in convertEnumToAlg.
    • Added mapping for ocrypto.MLKEM768Key to ALGORITHM_MLKEM_768 in convertAlgToEnum.
  • service/pkg/db/marshalHelpers.go
    • Added mapping for ALGORITHM_MLKEM_768 to mlkem:768 in FormatAlg.
  • service/policy/db/grant_mappings.go
    • Added mapping for ALGORITHM_MLKEM_768 to KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768.
  • service/policy/kasregistry/key_access_server_registry.proto
    • Updated validation rules for key_algorithm in CreateKeyRequest and RotateKeyRequest to include ALGORITHM_MLKEM_768 (value 20).
  • service/policy/objects.proto
    • Added KAS_PUBLIC_KEY_ALG_ENUM_MLKEM_768 enum with value 20.
    • Added ALGORITHM_MLKEM_768 enum with value 20.
Ignored Files
  • Ignored by pattern: docs/openapi/**/* (12)
    • docs/openapi/authorization/authorization.openapi.yaml
    • docs/openapi/authorization/v2/authorization.openapi.yaml
    • docs/openapi/policy/actions/actions.openapi.yaml
    • docs/openapi/policy/attributes/attributes.openapi.yaml
    • docs/openapi/policy/kasregistry/key_access_server_registry.openapi.yaml
    • docs/openapi/policy/namespaces/namespaces.openapi.yaml
    • docs/openapi/policy/objects.openapi.yaml
    • docs/openapi/policy/obligations/obligations.openapi.yaml
    • docs/openapi/policy/registeredresources/registered_resources.openapi.yaml
    • docs/openapi/policy/resourcemapping/resource_mapping.openapi.yaml
    • docs/openapi/policy/subjectmapping/subject_mapping.openapi.yaml
    • docs/openapi/policy/unsafe/unsafe.openapi.yaml
  • Ignored by pattern: protocol/**/* (2)
    • protocol/go/policy/kasregistry/key_access_server_registry.pb.go
    • protocol/go/policy/objects.pb.go
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.


Quantum threats loom near, ML-KEM secures the key, Future's secrets safe.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions

Copy link
Copy Markdown
Contributor
Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 188.434221ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 101.369588ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 387.846384ms
Throughput 257.83 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 42.166151343s
Average Latency 420.496563ms
Throughput 118.58 requests/second

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Code Review

This pull request adds support for ML-KEM key wrapping. The changes are extensive, touching many parts of the codebase from the low-level crypto library to the service and SDK layers. The core logic for ML-KEM encryption and decryption has been added to lib/ocrypto. A significant and beneficial refactoring has been done in service/internal/security to better support multiple key types through interfaces. Overall, the implementation looks good, but I've found a couple of issues that should be addressed, particularly around data encoding and the lack of unit tests for the new cryptographic functionality.

Comment on lines +35 to 37
type MLKEMDecryptor768 struct {
decap *mlkem.DecapsulationKey768
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

This PR introduces significant new cryptographic functionality for ML-KEM, but it appears to be missing corresponding unit tests. For example, there are no tests for MLKEMDecryptor768 or MLKEMEncryptor768 to verify the encryption and decryption flow. Adding unit tests is critical to ensure the correctness of this new code and prevent regressions.


func (e MLKEMEncryptor768) Metadata() (map[string]string, error) {
m := make(map[string]string)
m["encapsulatedKey"] = string(e.EphemeralKey())

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Casting a raw byte slice from e.EphemeralKey() directly to a string is unsafe. The ephemeral key (which is the ML-KEM ciphertext) is binary data, and this direct conversion can lead to data corruption if the bytes are not valid UTF-8. To safely represent this binary data as a string, it should be encoded, for example, using Base64. Other parts of the codebase, such as generateWrapKeyWithMLKEM in sdk/tdf.go, use Base64 encoding for this purpose.

Suggested change
m["encapsulatedKey"] = string(e.EphemeralKey())
m["encapsulatedKey"] = string(Base64Encode(e.EphemeralKey()))

@github-actions

Copy link
Copy Markdown
Contributor

Signed-off-by: David Mihalcik <dmihalcik@virtru.com>
@github-actions

Copy link
Copy Markdown
Contributor
Benchmark results, click to expand

Benchmark authorization.GetDecisions Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 198.529227ms

Benchmark authorization.v2.GetMultiResourceDecision Results:

Metric Value
Approved Decision Requests 1000
Denied Decision Requests 0
Total Time 92.65143ms

Benchmark Statistics

Name № Requests Avg Duration Min Duration Max Duration

Bulk Benchmark Results

Metric Value
Total Decrypts 100
Successful Decrypts 100
Failed Decrypts 0
Total Time 374.448114ms
Throughput 267.06 requests/second

TDF3 Benchmark Results:

Metric Value
Total Requests 5000
Successful Requests 5000
Failed Requests 0
Concurrent Requests 50
Total Time 40.234328031s
Average Latency 400.685123ms
Throughput 124.27 requests/second

@github-actions

Copy link
Copy Markdown
Contributor

@dmihalcik-virtru

Copy link
Copy Markdown
Member Author

Merged in #3652

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:db DB component comp:kas Key Access Server comp:lib:ocrypto comp:policy Policy Configuration ( attributes, subject mappings, resource mappings, kas registry) comp:sdk A software development kit, including library, for client applications and inter-service communicati docs Documentation pqc size/l

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant