Skip to content

feat: post-quantum support for age - #287

Closed
manselmi wants to merge 2 commits into
jdx:mainfrom
manselmi:age-post-quantum
Closed

feat: post-quantum support for age#287
manselmi wants to merge 2 commits into
jdx:mainfrom
manselmi:age-post-quantum

Conversation

@manselmi

Copy link
Copy Markdown

Originally authored by brandonkal.

  • Introduced support for post-quantum keys in the age encryption provider, allowing users to generate and use hybrid keys for enhanced security.

  • Updated documentation to reflect the new post-quantum capabilities, including usage instructions and configuration examples.

  • Modified the Cargo.toml to include the new age-xwing dependency for handling post-quantum keys.

  • Enhanced tests to validate the functionality of post-quantum key decryption and ensure compatibility with existing recipient types.

This update aims to future-proof the encryption capabilities of the application against potential quantum threats.

* Introduced support for post-quantum keys in the age encryption
  provider, allowing users to generate and use hybrid keys for enhanced
  security.

* Updated documentation to reflect the new post-quantum capabilities,
  including usage instructions and configuration examples.

* Modified the Cargo.toml to include the new `age-xwing` dependency for
  handling post-quantum keys.

* Enhanced tests to validate the functionality of post-quantum key
  decryption and ensure compatibility with existing recipient types.

This update aims to future-proof the encryption capabilities of the
application against potential quantum threats.

Originally authored by [brandonkal](jdx#249).
@gemini-code-assist

Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @manselmi, 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 significantly upgrades the application's cryptographic capabilities by integrating post-quantum key support into the age encryption provider. This enhancement aims to future-proof the system against emerging quantum computing threats, ensuring continued data security. The changes involve updating core dependencies, adjusting encryption/decryption workflows, and providing comprehensive documentation for the new features.

Highlights

  • Post-Quantum Key Support: Introduced the ability to generate and use hybrid post-quantum keys within the age encryption provider for enhanced security.
  • Dependency Integration: Integrated the age-xwing dependency and its transitive cryptographic dependencies to enable post-quantum capabilities.
  • Documentation Updates: Updated user documentation across README.md and docs/providers/age.md to guide users on generating, configuring, and understanding post-quantum keys, including limitations.
  • Enhanced Test Coverage: Added new test cases to validate the encryption and decryption functionality using post-quantum keys and to demonstrate expected behavior with mixed recipient types.
  • Core Logic Adjustment: Modified the age provider's encryption and decryption logic to correctly handle and prioritize post-quantum key types.
Changelog
  • Cargo.lock
    • Updated bech32 dependency version.
    • Added age-xwing and its extensive dependency tree, including hpke-rs, libcrux-ml-kem, hax-lib, tls_codec, keccak, core-models, and various libcrux-* crates.
  • Cargo.toml
    • Added age-xwing as a new git dependency.
  • README.md
    • Updated the description for the age provider to explicitly mention support for post-quantum keys.
  • docs/providers/age.md
    • Modified the introductory description to include post-quantum keys.
    • Added a detailed 'Post-Quantum Key Support' section covering key generation, configuration, formats, a comparison table with traditional keys, and important limitations regarding recipient type mixing.
    • Included a new checklist item for post-quantum key support.
    • Added troubleshooting tips specific to post-quantum keys.
  • docs/providers/overview.md
    • Updated the age provider's description in the overview tables and lists to reflect post-quantum key support.
  • mise.toml
    • Added rust = "latest" to the tool versions.
  • src/providers/age.rs
    • Imported SecretString, HybridIdentity, and HybridRecipient from age and age-xwing.
    • Modified the encrypt method to attempt parsing recipients as HybridRecipient first if they start with 'age1pq'.
    • Added a comment clarifying that mixing different age recipient types is not supported by the age library.
    • Modified the decrypt method to check for AGE-SECRET-KEY-PQ- in identity content and parse it as HybridIdentity before falling back to SSH or standard age identities.
  • test/age.bats
    • Added a new test case to verify successful decryption using generated post-quantum age keys.
    • Added a test case to confirm that attempting to encrypt with mixed x25519 and post-quantum recipients fails as expected due to library limitations.
Activity
  • No human activity has been recorded on this pull request yet.
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.

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.

@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 introduces post-quantum key support for the age encryption provider, a significant enhancement for future-proofing security. The changes include adding the age-xwing dependency, updating the core provider logic to handle hybrid key encryption and decryption, and adding comprehensive documentation and tests for the new functionality. My review focuses on dependency management, code clarity, and documentation consistency. Overall, this is a well-executed feature addition.

Comment thread Cargo.toml

# Provider dependencies
age = { version = "0.11", features = ["ssh"] }
age-xwing = { git = "https://github.com/thrzl/age-xwing", tag = "0.1.0" }

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

Using a git dependency can introduce security and maintenance risks, as it relies on the availability and integrity of the external repository. It's generally better to use dependencies from a registry like crates.io. If age-xwing is not available on crates.io, consider forking it into this project's organization or vendoring the code to have more control over it and ensure its long-term availability.

Comment thread docs/providers/age.md
# Verify your public key matches a recipient
cat ~/.config/fnox/age.txt # Check public key
cat ~/.ssh/id_ed25519.pub # Check SSH public key
cat ~/.config/fnox/age-pq.txt # Check post-quantum public key

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.

medium

There's an inconsistency in the documentation. The key generation example earlier uses ~/.config/fnox/age.txt as the output file, but this troubleshooting command refers to ~/.config/fnox/age-pq.txt. To avoid confusion, the filename should be consistent across the document.

Suggested change
cat ~/.config/fnox/age-pq.txt # Check post-quantum public key
cat ~/.config/fnox/age.txt # Check post-quantum public key

Comment thread src/providers/age.rs
{
// Parse as HybridIdentity
let identity =
HybridIdentity::from_string(SecretString::new(pq_line.to_string().into()))

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.

medium

The .into() call here is redundant because pq_line.to_string() already returns a String. You can remove it to improve code clarity.

Suggested change
HybridIdentity::from_string(SecretString::new(pq_line.to_string().into()))
HybridIdentity::from_string(SecretString::new(pq_line.to_string()))

@manselmi

Copy link
Copy Markdown
Author

This should probably depend on an X-Wing KEM implementation in crates.io (e.g. https://crates.io/crates/x-wing) instead of a library found only on GitHub.

@manselmi manselmi closed this Feb 23, 2026
@themaxdavitt

themaxdavitt commented Jul 31, 2026

Copy link
Copy Markdown

It would be great if we could lean on rage's implementation of this when it's ready: str4d/rage#632

I might be willing to open a PR adopting it here if I have the availability; I'll keep an eye on their repo in the meantime.

EDIT: Maybe age-plugin-pq could be used in the meantime, now that age plugin support has been merged? Haven't tried either yet myself.

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