Skip to content

feat: add ML-DSA-65 and ML-DSA-87 support to JWT encode and decode - #18132

Draft
ohmayr wants to merge 3 commits into
pqc-stack-2-service-accountfrom
pqc-stack-3-jwt
Draft

feat: add ML-DSA-65 and ML-DSA-87 support to JWT encode and decode#18132
ohmayr wants to merge 3 commits into
pqc-stack-2-service-accountfrom
pqc-stack-3-jwt

Conversation

@ohmayr

@ohmayr ohmayr commented Aug 17, 2026

Copy link
Copy Markdown
Contributor

WIP

@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 Post-Quantum Cryptography (PQC) algorithms, specifically ML-DSA-65 and ML-DSA-87, for JWT encoding and decoding. It integrates the pqc module from google.auth.crypt and updates algorithm mapping and header generation. Feedback on the changes suggests skipping the new unit tests if the pqc module is unavailable and correcting the reference to PqcSigner to use crypt.pqc.PqcSigner instead of crypt.PqcSigner.

assert header == {"typ": "JWT", "alg": "ES384", "kid": es384_signer.key_id}


def test_encode_basic_mldsa(monkeypatch):

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

The test_encode_basic_mldsa test should be skipped if the pqc module is not available. Use pytest.skip() to skip the entire test.

def test_encode_basic_mldsa(monkeypatch):
    if jwt.pqc is None:
        pytest.skip("pqc is not available")
References
  1. Use pytest.skip() to skip an entire test.


b64_key = base64.b64encode(der_bytes).decode("ascii")
pem = f"-----BEGIN PRIVATE KEY-----\n{b64_key}\n-----END PRIVATE KEY-----"
mldsa_signer = crypt.PqcSigner.from_string(pem, "key-mldsa-65")

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

Use crypt.pqc.PqcSigner instead of crypt.PqcSigner because PqcSigner is defined in the pqc submodule and is not directly exposed on the parent crypt module.

Suggested change
mldsa_signer = crypt.PqcSigner.from_string(pem, "key-mldsa-65")
mldsa_signer = crypt.pqc.PqcSigner.from_string(pem, "key-mldsa-65")

assert payload["metadata"]["meta"] == "data"


def test_decode_valid_mldsa(monkeypatch):

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

The test_decode_valid_mldsa test should be skipped if the pqc module is not available. Use pytest.skip() to skip the entire test.

def test_decode_valid_mldsa(monkeypatch):
    if jwt.pqc is None:
        pytest.skip("pqc is not available")
References
  1. Use pytest.skip() to skip an entire test.

Comment thread packages/google-auth/tests/test_jwt.py Outdated

b64_key = base64.b64encode(der_bytes).decode("ascii")
pem = f"-----BEGIN PRIVATE KEY-----\n{b64_key}\n-----END PRIVATE KEY-----"
mldsa_signer = crypt.PqcSigner.from_string(pem, "key-mldsa-65")

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

Use crypt.pqc.PqcSigner instead of crypt.PqcSigner because PqcSigner is defined in the pqc submodule and is not directly exposed on the parent crypt module.

Suggested change
mldsa_signer = crypt.PqcSigner.from_string(pem, "key-mldsa-65")
mldsa_signer = crypt.pqc.PqcSigner.from_string(pem, "key-mldsa-65")

@ohmayr
ohmayr force-pushed the pqc-stack-3-jwt branch 2 times, most recently from 4dcb899 to f6e470a Compare August 17, 2026 21:03
@ohmayr
ohmayr force-pushed the pqc-stack-3-jwt branch 2 times, most recently from 2f8fe5b to 04eebc8 Compare August 17, 2026 21:35
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.

1 participant