refactor(V2): IBKR OAuth signer — type tightening + verify-based test
Code review polish: - _signature_key/_encryption_key typed as RSAPrivateKey | None - sign() uses assert instead of type: ignore - test_oauth_signer_signs_with_rsa verifies signature against public key - Clarifying comments on %3D/%26 manual encoding and Task 3 imports Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from cerbero_mcp.exchanges.ibkr.oauth import OAuth1aSigner, build_signature_base_string
|
||||
from cryptography.hazmat.primitives import serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import rsa # noqa: I001
|
||||
import base64 as _b64
|
||||
|
||||
from cerbero_mcp.exchanges.ibkr.oauth import (
|
||||
OAuth1aSigner,
|
||||
build_signature_base_string,
|
||||
)
|
||||
from cryptography.hazmat.primitives import hashes, serialization
|
||||
from cryptography.hazmat.primitives.asymmetric import padding, rsa
|
||||
|
||||
|
||||
def test_signature_base_string_canonical_order():
|
||||
@@ -58,5 +63,23 @@ def test_oauth_signer_signs_with_rsa(tmp_path):
|
||||
"oauth_version": "1.0",
|
||||
},
|
||||
)
|
||||
assert isinstance(sig, str)
|
||||
assert len(sig) > 100
|
||||
|
||||
# Verify signature against the public key — proves correctness, not just shape
|
||||
base = build_signature_base_string(
|
||||
method="GET",
|
||||
url="https://api.ibkr.com/v1/api/iserver/auth/status",
|
||||
params={
|
||||
"oauth_consumer_key": "TEST_CONSUMER",
|
||||
"oauth_token": "TEST_TOKEN",
|
||||
"oauth_nonce": "abc",
|
||||
"oauth_timestamp": "1700000000",
|
||||
"oauth_signature_method": "RSA-SHA256",
|
||||
"oauth_version": "1.0",
|
||||
},
|
||||
)
|
||||
key.public_key().verify(
|
||||
_b64.b64decode(sig),
|
||||
base.encode("utf-8"),
|
||||
padding.PKCS1v15(),
|
||||
hashes.SHA256(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user