🔧 When Things Break
Signal Protocol Debugging Guide
In 15 minutes: Learn how to debug Signal Protocol implementation
Prerequisites: Best Practices
🎯 Logging (Safe)
Log operations, NOT key material.
// ✅ Good: Log operations
console.log('Initialized Alice')
console.log('Performed X3DH exchange')
console.log('Encrypted message')
// ❌ Bad: Log keys
// console.log('Shared secret:', secretKey) // Don't!
// console.log('Private key:', privateKey) // Security risk!
🔍 Debugging Common Issues
Issue: cryptoReady is false
const crypto = useCryptography()
if (!crypto.cryptoReady) {
// Needs initialization
await crypto.initializeCrypto()
// Wait for WASM to load
if (!crypto.cryptoReady) {
console.error('WASM failed to load')
// Check browser console, network issues, or WASM path
}
}
Issue: Shared secrets don't match
// Debug X3DH result
const aliceResult = await crypto.performSignalX3DHKeyExchange(alice, bobKeys)
const bobResult = await crypto.performSignalX3DHKeyExchange(bob, aliceKeys)
console.log('Alice secret:', crypto.bufferToSignalHex(aliceResult.masterSecret.slice(0, 8)))
console.log('Bob secret:', crypto.bufferToSignalHex(bobResult.masterSecret.slice(0, 8)))
if (aliceResult.masterSecret !== bobResult.masterSecret) {
console.error('❌ Shared secrets DO NOT match')
console.error('Alice DH output:', aliceResult.dhOutputs)
console.error('Bob DH output:', bobResult.dhOutputs)
}
Issue: Encryption fails
try {
const encrypted = await crypto.encryptSignalMessage(alice, bob, plaintext)
if (!encrypted.ciphertext) {
throw new Error('Encryption failed: No ciphertext returned')
}
if (!encrypted.ciphertext.length) {
throw new Error('Encryption failed: Zero-length ciphertext')
}
} catch (error) {
console.error('Encryption error:', error)
// Common causes:
// 1. cryptoReady = false → Call initializeCrypto()
// 2. Invalid user objects → Check initializeSignalUser output
// 3. Missing keys → Verify getSignalPublicKeyBundle
}
📋 Error Messages Reference
| Error | Cause | Solution |
|---|---|---|
cryptoReady = false | WASM not initialized | Call crypto.initializeCrypto() |
Failed to decrypt | Wrong key or corrupted ciphertext | Verify keys match, check ciphertext integrity |
PerformX3DH failed | Invalid user or missing bundle | Check initializeSignalUser output |
Encrypt failed | Invalid plaintext or keys | Ensure correct user objects and message bytes |
WASM module failed | Network or browser issue | Check browser console, verify WASM files accessible |
💡 Debugging Tips
- Add safe logging (operations, not keys)
- Check cryptoReady before any operation
- Test X3DH returns consistent result
- Verify encryption/decryption round-trip
- Start simple: 1 message encrypted/decrypted
- Add complexity: multiple messages
🎵 When to Ask for Help
Can't determine why shared secrets don't match? Need help with WASM loading? Implementation questions?
Provide:
- Minimal code example
- Error messages (with browser console output)
- Expected vs actual behavior
- Browser info (Chrome/Firefox/Edge)
🔗 Debug Resources
- Signal Protocol Source: /cryptography/src/crypto/SignalProtocol/
- Storybook Demos: /cryptography/src/stories/SignalProtocol/
- Test Files: /cryptography/src/tests/signal-protocol*.test.js
Debugging guide complete!