Skip to main content

🔧 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

ErrorCauseSolution
cryptoReady = falseWASM not initializedCall crypto.initializeCrypto()
Failed to decryptWrong key or corrupted ciphertextVerify keys match, check ciphertext integrity
PerformX3DH failedInvalid user or missing bundleCheck initializeSignalUser output
Encrypt failedInvalid plaintext or keysEnsure correct user objects and message bytes
WASM module failedNetwork or browser issueCheck browser console, verify WASM files accessible

💡 Debugging Tips

  1. Add safe logging (operations, not keys)
  2. Check cryptoReady before any operation
  3. Test X3DH returns consistent result
  4. Verify encryption/decryption round-trip
  5. Start simple: 1 message encrypted/decrypted
  6. 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!