Source code for sf_toolkit.auth.keys

"""Optional RSA key loading. Non-JWT authentication does not need cryptography."""

from __future__ import annotations

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey


[docs] def load_private_key( private_key: bytes | str | RSAPrivateKey, passphrase: bytes | str | None = None, ) -> RSAPrivateKey: """Load PEM/OpenSSH RSA material, or validate an already loaded RSA key. The decrypted key stays in memory; no files are read or written. Exceptions exclude key/passphrase values. At least 2048 bits are required. """ try: from cryptography.exceptions import UnsupportedAlgorithm from cryptography.hazmat.primitives import serialization from cryptography.hazmat.primitives.asymmetric.rsa import RSAPrivateKey except ImportError: raise ImportError("RSA JWT authentication requires sf-toolkit[jwt]") from None if isinstance(private_key, RSAPrivateKey): if passphrase is not None: raise ValueError("A loaded private key does not take a passphrase") key = private_key else: if not isinstance(private_key, (str, bytes)) or not isinstance( passphrase, (str, bytes, type(None)) ): raise ValueError("Invalid RSA private key or passphrase") raw = private_key.encode() if isinstance(private_key, str) else private_key raw = raw.strip() password = passphrase.encode() if isinstance(passphrase, str) else passphrase loader = ( serialization.load_ssh_private_key if raw.startswith(b"-----BEGIN OPENSSH PRIVATE KEY-----") else serialization.load_pem_private_key ) try: key = loader(raw, password=password) except (ValueError, TypeError, UnsupportedAlgorithm): raise ValueError("Invalid RSA private key or passphrase") from None if not isinstance(key, RSAPrivateKey): raise ValueError("Salesforce JWT authentication requires an RSA private key") if key.key_size < 2048: raise ValueError("Salesforce JWT RSA keys must be at least 2048 bits") return key