Skip to content

Commit 4ceabab

Browse files
authored
Merge pull request #981 from lukpueh/refactor-scheme-handling
Refactor scheme parsing
2 parents 6acab0b + 9424db5 commit 4ceabab

File tree

8 files changed

+186
-192
lines changed

8 files changed

+186
-192
lines changed

securesystemslib/signer/_aws_signer.py

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ class AWSSigner(Signer):
7474
"rsa-pkcs1v15-sha512": "RSASSA_PKCS1_V1_5_SHA_512",
7575
}
7676

77-
def __init__(self, aws_key_id: str, public_key: Key):
77+
def __init__(self, aws_key_id: str, public_key: SSlibKey):
7878
if AWS_IMPORT_ERROR:
7979
raise UnsupportedLibraryError(AWS_IMPORT_ERROR)
8080

@@ -84,7 +84,7 @@ def __init__(self, aws_key_id: str, public_key: Key):
8484
self.aws_algo = self.aws_algos[self.public_key.scheme]
8585

8686
@property
87-
def public_key(self) -> Key:
87+
def public_key(self) -> SSlibKey:
8888
return self._public_key
8989

9090
@classmethod
@@ -94,6 +94,9 @@ def from_priv_key_uri(
9494
public_key: Key,
9595
secrets_handler: SecretsHandler | None = None,
9696
) -> AWSSigner:
97+
if not isinstance(public_key, SSlibKey):
98+
raise ValueError(f"Expected SSlibKey for {priv_key_uri}")
99+
97100
uri = parse.urlparse(priv_key_uri)
98101

