def load_asymmetric_key(
private_key: bytes,
password: str | bytes | None = None,
) -> tuple[AllowedPrivateKeys, AllowedPublicKeys, str] | None:
if isinstance(password, str):
password = password.encode("utf-8")
try:
private_key = load_pem_private_key(private_key, password=password)
except ValueError:
return None
public_key = private_key.public_key()
if isinstance(private_key, rsa.RSAPrivateKey):
key_size = private_key.key_size
if key_size < 3072:
algorithm = "RS256"
elif key_size < 4096:
algorithm = "RS384"
else:
algorithm = "RS512"
elif isinstance(private_key, ec.EllipticCurvePrivateKey):
curve = private_key.curve.name
if curve == "secp256r1":
algorithm = "ES256"
elif curve == "secp256k1":
algorithm = "ES256K"
elif curve == "secp384r1":
algorithm = "ES384"
elif curve == "secp521r1":
algorithm = "ES512"
else:
raise ValueError(
f"Unsupported elliptic curve: {curve}. "
"Supported curves are secp256r1, secp256k1, secp384r1, and secp521r1."
)
elif isinstance(private_key, (ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey)):
algorithm = "EdDSA"
else:
raise ValueError(
f"Unsupported key type: {type(private_key).__name__}. "
"Supported key types are RSAPrivateKey, EllipticCurvePrivateKey, Ed25519PrivateKey, and Ed448PrivateKey."
)
return private_key, public_key, algorithm