feat(grpc-events): ExchangeKey ECDH (Path B) — clears the v8 client-key check
Implements HistoryService.ExchangeKey as a pure-managed P-256 ECDH key exchange and wires it ahead of the v8 Event OpenConnection. - HistorianNativeHandshake.BuildExchangeKeyClientHello / DeriveExchangeKeySecret: .NET ECDiffieHellman (nistP256); wire format "ECK1" + u32(32) + X(32) + Y(32), decoded from the live capture. No native AVEVA dependency. - HistorianGrpcHandshake.OpenSession(eventConnection: true): runs ExchangeKey on the context-key handle before the v8 OpenConnection. - Guardrail HistorianGrpcHandshakeRoutingTests scoped to the token-loop closure: still pins that the Negotiate token loop routes to ValidateClientCredential (not ExchangeKey), while allowing the legitimate ExchangeKey call in OpenSession. Live result: ExchangeKey succeeds (server accepts our public key) and the v8 OpenConnection error advances from 132/34 "Failed to get client key" to 132/171 AuthenticationFailed — the ECDH cleared the client-key layer. The remaining blocker is the 26-byte v8 credential token, which must be derived from the ECDH shared secret (token KDF, not yet recovered). Orchestrator stays on v6 (set eventConnection: true to re-arm once the KDF lands). 323/323 offline. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01B6mcaT2PjRFKcogzp9UkfC
This commit is contained in:
@@ -138,11 +138,12 @@ internal sealed class HistorianGrpcEventOrchestrator
|
||||
private List<HistorianEvent> RunEventChain(DateTime startUtc, DateTime endUtc, HistorianEventFilter? filter, CancellationToken cancellationToken)
|
||||
{
|
||||
using HistorianGrpcConnection connection = HistorianGrpcChannelFactory.Create(_options);
|
||||
// NOTE: the event read needs an Event-type (v8) connection, but the v8 OpenConnection is
|
||||
// server-coupled to HistoryService.ExchangeKey (ECDH) — it rejects a v8 open made on our
|
||||
// ValidateClientCredential session with native 132/34 "EstablishConnection Failed to get client
|
||||
// key" (Path A, disproven 2026-06-23). Staying on the v6 session until ExchangeKey is
|
||||
// implemented (Path B). The v8 serializer + BuildEventOpenConnectionVersion8Request are ready.
|
||||
// Event reads need an Event-type (v8) connection. Path B established the v8 ExchangeKey (ECDH)
|
||||
// client key — which cleared the "Failed to get client key" check — but the v8 OpenConnection
|
||||
// then fails at native 132/171 AuthenticationFailed: the 26-byte credential token must be derived
|
||||
// from the ECDH shared secret (the token-KDF is not yet reverse-engineered). Staying on the v6
|
||||
// session until that derivation lands; the ExchangeKey + v8 serializer are ready (set
|
||||
// eventConnection: true to re-arm). See docs/reverse-engineering/grpc-event-query-capture.md.
|
||||
HistorianGrpcHandshake.Session session = HistorianGrpcHandshake.OpenSession(connection, _options, cancellationToken);
|
||||
|
||||
RegisterCmEventTag(connection, session, cancellationToken);
|
||||
|
||||
Reference in New Issue
Block a user