Skip to content

feat: auto-detect ML-DSA keys in service account JSON credentials - #18131

Draft
ohmayr wants to merge 1 commit into
pqc-stack-1-modulefrom
pqc-stack-2-service-account
Draft

feat: auto-detect ML-DSA keys in service account JSON credentials#18131
ohmayr wants to merge 1 commit into
pqc-stack-1-modulefrom
pqc-stack-2-service-account

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 introduces support for post-quantum ML-DSA service account keys by detecting them in from_dict and returning a PqcSigner, accompanied by unit tests for both successful detection and upgrade scenarios. The feedback suggests type-validating the untrusted data input to prevent TypeError exceptions when checking for the private key, in line with the repository style guide. Additionally, it recommends mocking the entire crypt.pqc attribute in the unit tests to avoid potential AttributeError issues in environments where crypt.pqc is not present.

Comment on lines +56 to +57
if "private_key" in data and crypt.is_mldsa_key(data["private_key"]):
return crypt.PqcSigner.from_service_account_info(data)

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

According to the Repository Style Guide (Rule 2: Input Validation), any data loaded from external configuration files is untrusted and must be type-validated before indexing or calling dictionary lookup keys to avoid TypeError exceptions.

If data is not a dictionary, or if data["private_key"] is not a string, this check can raise a TypeError. We should explicitly verify that data is a dictionary and that data.get("private_key") is a string before passing it to crypt.is_mldsa_key.

Suggested change
if "private_key" in data and crypt.is_mldsa_key(data["private_key"]):
return crypt.PqcSigner.from_service_account_info(data)
if (
isinstance(data, dict)
and isinstance(data.get("private_key"), str)
and crypt.is_mldsa_key(data["private_key"])
):
return crypt.PqcSigner.from_service_account_info(data)
References
  1. Any data loaded from external configuration files (JSON, YAML, CSV) is untrusted. Always type-validate structure (e.g. check isinstance(data, dict) and isinstance(data.get("sub_key"), dict)) before indexing or calling dictionary lookup keys, avoiding TypeError exceptions. (link)



def test_from_dict_mldsa_signer_auto_detect_upgrade_required(monkeypatch):
monkeypatch.setattr(crypt.pqc, "mldsa", None)

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

If the environment running the tests has an older version of cryptography where crypt.pqc is None or does not exist, attempting to set an attribute on crypt.pqc directly will raise an AttributeError.

To make the test robust across all environments, mock the pqc attribute on the crypt module instead.

    mock_pqc = mock.Mock()
    mock_pqc.mldsa = None
    monkeypatch.setattr(crypt, "pqc", mock_pqc)

Comment on lines +155 to +160
monkeypatch.setattr(crypt.pqc, "mldsa", mock_mldsa)
monkeypatch.setattr(
crypt.pqc.serialization,
"load_pem_private_key",
lambda key, password, backend: MockMLDSA65PrivateKey(),
)

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

Similarly to the previous test, directly setting attributes on crypt.pqc or crypt.pqc.serialization can raise an AttributeError if they are not present or are None in the current environment.

We should mock the entire pqc attribute on the crypt module to ensure the test is robust.

    mock_pqc = mock.Mock()
    mock_pqc.mldsa = mock_mldsa
    mock_pqc.serialization.load_pem_private_key = lambda key, password, backend: MockMLDSA65PrivateKey()
    monkeypatch.setattr(crypt, "pqc", mock_pqc)

@ohmayr
ohmayr force-pushed the pqc-stack-2-service-account branch from cc3754d to a8ade66 Compare August 17, 2026 21:01
@ohmayr
ohmayr force-pushed the pqc-stack-2-service-account branch from a8ade66 to 8bd2f74 Compare August 17, 2026 21:03
@ohmayr
ohmayr force-pushed the pqc-stack-2-service-account branch from 8bd2f74 to 7128113 Compare August 17, 2026 21:34
@ohmayr
ohmayr force-pushed the pqc-stack-2-service-account branch from 7128113 to 1f0aae2 Compare August 17, 2026 21:50
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