feat: implement identity key change detection for Signal protocol

This implements the functionality from WhiskeySockets/Baileys PR #2307
with enhanced improvements:

## Core Features
- Extract identity key from PreKeyWhisperMessage before decryption
- Detect when a contact reinstalls WhatsApp (identity key changes)
- Automatically delete old session and recreate on identity change
- Trust On First Use (TOFU) for new contacts

## Improvements over original PR
- LRU cache for identity keys (1000 keys, 30min TTL)
- Integration with existing Circuit Breaker (reset on identity change)
- New Prometheus metrics for observability:
  - signal_identity_changes_total (new/changed)
  - signal_mac_errors_total
  - signal_session_recreations_total
  - signal_identity_key_cache_hits/misses
  - signal_identity_key_operations_ms (histogram)
- New 'identity.changed' event for applications to notify users
- RetryReason enum with MAC_ERROR_CODES and SESSION_ERROR_CODES
- Robust protobuf parsing with validation
- Structured logging with fingerprints

## Technical Details
- Manual protobuf parsing (compatible with any Signal implementation)
- SHA-256 fingerprints for key identification
- Atomic session deletion + identity key save
- Best-effort identity tracking (doesn't fail decryption on errors)

Resolves permanent MAC errors when contacts reinstall WhatsApp.

https://claude.ai/code/session_01SWAcNuGZQmEKyBPYkBhVHg
This commit is contained in:
Claude
2026-01-30 03:35:18 +00:00
parent 228ea998bd
commit 164c7fbe93
5 changed files with 654 additions and 15 deletions
+2
View File
@@ -81,6 +81,8 @@ export type SignalDataTypeMap = {
'lid-mapping': string
'device-list': string[]
tctoken: { token: Buffer; timestamp?: string }
/** Identity key for Signal Protocol - used for detecting contact reinstalls */
'identity-key': Uint8Array
}
export type SignalDataSet = { [T in keyof SignalDataTypeMap]?: { [id: string]: SignalDataTypeMap[T] | null } }