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:
@@ -1601,6 +1601,35 @@ export const metrics = {
|
||||
new Gauge('prekey_count', 'Current prekey count')
|
||||
),
|
||||
|
||||
// ========== Signal Identity Metrics ==========
|
||||
/** Total identity key changes detected (contact reinstalled WhatsApp) */
|
||||
signalIdentityChanges: baileysMetrics.register(
|
||||
new Counter('signal_identity_changes_total', 'Total identity key changes detected', ['type'])
|
||||
),
|
||||
/** Total Signal MAC errors encountered */
|
||||
signalMacErrors: baileysMetrics.register(
|
||||
new Counter('signal_mac_errors_total', 'Total Signal MAC verification errors', ['action'])
|
||||
),
|
||||
/** Total Signal session recreations by reason */
|
||||
signalSessionRecreations: baileysMetrics.register(
|
||||
new Counter('signal_session_recreations_total', 'Total Signal session recreations', ['reason'])
|
||||
),
|
||||
/** Identity key cache statistics */
|
||||
signalIdentityKeyCacheHits: baileysMetrics.register(
|
||||
new Counter('signal_identity_key_cache_hits_total', 'Total identity key cache hits')
|
||||
),
|
||||
signalIdentityKeyCacheMisses: baileysMetrics.register(
|
||||
new Counter('signal_identity_key_cache_misses_total', 'Total identity key cache misses')
|
||||
),
|
||||
/** Identity key operations latency */
|
||||
signalIdentityKeyOperations: baileysMetrics.register(
|
||||
new Histogram('signal_identity_key_operations_ms', 'Identity key operation latency in ms', ['operation'], [1, 5, 10, 25, 50, 100])
|
||||
),
|
||||
/** Current identity key cache size */
|
||||
signalIdentityKeyCacheSize: baileysMetrics.register(
|
||||
new Gauge('signal_identity_key_cache_size', 'Current identity key cache size')
|
||||
),
|
||||
|
||||
// ========== Cache Metrics ==========
|
||||
cacheHits: baileysMetrics.register(
|
||||
new Counter('cache_hits_total', 'Total cache hits', ['cache'])
|
||||
|
||||
Reference in New Issue
Block a user