| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- """签名金标向量与 HMAC/SHA256 守卫(任务书 P1-H)。
- 金标向量由独立实现(Node.js crypto)生成,与 C# 端 InboundSignatureHandler 同一算法:
- message = METHOD&path&accessKey×tamp&nonce&bodySha256&idempotencyKey
- signature = Base64(HMAC-SHA256(secret, message))
- """
- from __future__ import annotations
- from clients.inbound_client import InboundClient, build_message, sha256_hex, sign
- EMPTY_SHA256 = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
- GOLDEN = {
- "secret": "sim-secret-golden",
- "method": "POST",
- "path": "/api/mdp/inbound/S1_SALES_ORDER_ENTRY",
- "accessKey": "SIMKEY01",
- "timestamp": "1750000000",
- "nonce": "nonce-fixed-0001",
- "bodySha256": EMPTY_SHA256,
- "idempotencyKey": "IDEM-GOLDEN-0001",
- "signature": "caR7gxdSziU4IXI/kX4u8X11tOq0jGRmzzNHn8rEEAU=",
- }
- def test_sha256_empty_body():
- assert sha256_hex(b"") == EMPTY_SHA256
- def test_signature_golden_vector():
- message = build_message(
- GOLDEN["method"], GOLDEN["path"], GOLDEN["accessKey"], GOLDEN["timestamp"],
- GOLDEN["nonce"], GOLDEN["bodySha256"], GOLDEN["idempotencyKey"])
- assert message == (
- "POST&/api/mdp/inbound/S1_SALES_ORDER_ENTRY&SIMKEY01&1750000000"
- "&nonce-fixed-0001&" + EMPTY_SHA256 + "&IDEM-GOLDEN-0001")
- assert sign(GOLDEN["secret"], message) == GOLDEN["signature"]
- def test_signature_changes_with_secret():
- message = build_message("POST", "/api/mdp/inbound/MDM_ITEM", "K", "1", "n", EMPTY_SHA256, "I")
- assert sign("secret-a", message) != sign("secret-b", message)
- def test_request_headers_do_not_leak_signature():
- """sent_headers 中签名必须遮蔽;Secret 不出现在任何返回头。"""
- client = InboundClient("http://127.0.0.1:1", "SIMKEY01", GOLDEN["secret"])
- # 目标端口 1 必然连接失败,但 headers 在异常前已构造并返回
- status, body, headers = client.request(
- "GET", "/api/mdp/inbound/MDM_ITEM/schema", b"",
- idem=GOLDEN["idempotencyKey"], ts=int(GOLDEN["timestamp"]),
- nonce=GOLDEN["nonce"], contract_version="v2")
- assert status == 0
- assert headers["X-Signature"] == "***REDACTED***"
- assert headers["X-Access-Key"] == "SIMKEY01"
- assert headers["X-Content-SHA256"] == EMPTY_SHA256
- assert headers["X-Mdp-Contract-Version"] == "v2"
- assert GOLDEN["signature"] not in str(headers)
- for value in headers.values():
- assert GOLDEN["secret"] not in str(value)
- assert "SOURCE_UNREACHABLE" in str(body)
- def test_missing_idempotency_header_when_skipped():
- client = InboundClient("http://127.0.0.1:1", "SIMKEY01", "s")
- _, _, headers = client.request("POST", "/api/mdp/inbound/MDM_ITEM", b"{}", skip_idem=True)
- assert "Idempotency-Key" not in headers
|