/**
 * Encrypted communication channel using AES-256-GCM.
 *
 * After the handshake, both sides derive directional keys:
 *   - initiator→responder key (for messages from the MCP proxy to the remote server)
 *   - responder→initiator key (for messages from the remote server back)
 *
 * Each message is encrypted with a fresh random IV and includes:
 *   - 12-byte IV
 *   - 16-byte GCM auth tag
 *   - monotonic counter as AAD (prevents replay)
 *   - ciphertext
 *
 * Replay protection uses a sliding-window approach (similar to IPsec/DTLS):
 * messages may arrive out of order, but each counter can only be accepted once,
 * and counters that fall too far behind the highest seen are rejected.
 *
 * The shared secret from X25519 ECDH is never used directly — HKDF derives
 * separate encryption keys for each direction plus a MAC key.
 */
/** Derived session keys for one direction */
export interface DirectionalKey {
    /** AES-256-GCM encryption key (32 bytes) */
    encryptionKey: Buffer;
}
/** Full session keys for bidirectional communication */
export interface SessionKeys {
    /** Key for initiator → responder messages */
    sendKey: DirectionalKey;
    /** Key for responder → initiator messages */
    recvKey: DirectionalKey;
    /** Shared session ID for logging/correlation */
    sessionId: string;
}
/**
 * Derive bidirectional session keys from the X25519 shared secret.
 *
 * Uses HKDF-SHA256 with a role-aware info string so each direction
 * gets a unique key even from the same shared secret.
 *
 * @param sharedSecret - Raw X25519 ECDH output (32 bytes)
 * @param isInitiator - Whether this side initiated the handshake
 * @param handshakeHash - Hash of the handshake transcript (binds keys to this session)
 */
export declare function deriveSessionKeys(sharedSecret: Buffer, isInitiator: boolean, handshakeHash: Buffer): SessionKeys;
/**
 * Encrypted channel for bidirectional communication.
 *
 * Uses a sliding-window anti-replay mechanism: each message carries a
 * monotonic counter as AAD, and the receiver tracks which counters have
 * been seen. Out-of-order delivery is tolerated within the window, but
 * duplicate counters and counters that are too old are rejected.
 */
export declare class EncryptedChannel {
    private readonly keys;
    private sendCounter;
    /** Highest authenticated counter received so far (-1 = none seen yet). */
    private maxRecvCounter;
    /** Set of counters seen within the sliding window. */
    private readonly replayWindow;
    constructor(keys: SessionKeys);
    get sessionId(): string;
    /**
     * Return the underlying session keys (for handshake verification).
     */
    getKeys(): SessionKeys;
    /**
     * Encrypt a message for sending.
     *
     * @returns Buffer containing: IV (12) || authTag (16) || counter (8) || ciphertext
     */
    encrypt(plaintext: Buffer): Buffer;
    /**
     * Decrypt a received message.
     *
     * Uses a sliding-window check: counters that have already been seen or that
     * have fallen too far behind the highest authenticated counter are rejected.
     * Out-of-order delivery within the window is accepted.
     *
     * Window state is only updated **after** GCM authentication succeeds, so a
     * forged message cannot advance the window or poison the seen-set.
     *
     * @throws Error if the counter is a replay, too old, or decryption fails
     */
    decrypt(packed: Buffer): Buffer;
    /**
     * Convenience: encrypt a JSON-serializable object.
     */
    encryptJSON(obj: unknown): Buffer;
    /**
     * Convenience: decrypt and parse a JSON object.
     */
    decryptJSON<T = unknown>(packed: Buffer): T;
}
//# sourceMappingURL=channel.d.ts.map