99102
if uri.scheme != cls.SCHEME:
@@ -121,7 +124,7 @@ def _get_keytype_for_scheme(scheme: str) -> str:
121124
@classmethod
122125
def import_(
123126
cls, aws_key_id: str, local_scheme: str | None = None
124-
) -> tuple[str, Key]:
127+
) -> tuple[str, SSlibKey]:
125128
"""Loads a key and signer details from AWS KMS.
126129
127130
Returns the private key uri and the public key. This method should only
@@ -133,7 +136,7 @@ def import_(
133136
Defaults to 'rsassa-pss-sha256' if not provided and RSA.
134137
135138
Returns:
136-
Tuple[str, Key]: A tuple where the first element is a string
139+
Tuple[str, SSlibKey]: A tuple where the first element is a string
137140
representing the private key URI, and the second element is an
138141
instance of the public key.
139142

securesystemslib/signer/_azure_signer.py

Lines changed: 37 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,20 @@
2828
Encoding,
2929
PublicFormat,
3030
)
31+
32+
KEYTYPES_AND_SCHEMES = {
33+
KeyCurveName.p_256: ("ecdsa", "ecdsa-sha2-nistp256"),
34+
KeyCurveName.p_384: ("ecdsa", "ecdsa-sha2-nistp384"),
35+
KeyCurveName.p_521: ("ecdsa", "ecdsa-sha2-nistp521"),
36+
}
37+
38+
SIGNATURE_ALGORITHMS = {
39+
"ecdsa-sha2-nistp256": SignatureAlgorithm.es256,
40+
"ecdsa-sha2-nistp384": SignatureAlgorithm.es384,
41+
"ecdsa-sha2-nistp521": SignatureAlgorithm.es512,
42+
}
43+
44+
3145
except ImportError:
3246
AZURE_IMPORT_ERROR = (
3347
"Signing with Azure Key Vault requires azure-identity, "
@@ -66,27 +80,28 @@ class AzureSigner(Signer):
6680

6781
SCHEME = "azurekms"
6882

69-
def __init__(self, az_key_uri: str, public_key: Key):
83+
def __init__(self, az_key_uri: str, public_key: SSlibKey):
7084
if AZURE_IMPORT_ERROR:
7185
raise UnsupportedLibraryError(AZURE_IMPORT_ERROR)
7286

73-
try:
74-
cred = DefaultAzureCredential()
75-
self.crypto_client = CryptographyClient(
76-
az_key_uri,
77-
credential=cred,
78-
)
79-
self.signature_algorithm = self._get_signature_algorithm(
80-
public_key,
87+
if (public_key.keytype, public_key.scheme) not in KEYTYPES_AND_SCHEMES.values():
88+
logger.info("only EC keys are supported for now")
89+
raise UnsupportedKeyType(
90+
"Supplied key must be an EC key on curve "
91+
"nistp256, nistp384, or nistp521"
8192
)
82-
self.hash_algorithm = self._get_hash_algorithm(public_key)
83-
except UnsupportedKeyType as e:
84-
logger.info("Key %s has unsupported key type or unsupported elliptic curve")
85-
raise e
93+
94+
cred = DefaultAzureCredential()
95+
self.crypto_client = CryptographyClient(
96+
az_key_uri,
97+
credential=cred,
98+
)
99+
self.signature_algorithm = SIGNATURE_ALGORITHMS[public_key.scheme]
100+
self.hash_algorithm = public_key.get_hash_algorithm_name()
86101
self._public_key = public_key
87102

88103
@property
89-
def public_key(self) -> Key:
104+
def public_key(self) -> SSlibKey:
90105
return self._public_key
91106

92107
@staticmethod
@@ -128,53 +143,12 @@ def _create_crypto_client(
128143
)
129144
raise e
130145

131-
@staticmethod
132-
def _get_signature_algorithm(public_key: Key) -> SignatureAlgorithm:
133-
"""Return SignatureAlgorithm after parsing the public key"""
134-
if public_key.keytype != "ecdsa":
135-
logger.info("only EC keys are supported for now")
136-
raise UnsupportedKeyType("Supplied key must be an EC key")
137-
# Format is "ecdsa-sha2-nistp256"
138-
comps = public_key.scheme.split("-")
139-
if len(comps) != 3: # noqa: PLR2004
140-
raise UnsupportedKeyType("Invalid scheme found")
141-
142-
if comps[2] == "nistp256":
143-
return SignatureAlgorithm.es256
144-
if comps[2] == "nistp384":
145-
return SignatureAlgorithm.es384
146-
if comps[2] == "nistp521":
147-
return SignatureAlgorithm.es512
148-
149-
raise UnsupportedKeyType("Unsupported curve supplied by key")
150-
151-
@staticmethod
152-
def _get_hash_algorithm(public_key: Key) -> str:
153-
"""Return the hash algorithm used by the public key"""
154-
# Format is "ecdsa-sha2-nistp256"
155-
comps = public_key.scheme.split("-")
156-
if len(comps) != 3: # noqa: PLR2004
157-
raise UnsupportedKeyType("Invalid scheme found")
158-
159-
if comps[2] == "nistp256":
160-
return "sha256"
161-
if comps[2] == "nistp384":
162-
return "sha384"
163-
if comps[2] == "nistp521":
164-
return "sha512"
165-
166-
raise UnsupportedKeyType("Unsupported curve supplied by key")
167-
168146
@staticmethod
169147
def _get_keytype_and_scheme(crv: str) -> tuple[str, str]:
170-
if crv == KeyCurveName.p_256:
171-
return "ecdsa", "ecdsa-sha2-nistp256"
172-
if crv == KeyCurveName.p_384:
173-
return "ecdsa", "ecdsa-sha2-nistp384"
174-
if crv == KeyCurveName.p_521:
175-
return "ecdsa", "ecdsa-sha2-nistp521"
176-
177-
raise UnsupportedKeyType("Unsupported curve supplied by key")
148+
try:
149+
return KEYTYPES_AND_SCHEMES[crv]
150+
except KeyError:
151+
raise UnsupportedKeyType("Unsupported curve supplied by key")
178152

179153
@classmethod
180154
def from_priv_key_uri(
@@ -183,6 +157,9 @@ def from_priv_key_uri(
183157
public_key: Key,
184158
secrets_handler: SecretsHandler | None = None,
185159
) -> AzureSigner:
160+
if not isinstance(public_key, SSlibKey):
161+
raise ValueError(f"Expected SSlibKey for {priv_key_uri}")
162+
186163
uri = parse.urlparse(priv_key_uri)
187164

188165
if uri.scheme != cls.SCHEME:
@@ -192,7 +169,7 @@ def from_priv_key_uri(
192169
return cls(az_key_uri, public_key)
193170

194171
@classmethod
195-
def import_(cls, az_vault_name: str, az_key_name: str) -> tuple[str, Key]:
172+
def import_(cls, az_vault_name: str, az_key_name: str) -> tuple[str, SSlibKey]:
196173
"""Load key and signer details from KMS
197174
198175
Returns the private key uri and the public key. This method should only

