-
Notifications
You must be signed in to change notification settings - Fork 62
Add function for determining key_details
#1456
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 6 commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
0b4d8a3
add _get_key_details
ramonpetgrave64 13464b0
use in v2 client, fix types
ramonpetgrave64 4b1576c
details from certificate, add rsa and ed25519
ramonpetgrave64 466674e
Merge branch 'main' into key-details
ramonpetgrave64 60b5025
changelog
ramonpetgrave64 4bd34d7
note about unrecommended types
ramonpetgrave64 3482068
cleanup if-else
ramonpetgrave64 0ba78f4
Merge branch 'main' into key-details
ramonpetgrave64 eb19c3b
Merge branch 'main' into key-details
jku File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
# Copyright 2025 The Sigstore Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
""" | ||
Utilities for getting the sigstore_protobuf_specs.dev.sigstore.common.v1.PublicKeyDetails. | ||
""" | ||
|
||
from typing import cast | ||
|
||
from cryptography.hazmat.primitives.asymmetric import ec, ed25519, padding, rsa | ||
from cryptography.x509 import Certificate | ||
from sigstore_protobuf_specs.dev.sigstore.common import v1 | ||
|
||
|
||
def _get_key_details(certificate: Certificate) -> v1.PublicKeyDetails: | ||
""" | ||
Determine PublicKeyDetails from the Certificate. | ||
We disclude the unrecommended types. | ||
See | ||
- https://github.com/sigstore/architecture-docs/blob/6a8d78108ef4bb403046817fbcead211a9dca71d/algorithm-registry.md. | ||
- https://github.com/sigstore/protobuf-specs/blob/3aaae418f76fb4b34df4def4cd093c464f20fed3/protos/sigstore_common.proto | ||
""" | ||
public_key = certificate.public_key() | ||
params = certificate.signature_algorithm_parameters | ||
if isinstance(public_key, ec.EllipticCurvePublicKey): | ||
if isinstance(public_key.curve, ec.SECP256R1): | ||
key_details = v1.PublicKeyDetails.PKIX_ECDSA_P256_SHA_256 | ||
elif isinstance(public_key.curve, ec.SECP384R1): | ||
key_details = v1.PublicKeyDetails.PKIX_ECDSA_P384_SHA_384 | ||
elif isinstance(public_key.curve, ec.SECP521R1): | ||
key_details = v1.PublicKeyDetails.PKIX_ECDSA_P521_SHA_512 | ||
else: | ||
raise ValueError(f"Unsupported EC curve: {public_key.curve.name}") | ||
elif isinstance(public_key, rsa.RSAPublicKey): | ||
if public_key.key_size == 2048: | ||
raise ValueError("Unsupported RSA key size: 2048") | ||
elif public_key.key_size == 3072: | ||
if isinstance(params, padding.PKCS1v15): | ||
key_details = v1.PublicKeyDetails.PKIX_RSA_PKCS1V15_3072_SHA256 | ||
elif isinstance(params, padding.PSS): | ||
key_details = v1.PublicKeyDetails.PKIX_RSA_PSS_3072_SHA256 | ||
else: | ||
raise ValueError( | ||
f"Unsupported public key type, size, and padding: {type(public_key)}, {public_key.key_size}, {params}" | ||
) | ||
elif public_key.key_size == 4096: | ||
if isinstance(params, padding.PKCS1v15): | ||
key_details = v1.PublicKeyDetails.PKIX_RSA_PKCS1V15_3072_SHA256 | ||
elif isinstance(params, padding.PSS): | ||
key_details = v1.PublicKeyDetails.PKIX_RSA_PSS_3072_SHA256 | ||
else: | ||
raise ValueError( | ||
f"Unsupported public key type, size, and padding: {type(public_key)}, {public_key.key_size}, {params}" | ||
) | ||
else: | ||
raise ValueError(f"Unsupported RSA key size: {public_key.key_size}") | ||
elif isinstance(public_key, ed25519.Ed25519PublicKey): | ||
key_details = v1.PublicKeyDetails.PKIX_ED25519 | ||
# There is likely no need to explicitly detect PKIX_ED25519_PH, especially since the cryptography | ||
# library does not yet support Ed25519ph. | ||
else: | ||
raise ValueError(f"Unsupported public key type: {type(public_key)}") | ||
return cast(v1.PublicKeyDetails, key_details) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
# Copyright 2025 The Sigstore Authors | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
# Unless required by applicable law or agreed to in writing, software | ||
# distributed under the License is distributed on an "AS IS" BASIS, | ||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
# See the License for the specific language governing permissions and | ||
# limitations under the License. | ||
|
||
from unittest.mock import Mock | ||
|
||
import pytest | ||
from cryptography.hazmat.primitives.asymmetric import dsa, ec, ed25519, padding, rsa | ||
from sigstore_protobuf_specs.dev.sigstore.common import v1 | ||
|
||
from sigstore._internal.key_details import _get_key_details | ||
|
||
|
||
@pytest.mark.parametrize( | ||
"mock_certificate", | ||
[ | ||
# ec | ||
pytest.param( | ||
Mock( | ||
public_key=Mock( | ||
return_value=ec.generate_private_key(ec.SECP192R1()).public_key() | ||
) | ||
), | ||
marks=[pytest.mark.xfail(strict=True)], | ||
), | ||
Mock( | ||
public_key=Mock( | ||
return_value=ec.generate_private_key(ec.SECP256R1()).public_key() | ||
) | ||
), | ||
Mock( | ||
public_key=Mock( | ||
return_value=ec.generate_private_key(ec.SECP384R1()).public_key() | ||
) | ||
), | ||
Mock( | ||
public_key=Mock( | ||
return_value=ec.generate_private_key(ec.SECP521R1()).public_key() | ||
) | ||
), | ||
# rsa pkcs1 | ||
pytest.param( | ||
Mock( | ||
public_key=Mock( | ||
return_value=rsa.generate_private_key( | ||
public_exponent=65537, key_size=2048 | ||
).public_key() | ||
), | ||
signature_algorithm_parameters=padding.PKCS1v15(), | ||
), | ||
marks=[pytest.mark.xfail(strict=True)], | ||
), | ||
Mock( | ||
public_key=Mock( | ||
return_value=rsa.generate_private_key( | ||
public_exponent=65537, key_size=3072 | ||
).public_key() | ||
), | ||
signature_algorithm_parameters=padding.PKCS1v15(), | ||
), | ||
Mock( | ||
public_key=Mock( | ||
return_value=rsa.generate_private_key( | ||
public_exponent=65537, key_size=4096 | ||
).public_key() | ||
), | ||
signature_algorithm_parameters=padding.PKCS1v15(), | ||
), | ||
# rsa pss | ||
pytest.param( | ||
Mock( | ||
public_key=Mock( | ||
return_value=rsa.generate_private_key( | ||
public_exponent=65537, key_size=2048 | ||
).public_key() | ||
), | ||
signature_algorithm_parameters=padding.PSS(None, 0), | ||
), | ||
marks=[pytest.mark.xfail(strict=True)], | ||
), | ||
Mock( | ||
public_key=Mock( | ||
return_value=rsa.generate_private_key( | ||
public_exponent=65537, key_size=3072 | ||
).public_key() | ||
), | ||
signature_algorithm_parameters=padding.PSS(None, 0), | ||
), | ||
Mock( | ||
public_key=Mock( | ||
return_value=rsa.generate_private_key( | ||
public_exponent=65537, key_size=4096 | ||
).public_key() | ||
), | ||
signature_algorithm_parameters=padding.PSS(None, 0), | ||
), | ||
# ed25519 | ||
Mock( | ||
public_key=Mock( | ||
return_value=ed25519.Ed25519PrivateKey.generate().public_key(), | ||
signature_algorithm_parameters=None, | ||
) | ||
), | ||
# unsupported | ||
pytest.param( | ||
Mock( | ||
public_key=Mock( | ||
return_value=dsa.generate_private_key(key_size=1024).public_key() | ||
), | ||
signature_algorithm_parameters=None, | ||
), | ||
marks=[pytest.mark.xfail(strict=True)], | ||
), | ||
], | ||
) | ||
def test_get_key_details(mock_certificate): | ||
""" | ||
Ensures that we return a PublicKeyDetails for supported key types and schemes. | ||
""" | ||
key_details = _get_key_details(mock_certificate) | ||
assert isinstance(key_details, v1.PublicKeyDetails) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.