#pragma once #include "chat_protocol.h" #include #include #include // HushChat compatibility-fixture / capture-manifest / seed-projection tooling. // // Everything in this header is DEAD AT RUNTIME in the shipping app and test // binaries — its only caller is the standalone dev CLI // tools/hushchat_fixture_check.cpp. It is deliberately compiled ONLY into the // HushChatFixtureCheck target so this validation scaffolding (and its libsodium // seed-projection path) never reaches the wallet binary. Keep it that way: do // not add chat_fixture_tooling.cpp to APP_SOURCES or the test target. // // It builds on the runtime types declared in chat_protocol.h. namespace dragonx::chat { enum class HushChatDecryptPreflightError { None, FeatureDisabled, NonMessageHeader, InvalidHeaderNumber, UnsupportedVersion, MissingReplyAddress, MissingConversationId, InvalidSecretstreamHeader, InvalidPublicKey, EmptyCiphertext, OversizedCiphertext, OddLengthCiphertext, InvalidCiphertextHex, TruncatedCiphertext }; struct HushChatDecryptPreflightInput { HushChatHeader header; std::string ciphertext_hex; }; struct HushChatDecryptPreflightResult { bool ok = false; bool feature_enabled = false; HushChatDecryptPreflightError error = HushChatDecryptPreflightError::None; const char* error_name = "None"; std::size_t ciphertext_size = 0; }; enum class HushChatHexDecodeError { None, Empty, OddLength, InvalidHex, UnexpectedByteLength }; struct HushChatHexDecodeResult { bool ok = false; HushChatHexDecodeError error = HushChatHexDecodeError::None; const char* error_name = "None"; std::vector bytes; }; enum class HushChatDecryptDirection { Incoming, Outgoing }; enum class HushChatSessionKeySelection { ClientRx, ServerTx }; enum class HushChatDecryptInputError { None, FeatureDisabled, InvalidStoredChatKey, DecryptPreflightFailed, InvalidPeerPublicKey, InvalidStreamHeader, InvalidCiphertext }; struct HushChatDecryptInputMaterial { std::string stored_chat_key_hex; HushChatHeader header; std::string ciphertext_hex; HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming; std::string peer_public_key_hex; }; struct HushChatPreparedDecryptInput { std::vector stored_chat_key_bytes; std::vector seed_bytes; std::vector peer_public_key_bytes; std::vector stream_header_bytes; std::vector ciphertext_bytes; HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming; HushChatSessionKeySelection session_key_selection = HushChatSessionKeySelection::ClientRx; std::size_t plaintext_capacity = 0; }; struct HushChatDecryptInputPreparationResult { bool ok = false; bool feature_enabled = false; HushChatDecryptInputError error = HushChatDecryptInputError::None; const char* error_name = "None"; HushChatHexDecodeError hex_error = HushChatHexDecodeError::None; HushChatDecryptPreflightError preflight_error = HushChatDecryptPreflightError::None; HushChatPreparedDecryptInput prepared; }; struct HushChatDecryptFixtureReadinessResult { bool ready = false; std::size_t stored_chat_key_size = 0; std::size_t seed_size = 0; std::size_t peer_public_key_size = 0; std::size_t stream_header_size = 0; std::size_t ciphertext_size = 0; std::size_t plaintext_capacity = 0; HushChatSessionKeySelection session_key_selection = HushChatSessionKeySelection::ClientRx; }; enum class HushChatCompatibilityFixtureError { None, FeatureDisabled, MissingFixtureId, InvalidLocalPublicKey, InvalidPeerPublicKey, InvalidHeaderMemo, InvalidMemoPair, NonMemoHeader, HeaderPublicKeyMismatch, DecryptInputFailed, NotFixtureReady, ExpectedStoredChatKeyLengthMismatch, ExpectedSeedLengthMismatch, ExpectedLocalPublicKeyLengthMismatch, ExpectedPeerPublicKeyLengthMismatch, ExpectedStreamHeaderLengthMismatch, ExpectedCiphertextLengthMismatch, ExpectedPlaintextLengthMismatch, ExpectedRoleMismatch, InvalidPlaintextHash }; struct HushChatCompatibilityFixture { std::string fixture_id; std::string stored_chat_key_hex; std::string local_public_key_hex; std::string peer_public_key_hex; std::string header_memo; std::string ciphertext_memo; HushChatDecryptDirection direction = HushChatDecryptDirection::Incoming; HushChatSessionKeySelection expected_session_key_selection = HushChatSessionKeySelection::ClientRx; std::size_t expected_stored_chat_key_size = 32; std::size_t expected_seed_size = 32; std::size_t expected_local_public_key_size = 32; std::size_t expected_peer_public_key_size = 32; std::size_t expected_stream_header_size = 24; std::size_t expected_ciphertext_size = 0; std::size_t expected_plaintext_size = 0; std::string expected_plaintext_hash_hex; }; struct HushChatCompatibilityFixtureVerificationResult { bool ok = false; bool feature_enabled = false; HushChatCompatibilityFixtureError error = HushChatCompatibilityFixtureError::None; const char* error_name = "None"; HushChatHexDecodeError hex_error = HushChatHexDecodeError::None; HushChatDecryptInputError decrypt_input_error = HushChatDecryptInputError::None; HushChatDecryptPreflightError preflight_error = HushChatDecryptPreflightError::None; HushChatHeader header; HushChatDecryptInputPreparationResult preparation; HushChatDecryptFixtureReadinessResult readiness; std::size_t local_public_key_size = 0; std::size_t peer_public_key_size = 0; std::size_t plaintext_hash_size = 0; }; enum class HushChatCompatibilityFixtureKind { IncomingMemo, OutgoingMemo, SeedPublicKeyProjection, CorruptedAuthFailure, ContactExclusion }; enum class HushChatCompatibilityFixtureFileStatus { Pending, Ready }; enum class HushChatCompatibilityFixtureFileError { None, FeatureDisabled, InvalidJson, JsonNotObject, InvalidSchema, MissingKind, UnknownKind, MissingStatus, UnknownStatus, MissingFixtureId, MissingPendingReason, MissingFixtureObject, InvalidFixtureField, FixtureVerificationFailed, ContactFixtureNotExcluded, FileReadFailed }; struct HushChatCompatibilityFixtureFile { std::string schema; HushChatCompatibilityFixtureKind kind = HushChatCompatibilityFixtureKind::IncomingMemo; HushChatCompatibilityFixtureFileStatus status = HushChatCompatibilityFixtureFileStatus::Pending; std::string fixture_id; std::string pending_reason; HushChatCompatibilityFixture fixture; }; struct HushChatCompatibilityFixtureFileParseResult { bool ok = false; bool feature_enabled = false; bool pending = false; bool verified = false; bool excluded_from_decrypt = false; HushChatCompatibilityFixtureFileError error = HushChatCompatibilityFixtureFileError::None; const char* error_name = "None"; HushChatCompatibilityFixtureFile file; HushChatCompatibilityFixtureVerificationResult verification; }; enum class HushChatSeedPublicKeyProjectionError { None, FeatureDisabled, MissingFixtureId, InvalidStoredChatKey, InvalidLocalPublicKey, ExpectedStoredChatKeyLengthMismatch, ExpectedSeedLengthMismatch, ExpectedLocalPublicKeyLengthMismatch, SodiumInitializationFailed, KeypairProjectionFailed, ProjectedPublicKeyMismatch }; struct HushChatSeedPublicKeyProjectionResult { bool ok = false; bool feature_enabled = false; HushChatSeedPublicKeyProjectionError error = HushChatSeedPublicKeyProjectionError::None; const char* error_name = "None"; HushChatHexDecodeError hex_error = HushChatHexDecodeError::None; std::size_t stored_chat_key_size = 0; std::size_t seed_size = 0; std::size_t local_public_key_size = 0; std::size_t projected_public_key_size = 0; }; enum class HushChatCorruptedAuthFailureReadinessError { None, FeatureDisabled, FixturePending, WrongFixtureKind, FixtureNotVerified, SeedProjectionNotVerified }; struct HushChatCorruptedAuthFailureReadinessResult { bool ok = false; bool feature_enabled = false; bool structurally_ready_for_future_auth_check = false; bool requires_future_secretstream_auth_failure = false; bool decrypted = false; bool authenticated = false; HushChatCorruptedAuthFailureReadinessError error = HushChatCorruptedAuthFailureReadinessError::None; const char* error_name = "None"; }; enum class HushChatCompatibilityFixtureImportError { None, FeatureDisabled, MissingRequiredKind, DuplicateKind, FixtureLoadFailed, FixtureKindMismatch, FixturePending, FixtureInvalid, FixtureNotVerified, SeedProjectionFailed, AuthFailureScaffoldFailed, ContactFixtureNotExcluded }; struct HushChatCompatibilityFixtureImportCandidate { HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo; std::string path; }; struct HushChatCompatibilityFixtureImportItem { HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo; HushChatCompatibilityFixtureKind loaded_kind = HushChatCompatibilityFixtureKind::IncomingMemo; std::string path; bool supplied = false; bool pending = false; bool replacement_eligible = false; bool seed_projection_verified = false; bool future_auth_failure_required = false; bool structurally_ready_for_future_auth_check = false; HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None; const char* error_name = "None"; HushChatCompatibilityFixtureFileParseResult parsed; HushChatSeedPublicKeyProjectionResult seed_projection; HushChatCorruptedAuthFailureReadinessResult auth_failure_readiness; }; struct HushChatCompatibilityFixtureImportChecklistResult { bool ok = false; bool feature_enabled = false; bool replacement_ready = false; HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None; const char* error_name = "None"; std::size_t required_count = 0; std::size_t supplied_count = 0; std::size_t missing_count = 0; std::size_t pending_count = 0; std::size_t verified_count = 0; std::size_t seed_projection_verified_count = 0; std::size_t future_auth_failure_required_count = 0; std::size_t auth_failure_structural_ready_count = 0; std::size_t excluded_count = 0; std::size_t rejected_count = 0; std::vector items; }; struct HushChatCompatibilityFixtureReplacementReportItem { HushChatCompatibilityFixtureKind expected_kind = HushChatCompatibilityFixtureKind::IncomingMemo; HushChatCompatibilityFixtureKind loaded_kind = HushChatCompatibilityFixtureKind::IncomingMemo; std::string path; bool supplied = false; bool pending = false; bool replacement_eligible = false; bool refused = true; bool seed_projection_verified = false; bool future_auth_failure_required = false; bool structurally_ready_for_future_auth_check = false; bool cont_excluded = false; bool decrypted = false; bool authenticated = false; HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None; const char* error_name = "None"; }; struct HushChatCompatibilityFixtureReplacementDryRunResult { bool ok = false; bool feature_enabled = false; bool dry_run_only = true; bool redacted_report = true; bool would_replace = false; bool replacement_refused = true; HushChatCompatibilityFixtureImportError error = HushChatCompatibilityFixtureImportError::None; const char* error_name = "None"; std::size_t required_count = 0; std::size_t supplied_count = 0; std::size_t missing_count = 0; std::size_t pending_count = 0; std::size_t verified_count = 0; std::size_t seed_projection_verified_count = 0; std::size_t future_auth_failure_required_count = 0; std::size_t auth_failure_structural_ready_count = 0; std::size_t excluded_count = 0; std::size_t rejected_count = 0; std::vector report_items; }; enum class HushChatCaptureManifestError { None, FeatureDisabled, FileReadFailed, InvalidJson, JsonNotObject, InvalidSchema, MissingManifestId, MissingStatus, UnknownStatus, MissingFixtureDirectory, MissingDryRunCommand, InvalidDryRunCommand, MissingProvenance, MissingSourceClient, InvalidSourceClient, MissingSourceClientVersion, MissingCaptureDate, MissingNetwork, MissingCaptureMethod, MissingHandling, MissingHandlingFlag, HandlingFlagNotTrue, MissingCategories, InvalidCategoryEntry, UnknownCategory, DuplicateCategory, MissingRequiredCategory, ProhibitedFieldPresent }; enum class HushChatCaptureManifestStatus { Staged }; struct HushChatCaptureManifestCategoryReport { HushChatCompatibilityFixtureKind kind = HushChatCompatibilityFixtureKind::IncomingMemo; std::string staged_filename; bool declared = false; }; struct HushChatCaptureManifestValidationResult { bool ok = false; bool feature_enabled = false; bool redacted_report = true; bool validates_provenance_only = true; bool no_sensitive_material_declared = false; bool has_dry_run_command = false; HushChatCaptureManifestError error = HushChatCaptureManifestError::None; const char* error_name = "None"; HushChatCaptureManifestStatus status = HushChatCaptureManifestStatus::Staged; std::string manifest_path; std::string fixture_directory; std::size_t required_count = 0; std::size_t declared_count = 0; std::size_t missing_count = 0; std::size_t duplicate_count = 0; std::size_t prohibited_field_count = 0; std::size_t handling_flag_count = 0; std::vector categories; }; constexpr std::size_t kHushChatSecretstreamABytes = 17; constexpr std::size_t kHushChatStoredChatKeyByteLength = 32; constexpr std::size_t kHushChatStoredChatKeyHexLength = kHushChatStoredChatKeyByteLength * 2; constexpr std::size_t kHushChatSeedByteLength = 32; constexpr std::size_t kHushChatPublicKeyByteLength = kHushChatPublicKeyHexLength / 2; constexpr std::size_t kHushChatSecretstreamHeaderByteLength = kHushChatSecretstreamHeaderHexLength / 2; constexpr const char* kHushChatCompatibilityFixtureSchema = "dragonx.hushchat.compat-fixture.v1"; constexpr const char* kHushChatCaptureManifestSchema = "dragonx.hushchat.capture-manifest.v1"; HushChatDecryptPreflightResult validateHushChatMemoDecryptPreflight( const HushChatDecryptPreflightInput& input, bool featureEnabled = hushChatFeatureEnabledAtBuild()); HushChatHexDecodeResult decodeHushChatHexBytes(const std::string& hex, std::size_t expectedByteLength); HushChatDecryptInputPreparationResult prepareHushChatDecryptInput( const HushChatDecryptInputMaterial& material, bool featureEnabled = hushChatFeatureEnabledAtBuild()); HushChatDecryptFixtureReadinessResult inspectHushChatDecryptFixtureReadiness( const HushChatPreparedDecryptInput& prepared); HushChatSessionKeySelection hushChatSessionKeySelectionForDirection(HushChatDecryptDirection direction); HushChatCompatibilityFixtureVerificationResult verifyHushChatCompatibilityFixture( const HushChatCompatibilityFixture& fixture, bool featureEnabled = hushChatFeatureEnabledAtBuild()); HushChatCompatibilityFixtureFileParseResult parseHushChatCompatibilityFixtureFile( const std::string& jsonText, bool featureEnabled = hushChatFeatureEnabledAtBuild()); HushChatCompatibilityFixtureFileParseResult loadHushChatCompatibilityFixtureFile( const std::string& path, bool featureEnabled = hushChatFeatureEnabledAtBuild()); HushChatSeedPublicKeyProjectionResult verifyHushChatSeedPublicKeyProjection( const HushChatCompatibilityFixture& fixture, bool featureEnabled = hushChatFeatureEnabledAtBuild()); HushChatCorruptedAuthFailureReadinessResult inspectHushChatCorruptedAuthFailureReadiness( const HushChatCompatibilityFixtureFileParseResult& parsed, const HushChatSeedPublicKeyProjectionResult& seedProjection, bool featureEnabled = hushChatFeatureEnabledAtBuild()); std::vector hushChatRequiredCompatibilityFixtureKinds(); HushChatCompatibilityFixtureImportChecklistResult inspectHushChatCompatibilityFixtureImportChecklist( const std::vector& candidates, bool featureEnabled = hushChatFeatureEnabledAtBuild()); HushChatCompatibilityFixtureReplacementDryRunResult inspectHushChatCompatibilityFixtureReplacementDryRun( const std::vector& candidates, bool featureEnabled = hushChatFeatureEnabledAtBuild()); HushChatCaptureManifestValidationResult validateHushChatCaptureManifest( const std::string& jsonText, bool featureEnabled = hushChatFeatureEnabledAtBuild()); HushChatCaptureManifestValidationResult loadHushChatCaptureManifestFile( const std::string& path, bool featureEnabled = hushChatFeatureEnabledAtBuild()); const char* hushChatDecryptPreflightErrorName(HushChatDecryptPreflightError error); const char* hushChatHexDecodeErrorName(HushChatHexDecodeError error); const char* hushChatDecryptDirectionName(HushChatDecryptDirection direction); const char* hushChatSessionKeySelectionName(HushChatSessionKeySelection selection); const char* hushChatDecryptInputErrorName(HushChatDecryptInputError error); const char* hushChatCompatibilityFixtureErrorName(HushChatCompatibilityFixtureError error); const char* hushChatCompatibilityFixtureKindName(HushChatCompatibilityFixtureKind kind); const char* hushChatCompatibilityFixtureFileStatusName(HushChatCompatibilityFixtureFileStatus status); const char* hushChatCompatibilityFixtureFileErrorName(HushChatCompatibilityFixtureFileError error); const char* hushChatSeedPublicKeyProjectionErrorName(HushChatSeedPublicKeyProjectionError error); const char* hushChatCorruptedAuthFailureReadinessErrorName(HushChatCorruptedAuthFailureReadinessError error); const char* hushChatCompatibilityFixtureImportErrorName(HushChatCompatibilityFixtureImportError error); const char* hushChatCaptureManifestErrorName(HushChatCaptureManifestError error); } // namespace dragonx::chat