securesystemslib/signer/_crypto_signer.py

Lines changed: 9 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,7 @@
3838
)
3939
from cryptography.hazmat.primitives.asymmetric.types import PrivateKeyTypes
4040
from cryptography.hazmat.primitives.hashes import (
41-
SHA224,
4241
SHA256,
43-
SHA384,
44-
SHA512,
4542
HashAlgorithm,
4643
)
4744
from cryptography.hazmat.primitives.serialization import (
@@ -50,6 +47,9 @@
5047
PrivateFormat,
5148
load_pem_private_key,
5249
)
50+
51+
from securesystemslib.signer._crypto_utils import get_hash_algorithm
52+
5353
except ImportError:
5454
CRYPTO_IMPORT_ERROR = "'pyca/cryptography' library required"
5555

@@ -77,21 +77,6 @@ class _NoSignArgs:
7777
_ECDSA_KEYTYPES = ["ecdsa", "ecdsa-sha2-nistp256"]
7878

7979

80-
def _get_hash_algorithm(name: str) -> "HashAlgorithm":
81-
"""Helper to return hash algorithm for name."""
82-
algorithm: HashAlgorithm
83-
if name == "sha224":
84-
algorithm = SHA224()
85-
if name == "sha256":
86-
algorithm = SHA256()
87-
if name == "sha384":
88-
algorithm = SHA384()
89-
if name == "sha512":
90-
algorithm = SHA512()
91-
92-
return algorithm
93-
94-
9580
def _get_rsa_padding(name: str, hash_algorithm: "HashAlgorithm") -> "AsymmetricPadding":
9681
"""Helper to return rsa signature padding for name."""
9782
padding: AsymmetricPadding
@@ -155,9 +140,12 @@ def __init__(
155140
if not isinstance(private_key, RSAPrivateKey):
156141
raise ValueError(f"invalid rsa key: {type(private_key)}")
157142

158-
padding_name, hash_name = public_key.scheme.split("-")[1:]
159-
hash_algo = _get_hash_algorithm(hash_name)
143+
hash_name = public_key.get_hash_algorithm_name()
144+
hash_algo = get_hash_algorithm(hash_name)
145+
146+
padding_name = public_key.get_padding_name()
160147
padding = _get_rsa_padding(padding_name, hash_algo)
148+
161149
self._sign_args = _RSASignArgs(padding, hash_algo)
162150
self._private_key = private_key
163151

@@ -187,7 +175,7 @@ def __init__(
187175
self._public_key = public_key
188176

189177
@property
190-
def public_key(self) -> Key:
178+
def public_key(self) -> SSlibKey:
191179
return self._public_key
192180

193181
@property
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
"""Signer utils for internal use that require pyca/cryptography."""
2+
3+
from cryptography.hazmat.primitives.hashes import (
4+
SHA224,
5+
SHA256,
6+
SHA384,
7+
SHA512,
8+
HashAlgorithm,
9+
)
10+
11+
12+
def get_hash_algorithm(name: str) -> HashAlgorithm:
13+
"""Helper to return hash algorithm object for name."""
14+
if name == "sha224":
15+
return SHA224()
16+
elif name == "sha256":
17+
return SHA256()
18+
elif name == "sha384":
19+
return SHA384()
20+
elif name == "sha512":
21+
return SHA512()
22+
23+
raise ValueError(f"Unsupported hash algorithm: {name}")

0 commit comments

Comments
 (0)