{"record":{"id":"e5b89946f0b4de07","repo":"BerriAI/litellm","slug":"the-provided-private-key-is-not-an-rsa-key-which","errorCode":null,"errorMessage":"The provided private key is not an RSA key, which is required for OCI signing.","messagePattern":"The provided private key is not an RSA key, which is required for OCI signing\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"critical","filePath":"litellm/llms/oci/common_utils.py","lineNumber":123,"sourceCode":"def build_signature_string(method: str, path: str, headers: dict, signed_headers: list) -> str:\n    lines: Final = []\n    for header in signed_headers:\n        if header == \"(request-target)\":\n            value = f\"{method.lower()} {path}\"\n        else:\n            value = headers[header]\n        lines.append(f\"{header}: {value}\")\n    return \"\\n\".join(lines)\n\n\ndef load_private_key_from_str(key_str: str) -> Any:\n    _require_cryptography()\n    key: Final = serialization.load_pem_private_key(\n        key_str.encode(\"utf-8\"),\n        password=None,\n    )\n    if not isinstance(key, rsa.RSAPrivateKey):\n        raise TypeError(\"The provided private key is not an RSA key, which is required for OCI signing.\")\n    return key\n\n\ndef load_private_key_from_file(file_path: str) -> Any:\n    \"\"\"Loads a private key from a file path.\"\"\"\n    try:\n        with open(file_path, \"r\", encoding=\"utf-8\") as f:\n            key_str: Final = f.read().strip()\n    except FileNotFoundError:\n        raise FileNotFoundError(f\"Private key file not found: {file_path}\")\n    except OSError as e:\n        raise OSError(f\"Failed to read private key file '{file_path}': {e}\") from e\n\n    if not key_str:\n        raise ValueError(f\"Private key file is empty: {file_path}\")\n\n    return load_private_key_from_str(key_str)\n","sourceCodeStart":105,"sourceCodeEnd":141,"githubUrl":"https://github.com/BerriAI/litellm/blob/6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d/litellm/llms/oci/common_utils.py#L105-L141","documentation":"load_private_key_from_str loads the PEM private key and enforces that it is an RSA key, because OCI request signing uses RSA PKCS1v15 + SHA256. An EC/Ed25519 key parses fine but cannot produce a valid OCI signature, so it is rejected immediately with TypeError instead of producing cryptic 401s.","triggerScenarios":"The OCI_USER's API key was generated as ECDSA or Ed25519 instead of RSA-2048+, or the wrong key file (e.g. an SSH ed25519 key) was pointed at by OCI_KEY_FILE / oci_key_file.","commonSituations":"Developers reusing ~/.ssh/id_ed25519; OpenSSL defaults drifting to EC keys (openssl genpkey -algorithm EC); keys generated for a different cloud provider; copying an OCI config file whose key_file path points at an EC key generated later.","solutions":["Generate an RSA key: openssl genrsa -out oci_key.pem 2048 (or ssh-keygen -t RSA -b 2048 -m PEM).","Upload the new public key in the OCI Console (Identity > Users > API Keys) and copy the new fingerprint into OCI_FINGERPRINT.","Point oci_key_file / OCI_KEY_FILE at the RSA PEM file.","Verify: openssl rsa -in oci_key.pem -check -noout succeeds only for RSA keys."],"exampleFix":"# before (ed25519/EC key → TypeError)\n# key generated with: ssh-keygen -t ed25519\n\n# after\n# openssl genrsa -out ~/.oci/oci_key.pem 2048\n# upload public key in OCI Console, update fingerprint\nlitellm.completion(model=\"oci/...\", messages=m)  # signs successfully","handlingStrategy":"validation","validationCode":"from cryptography.hazmat.primitives import serialization\nkey = serialization.load_pem_private_key(pem.encode(), password=None)\nfrom cryptography.hazmat.primitives.asymmetric import rsa\nassert isinstance(key, rsa.RSAPrivateKey), \"OCI requires an RSA private key\"","typeGuard":"from cryptography.hazmat.primitives.asymmetric import rsa\n\ndef is_rsa_key(key) -> bool:\n    return isinstance(key, rsa.RSAPrivateKey)","tryCatchPattern":"try:\n    litellm.completion(model=\"oci/...\", messages=m)\nexcept TypeError as e:\n    if \"not an RSA key\" in str(e):\n        raise ConfigError(\"Regenerate key: openssl genrsa -out oci_key.pem 2048 and re-upload\") from e\n    raise","preventionTips":["Standardize key generation: openssl genrsa -out oci_key.pem 2048.","Re-verify the key type after any key rotation or provider migration.","Add a startup check that the configured key parses as RSA."],"tags":["oci","authentication","rsa","crypto","credentials"],"backgroundTag":null,"analyzedSha":"6c2dcb801bf2b75c18f1bb24140e7cf57465cc4d","analyzedAt":"2026-08-15T07:12:03.035Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}